Developer Guide
Dependencies
BOLDQC is built upon FSL, dcm2niix, and a custom Python-based NIfTI quality assessment library. The container is based on Rocky Linux.
| Package | Version | Download |
|---|---|---|
| Rocky Linux | 8 |
|
| FSL | 6.0.4 |
|
| dcm2niix | v1.0.20260724 |
Pipeline overview
The BOLDQC pipeline consists of two main processing tasks: niftiqa_wrapper
and stackcheck_ext. Together, these tasks produce signal quality metrics,
motion estimates, and snapshot images for a single BOLD fMRI run.
niftiqa_wrapper
The niftiqa_wrapper.py script is a Python-based quality assessment tool that
computes voxel-wise statistics from a 4D BOLD NIfTI image. It produces derived
3D volumes (mean, standard deviation, SNR, slope, and mask) and generates
mosaic thumbnail images using FSL's slicer command.
niftiqa.py
The core niftiqa.py script loads the 4D NIfTI image, discards an initial
number of volumes (skip), applies an intensity-based mask, and computes the
following derived volumes:
- Mean — temporal mean of the time series
- StDev — temporal standard deviation (ddof=1)
- SNR — voxel-wise signal-to-noise ratio (mean / stdev)
- Slope — linear regression slope across time points per voxel
- Mask — binary volume based on mean intensity threshold
It also generates a per-slice mean intensity report and a mean slice intensity plot.
niftiqa.py --skip 4 --mask-threshold ${MASK_THRESHOLD} --mean-slice-plot-format png --all --output-dir ${OUTPUT_DIR} ${NIFTI}
slicer
After niftiqa.py completes, mosaic thumbnail images are generated for each
derived 3D volume using FSL's slicer command
slicer ${INPUT_NIFTI} -u -S ${NTH_VOX} ${X_WIDTH} ${OUTPUT_PNG}
stackcheck_ext
The stackcheck_ext.sh script performs orientation correction, signal quality
analysis, and motion estimation on a BOLD fMRI NIfTI image. It depends heavily
on FSL tools.
fslorient
Checks and enforces image orientation. If the image is in NEUROLOGICAL orientation, it is flipped to RADIOLOGICAL
fslorient -getorient ${NIFTI}
fslorient -swaporient ${NIFTI}
fslswapdim
Enforces LPI (Left-Posterior-Inferior) voxel dimensions on the input image
fslswapdim ${NIFTI} RL PA IS ${NIFTI}
stackcheck_nifti
Runs the core signal quality analysis, computing mean, mask, standard deviation, and SNR volumes, along with a per-slice report
stackcheck_nifti --threshold ${THRESH} --skip ${SKIP} --report --mean --mask --stdev --snr --plot --input ${NIFTI} --output-basename ${OUTDIR}/${BASE}
mcflirt
Performs motion correction using FSL's mcflirt. Outputs rotation and
translation parameters, transformation matrices, and RMS displacement files
(both relative and absolute)
mcflirt -in ${NIFTI} -report -plots -mats -rmsrel -rmsabs -refvol 0 -out ${OUTDIR}/moco
Motion parameter extraction
After mcflirt completes, motion parameters are extracted from the .par file
and reformatted into three data files:
| File | Description |
|---|---|
${BASE}.dat |
Absolute displacement (reordered columns from moco.par) |
${BASE}.rdat |
Mean-centered displacement |
${BASE}.ddat |
Frame-to-frame relative displacement |
These data files are then used to compute summary motion statistics (mean, standard deviation, maximum) for translations and rotations in each axis, as well as counts of movements exceeding 0.1mm and 0.5mm thresholds.
fslmeants
Calculates mean masked signal values for the derived volumes using FSL's
fslmeants
fslmeants -i ${OUTDIR}/${BASE}_snr.nii -m ${OUTDIR}/${BASE}_mask.nii
fslmeants -i ${OUTDIR}/${BASE}_stdev.nii -m ${OUTDIR}/${BASE}_mask.nii
fslmeants -i ${OUTDIR}/${BASE}_mean.nii -m ${OUTDIR}/${BASE}_mask.nii
fslmeants -i ${OUTDIR}/${BASE}_slope.nii -m ${OUTDIR}/${BASE}_mask.nii
Motion and mean slice plots
Motion parameters and mean slice intensity data are plotted using matplotlib
# Motion plot: rotations (pitch, roll, yaw) and translations (x, y, z)
${OUTDIR}/${BASE}_motion.png
# Mean slice intensity plot
${OUTDIR}/${BASE}_meanSlice.png
Auto report
A comprehensive text report (${BASE}_autoReport.txt) is generated containing
all computed QC metrics, motion statistics, and processing provenance.
Mask threshold
The mask threshold is automatically determined based on the DICOM metadata
fields BitsStored and ReceiveCoilName:
| Bits Stored | Receive Coil | Threshold |
|---|---|---|
| any | HeadNeck_20 |
3000.0 |
| 12 | any | 150.0 |
| 16 | Head_32 |
1500.0 |
| 16 | Head_64/HeadNeck_64 |
3000.0 |