Software listed are non-exhaustive.
I(T(v)) \approx R(v)
Least squares (images have the same scale) C\{ R(v), I(T(v))\} = \int_{v \subset \mathbb{R}^3} \{ I(T(v)) - R(v)\}^2 dv
Correlation (images on different scales)
Mutual information (images with different contrasts/distributions) \mathrm{MI}(R, I) = \sum_{r,i} \mathbb{P}_{RI}(r, i) \log \left( \frac{\mathbb{P}_{RI}(r, i)}{\mathbb{P}_R(r), \mathbb{P}_I(i)} \right)
where \mathbb{P}_{RI}(r, i): is the joint probability, and \mathbb{P}_R(r), \mathbb{P}_I(i) are the marginal probabilities
\begin{bmatrix} y_1 \\ y_2 \\ y_3\\ 1 \end{bmatrix} = T_4 T_3 T_2 T_1 \cdot \begin{bmatrix} x_1 \\ x_2 \\ x_3\\ 1 \end{bmatrix}
Translation of image T_4 = \begin{bmatrix} 1 & 0 & 0 & q_1 \\ 0 & 1 & 0 & q_2 \\ 0 & 0 & 1 & q_3\\ 0 & 0 & 0 & 1 \end{bmatrix}
Rotation around the x-axis:
T_1 = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos(q_4) & \sin(q_4) & 0 \\ 0 & -\sin(q_4) & \cos(q_4) & 0\\ 0 & 0 & 0 & 1 \end{bmatrix}
Other rotations are defined similarly. See the reference above.
Commands I ran:
fast -B images/simon_bc.nii.gz images/simon.nii.gz
bet images/simon_bc.nii.gz images/simonReg/simon_brain.nii.gz
# dof controls number of parameters 6 is rigid-body
flirt -in images/simonReg/simon_brain.nii.gz -ref images/MNI152_T1_1mm_brain.nii.gz -dof 6 -o images/simonReg/simon_brain_rigidReg.nii.gz -omat images/simonReg/rigidReg.txt
# defaults to 12 for affine transformation
flirt -in images/simonReg/simon_brain.nii.gz -ref images/MNI152_T1_1mm_brain.nii.gz -o images/simonReg/simon_brain_affineReg.nii.gz -omat images/simonReg/affineReg.txtTo view the results with the MNI template
To view transformation matrices
Visualize results
HO_simon.nii.gz
MNI2simon.nii.gz
affineReg.txt
field.nii.gz
jacobian.nii.gz
rigidReg.txt
simon2MNI.nii.gz
simon_bet.nii.gz
simon_brain.nii.gz
simon_brain_affineReg.nii.gz
simon_brain_mixeltype.nii.gz
simon_brain_pve_0.nii.gz
simon_brain_pve_1.nii.gz
simon_brain_pve_2.nii.gz
simon_brain_pveseg.nii.gz
simon_brain_rigidReg.nii.gz
simon_brain_seg.nii.gz
simon_brain_to_MNI152_T1_1mm_brain.log
simon_brain_warpcoef.nii.gz
simon_nonlinearReg.nii.gz
A relatively simple processing step
Smoothing kernels CPAC pipeline
Anatomical pipeline
Option/Alt + click to zoom in.
# output from fsl_anat.
# Base image is the input data.
# Second image is the segmentation output
fsleyes data/RBC/HBN_BIDS/sub-NDARAA306NT2/ses-HBNsiteRU/anat/sub-NDARAA306NT2_ses-HBNsiteRU_acq-HCP_T1w.anat/T1.nii.gz data/RBC/HBN_BIDS/sub-NDARAA306NT2/ses-HBNsiteRU/anat/sub-NDARAA306NT2_ses-HBNsiteRU_acq-HCP_T1w.anat/T1_fast_pveseg.nii.gzEstimation of volumes of regions defined from an anatomical atlas.
Approaches:
# invert the warp from subject space to template space
invwarp -w images/simonReg/simon2MNI.nii.gz -o images/simonReg/MNI2simon.nii.gz -r images/simonReg/simon_brain.nii.gz
# convert atlas to subject space. Use nearest neighbor interpolation
applywarp --i=/Users/vandeks/fsl/data/atlases/HarvardOxford/HarvardOxford-cort-maxprob-thr25-1mm.nii.gz --ref=images/simonReg/simon_brain.nii.gz --warp=images/simonReg/MNI2simon.nii.gz --out=images/simonReg/HO_simon.nii.gz --interp=nn
# visualize results on simon's brain
fsleyes images/simonReg/simon_brain.nii.gz images/simonReg/HO_simon.nii.gzCode from ChatGPT to compute volumes.
# 2. Estimate voxel volume (assumes cubic mm)
voxel_volume=$(fslval ${ref_image} pixdim1)
voxel_volume=$(echo "${voxel_volume} * $(fslval ${ref_image} pixdim2) * $(fslval ${ref_image} pixdim3)" | bc -l)
# 3. Loop over atlas labels to count voxels and estimate volume
echo "Label,VoxelCount,Volume_mm3"
for label in {1..48}; do
count=$(fslstats ${atlas_subj} -l $(($label - 1)) -u $label -V | awk '{print $1}')
volume=$(echo "$count * $voxel_volume" | bc -l)
echo "$label,$count,$volume"
doneFreesurfer is among the most popular software for cortical surface reconstruction

Functional pipeline
Motion parameters from Despicable Me
How the DCT cutoff works
FEAT asks you for a high-pass filter cutoff (in seconds), e.g. 100s.
This is the minimum period length that will be modeled as noise.
All fluctuations slower than this period (i.e., longer trends) are captured by the DCT regressors and removed.
Faster fluctuations (shorter than this period) remain in the data/GLM.
Implementation: a set of cosine basis functions with periods ≥ cutoff are generated, spaced to cover the run length.
Rule of thumb in FSL: 2 × the longest inter-stimulus interval (ISI) / block length in your design.
Simon: Needs to be longer than the longest block length
Rationale: you want to preserve your task regressors of interest, but still remove very slow scanner drift.
FSL uses a Discrete Cosine Transform (DCT, Type II) basis set to model slow drifts.
If you have a run of length T seconds (N volumes × TR), then for each time point t = 0, 1, \dots, N-1:
X_{k}(t) \;=\; \cos\!\Bigg( \frac{\pi (t+0.5)k}{N} \Bigg), \quad k=0,1,\dots,N-1
This is the standard DCT-II form. Each k corresponds to a different frequency (periodicity).
Mapping cutoff to maximum period
The cutoff you choose in FEAT (e.g., 100 s) determines which DCT frequencies are included as nuisance regressors.
Let TR = sampling interval (e.g., 2 s).
Let N = number of volumes.
Total run length = T = N \times \text{TR}.
The fundamental frequency increment of the DCT is:
f_k = \frac{k}{2T} \quad \text{(Hz)}.
Corresponding period:
P_k = \frac{1}{f_k} = \frac{2T}{k}.
Now, the high-pass cutoff (say 100 s) means: include all cosines with periods ≥ cutoff, i.e., P_k \geq 100 \, \text{s}. Equivalently, all frequencies f_k \leq 0.01 \,\text{Hz}.
FEAT computes how many DCT terms are needed so that the lowest frequency kept matches the cutoff.
Example: run length T=600 s (10 min).
This way, any oscillation longer than 100 s is modeled by the DCT regressors and removed.
cd data/RBC/HBN_BIDS/sub-NDARAA306NT2/ses-HBNsiteRU/fmap
# merge the two phase encoding images
fslmerge -t AP_PA_merged.nii.gz sub-NDARAA306NT2_ses-HBNsiteRU_acq-fMRI_dir-AP_epi.nii.gz sub-NDARAA306NT2_ses-HBNsiteRU_acq-fMRI_dir-PA_epi.nii.gz
# write acquistion parameters x, y, z phase encoding directions. Final parameter is total readout time
echo "0 -1 0 0.04565\n0 1 0 0.04565" > acquisitionParams.txt
# apply topup
topup --imain=AP_PA_merged.nii.gz \
--datain=acquisitionParams.txt \
--config=b02b0.cnf \
--out=topup_AP_PA_b0 \
--iout=topup_AP_PA_b0_iout \
--fout=topup_AP_PA_b0_fout
# create mean of two unwarped images
fslmaths topup_AP_PA_b0_fout.nii.gz -abs -Tmean b0_mean.nii.gz
# brain extract the mean image
bet b0_mean.nii.gz b0_mean_brain.nii.gz -m
# convert Hz to radians
fslmaths topup_AP_PA_b0_iout.nii.gz -mul 6.283185307179586 field_rads.nii.gzFEAT B0 options:
field_rads.nii.gzb0_mean_brain.nii.gz.json file "TotalReadoutTime": 0.0481411.json file "PhaseEncodingDirection": "j-",Functional registration
fsl_anat tool (recommend this) and also using a manual registration-based approach# brain extraction fails here
fast data/RBC/HBN_BIDS/sub-NDARAA306NT2/ses-HBNsiteRU/anat/sub-NDARAA306NT2_ses-HBNsiteRU_acq-HCP_T1w.nii.gz
bet data/RBC/HBN_BIDS/sub-NDARAA306NT2/ses-HBNsiteRU/anat/sub-NDARAA306NT2_ses-HBNsiteRU_acq-HCP_T1w_bc.nii.gz data/RBC/HBN_BIDS/sub-NDARAA306NT2/ses-HBNsiteRU/anat/sub-NDARAA306NT2_ses-HBNsiteRU_acq-HCP_T1w_bet.nii.gz
fsleyes data/RBC/HBN_BIDS/sub-NDARAA306NT2/ses-HBNsiteRU/anat/sub-NDARAA306NT2_ses-HBNsiteRU_acq-HCP_T1w_bet.nii.gzFeat_gui# create mask with no holes
fslmaths /Users/vandeks/fsl/data/standard/MNI152_T1_1mm_brain_mask.nii.gz -fillh /Users/vandeks/fsl/data/standard/MNI152_T1_1mm_brain_noholes_mask.nii.gz
# Input images
func="data/RBC/HBN_BIDS/sub-NDARAA306NT2/ses-HBNsiteRU/func/sub-NDARAA306NT2_ses-HBNsiteRU_task-movieDM_bold.nii.gz"
anat="data/RBC/HBN_BIDS/sub-NDARAA306NT2/ses-HBNsiteRU/anat/sub-NDARAA306NT2_ses-HBNsiteRU_acq-HCP_T1w.nii.gz"
# register to the template
flirt -in $anat -ref /Users/vandeks/fsl/data/standard/MNI152_T1_1mm.nii.gz -dof 12 -omat data/RBC/HBN_BIDS/sub-NDARAA306NT2/ses-HBNsiteRU/anat/linearReg.txt
# get inverse transform
convert_xfm -inverse -omat data/RBC/HBN_BIDS/sub-NDARAA306NT2/ses-HBNsiteRU/anat/inv_linearReg.txt data/RBC/HBN_BIDS/sub-NDARAA306NT2/ses-HBNsiteRU/anat/linearReg.txt
# Move MNI mask into subject space
flirt -in /Users/vandeks/fsl/data/standard/MNI152_T1_1mm_brain_noholes_mask.nii.gz -ref $anat -applyxfm -init data/RBC/HBN_BIDS/sub-NDARAA306NT2/ses-HBNsiteRU/anat/inv_linearReg.txt -interp nearestneighbour -out data/RBC/HBN_BIDS/sub-NDARAA306NT2/ses-HBNsiteRU/anat/sub-NDARAA306NT2_ses-HBNsiteRU_acq-HCP_T1w_brain_mask.nii.gz
# view the MNI mask in subject space
# fsleyes data/RBC/HBN_BIDS/sub-NDARAA306NT2/ses-HBNsiteRU/anat/sub-NDARAA306NT2_ses-HBNsiteRU_acq-HCP_T1w.nii.gz data/RBC/HBN_BIDS/sub-NDARAA306NT2/ses-HBNsiteRU/anat/sub-NDARAA306NT2_ses-HBNsiteRU_acq-HCP_T1w_brain_mask.nii.gz
# create brain only image by applying brain mask
fslmaths data/RBC/HBN_BIDS/sub-NDARAA306NT2/ses-HBNsiteRU/anat/sub-NDARAA306NT2_ses-HBNsiteRU_acq-HCP_T1w.nii.gz -mas data/RBC/HBN_BIDS/sub-NDARAA306NT2/ses-HBNsiteRU/anat/sub-NDARAA306NT2_ses-HBNsiteRU_acq-HCP_T1w_brain_mask.nii.gz data/RBC/HBN_BIDS/sub-NDARAA306NT2/ses-HBNsiteRU/anat/sub-NDARAA306NT2_ses-HBNsiteRU_acq-HCP_T1w_brain.nii.gz