Run this notebook
This notebook walks through a simple, novice-friendly workflow in Neurodesk EDU:
set up one example project folder and download the FEAT templates used for higher-level modeling
download a public OSF archive that contains the five run-level Level-1
.featdirectories for sub-104 and the precomputed Level-2.gfeatdirectories for the full samplerender and run a fixed-effects Level-2 FEAT model for cope10 (reciprocate > defect) in sub-104
review the Level-2 output, including quick NiiVue visualizations
render and run an initial Level-3 one-group model focused on the same lower-level cope
inspect the resulting mask before trusting the activation map, using a real teachable moment from this workflow
download a refreshed Level-2 archive generated after rerunning preprocessing with fMRIPrep 25.2.5, rerender the same one-group Level-3 template, and rerun the group model
review the refreshed Level-3 output and compare it with the original result
The main teaching goal is to show how higher-level FEAT analyses can still go wrong even when the commands run cleanly — and why it is so important to check the mask before interpreting the activation.
Author:
David V. SmithDate: April 18, 2026
License:
MIT LicenseProvenance: This notebook adapts course materials and selected logic from the Fareri trust-game workflow code, but rewrites the steps so they can be followed directly in notebook cells. Full workflow repository: tubric
Acknowledgments: This notebook was generated with assistance from ChatGPT-5 across several iterations and then revised by the instructor. The instructor reviewed the final content and takes responsibility for it.
Citation and Resources¶
Study-specific references¶
Fareri et al. (2022): Fareri, D. S., Hackett, K., Tepfer, L. J., Kelly, V., Henninger, N., Reeck, C., Giovannetti, T., & Smith, D. V. (2022). Age-related differences in ventral striatal and default mode network function during reciprocated trust. NeuroImage, 256, 119267. DOI
Smith et al. (2024): Smith, D. V., Ludwig, R. M., Dennison, J. B., Reeck, C., & Fareri, D. S. (2024). An fMRI Dataset on Social Reward Processing and Decision Making in Younger and Older Adults. Scientific Data, 11(1), 158. DOI
Full workflow repository¶
Fareri trust-game workflow repo: tubric
/fareri -2022 -neuroimage
Public archives for this notebook¶
Persistent OSF project DOI: Smith (2026)
Original OSF file page: Original activation archive
Refreshed OSF file page: Revised FSL activation archive
Table of content¶
1. Load software tools and import python libraries
2. Project setup
3. Download the FEAT derivatives from OSF
4. Check the downloaded inputs
5. Render the Level-2 FEAT template
6. Run the Level-2 FEAT model
7. Review the Level-2 output
8. Render and run the initial Level-3 FEAT model
9. Review the initial Level-3 output and check the mask
10. Refresh the Level-3 inputs and rerun the group model
11. Review the refreshed Level-3 output
12. Dependencies in Jupyter/Python
1. Load software tools and import python libraries¶
import module
await module.load('fsl/6.0.7.16')
await module.list()
['fsl/6.0.7.16']%%capture
!pip install nibabel numpy osfclient
from pathlib import Path
import os
import numpy as np
import nibabel as nib
from IPython.display import display, Markdown, Image
HOME = Path.home()
EXAMPLE_DIR = HOME / "trust_example_higherlevel"
DOWNLOAD_DIR = EXAMPLE_DIR / "downloads"
DERIV_ROOT = EXAMPLE_DIR / "derivatives" / "fsl"
TEMPLATE_ROOT = EXAMPLE_DIR / "templates"
for d in [DOWNLOAD_DIR, DERIV_ROOT, TEMPLATE_ROOT]:
d.mkdir(parents=True, exist_ok=True)
sub = "104"
task = "trust"
model_type = "act"
sm = 6
nruns = 5
cope_num = 10
print("Example directory:", EXAMPLE_DIR)
print("Downloads:", DOWNLOAD_DIR)
print("Derivative root:", DERIV_ROOT)
print("Template root:", TEMPLATE_ROOT)
Example directory: /home/jovyan/trust_example_higherlevel
Downloads: /home/jovyan/trust_example_higherlevel/downloads
Derivative root: /home/jovyan/trust_example_higherlevel/derivatives/fsl
Template root: /home/jovyan/trust_example_higherlevel/templates
2. Project setup¶
We will keep everything for this example in one folder directly under the home directory:
~/trust_example_higherlevel
This notebook is designed to be rerun safely. To make that possible, we keep the downloaded archive, the shared derivatives, and the notebook-generated FEAT outputs in separate subfolders.
For this notebook, we need:
one Level-2 fixed-effects template for rerunning sub-104
one Level-3 one-group template for the initial and refreshed group analyses
We will use three subfolders with different roles:
~/trust_example_higherlevel/templatesfor the downloaded.fsftemplates~/trust_example_higherlevel/downloadsfor the raw OSF archive and its unpacked contents~/trust_example_higherlevel/derivatives/fslfor the shared FEAT derivatives and the new notebook-generated higher-level outputs
%%bash
set -e
EXAMPLE_DIR="$HOME/trust_example_higherlevel"
mkdir -p "$EXAMPLE_DIR/templates"
mkdir -p "$EXAMPLE_DIR/downloads"
mkdir -p "$EXAMPLE_DIR/derivatives/fsl/sub-104"
# Copy the FEAT templates we need for this notebook.
curl -L \
https://raw.githubusercontent.com/tubric/fareri-2022-neuroimage/main/templates/L2_task-trust_model-01_type-act_nruns-5.fsf \
-o "$EXAMPLE_DIR/templates/L2_task-trust_model-01_type-act_nruns-5.fsf"
curl -L \
https://raw.githubusercontent.com/tubric/fareri-2022-neuroimage/main/templates/L3_template_n48_trust_onegroup.fsf \
-o "$EXAMPLE_DIR/templates/L3_template_n48_trust_onegroup.fsf"
echo "Templates copied to:"
ls -1 "$EXAMPLE_DIR/templates"
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 9228 100 9228 0 0 30239 0 --:--:-- --:--:-- --:--:-- 30255
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 21483 100 21483 0 0 79060 0 --:--:-- --:--:-- --:--:-- 79273
Templates copied to:
L2_task-trust_model-01_type-act_nruns-5.fsf
L3_template_n48_trust_onegroup.fsf
!find ~/trust_example_higherlevel/templates -maxdepth 1 -type f | sort
/home/jovyan/trust_example_higherlevel/templates/L2_task-trust_model-01_type-act_nruns-5.fsf
/home/jovyan/trust_example_higherlevel/templates/L3_template_n48_trust_onegroup.fsf
The original shell scripts automate higher-level FEAT across many participants, models, and contrasts. Here we narrow that logic to one concrete teaching case.
The OSF archive used below contains two kinds of material that matter for this notebook:
the five run-level Level-1
.featdirectories for sub-104, which let us rerun the Level-2 model from scratchthe precomputed Level-2
.gfeatdirectories for the full sample, which let us build Level-3 group analyses without first rerunning every participant
That combination keeps the notebook compact while still showing the full higher-level workflow end to end.
3. Download the FEAT derivatives from OSF¶
For this notebook, assume the completed FEAT derivatives have already been shared through the public OSF project:
Persistent project DOI: Smith (2026)
OSF project: KTXUG project page
File page: Original activation archive
The first command below lists the files visible in that OSF project. In this case, the archive path reported by osf ls is:
osfstorage/fareri-2022-neuroimage_example-activation.tar.gz
The cell is written so that it can be rerun safely. If the archive already exists locally, it will be reused rather than downloaded again. The unpacked archive contents will still be refreshed, and the archived FEAT derivatives will be copied into the notebook’s derivatives/fsl/ folder.
%%bash
set -e
EXAMPLE_DIR="$HOME/trust_example_higherlevel"
PROJECT="ktxug"
REMOTE_ARCHIVE="osfstorage/fareri-2022-neuroimage_example-activation.tar.gz"
LOCAL_ARCHIVE="$EXAMPLE_DIR/downloads/fareri-2022-neuroimage_example-activation.tar.gz"
DOWNLOAD_DIR="$EXAMPLE_DIR/downloads"
DERIV_DIR="$EXAMPLE_DIR/derivatives/fsl"
mkdir -p "$DOWNLOAD_DIR"
mkdir -p "$DERIV_DIR"
echo "Files visible in OSF project $PROJECT:"
osf -p "$PROJECT" ls
echo
if [ ! -f "$LOCAL_ARCHIVE" ]; then
echo "Downloading archive from OSF ..."
osf -p "$PROJECT" fetch "$REMOTE_ARCHIVE" "$LOCAL_ARCHIVE"
else
echo "Archive already exists locally. Reusing it:"
echo " $LOCAL_ARCHIVE"
fi
echo
echo "Refreshing unpacked archive contents ..."
rm -rf "$DOWNLOAD_DIR/__forOSF"
tar -xzf "$LOCAL_ARCHIVE" -C "$DOWNLOAD_DIR"
echo
echo "Copying archived FEAT derivatives into the teaching directory ..."
cp -r "$DOWNLOAD_DIR/__forOSF/." "$DERIV_DIR/"
echo
echo "Example derivatives are now here:"
echo " $DERIV_DIR"
find "$DERIV_DIR" -maxdepth 2 -type d | sort | head -60
Files visible in OSF project ktxug:
osfstorage/revised-fsl-activation.tar.gz
osfstorage/fareri-2022-neuroimage_example-activation.tar.gz
Downloading archive from OSF ...
Refreshing unpacked archive contents ...
Copying archived FEAT derivatives into the teaching directory ...
Example derivatives are now here:
/home/jovyan/trust_example_higherlevel/derivatives/fsl
/home/jovyan/trust_example_higherlevel/derivatives/fsl
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-01_sm-6.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-02_sm-6.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-03_sm-6.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-04_sm-6.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-05_sm-6.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-105
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-105/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-106
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-106/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-107
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-107/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-108
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-108/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-109
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-109/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-110
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-110/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-111
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-111/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-112
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-112/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-113
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-113/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-115
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-115/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-116
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-116/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-117
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-117/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-118
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-118/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-120
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-120/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-121
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-121/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-122
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-122/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-124
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-124/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-125
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-125/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-126
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-126/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-127
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-127/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-128
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-128/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-129
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-129/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-130
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-130/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-131
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-131/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-132
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-132/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-133
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-133/L2_task-trust_model-01_type-act_sm-6.gfeat
100%|██████████| 3.30G/3.30G [03:22<00:00, 16.3Mbytes/s]
!find ~/trust_example_higherlevel/derivatives/fsl -maxdepth 2 -type d | sort | head -60
/home/jovyan/trust_example_higherlevel/derivatives/fsl
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-01_sm-6.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-02_sm-6.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-03_sm-6.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-04_sm-6.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-05_sm-6.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-105
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-105/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-106
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-106/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-107
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-107/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-108
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-108/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-109
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-109/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-110
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-110/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-111
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-111/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-112
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-112/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-113
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-113/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-115
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-115/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-116
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-116/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-117
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-117/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-118
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-118/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-120
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-120/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-121
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-121/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-122
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-122/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-124
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-124/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-125
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-125/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-126
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-126/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-127
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-127/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-128
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-128/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-129
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-129/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-130
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-130/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-131
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-131/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-132
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-132/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-133
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-133/L2_task-trust_model-01_type-act_sm-6.gfeat
The archive is expected to unpack into a top-level __forOSF/ folder. Its contents are then copied into:
~/trust_example_higherlevel/derivatives/fsl/
That means the notebook’s working derivative tree now includes:
the five run-level Level-1
.featdirectories for sub-104the precomputed Level-2
.gfeatdirectories for the full sample
Later cells clean only the specific notebook-generated outputs they are about to recreate, which keeps reruns predictable without deleting the archived materials.
4. Check the downloaded inputs¶
Before rendering any templates, it is worth confirming two simple things:
the five run-level Level-1
.featdirectories exist for sub-104, because they are the direct inputs to the Level-2 modelthe precomputed Level-2
.gfeatdirectories exist across the sample, because they are the direct inputs to the Level-3 group models
These checks are deliberately simple and explicit. If the expected directories are missing, it is better to stop here than to render templates that point to nonexistent inputs.
%%bash
set -e
echo "Checking sub-104 run-level Level-1 FEAT inputs ..."
find ~/trust_example_higherlevel/derivatives/fsl/sub-104 -maxdepth 1 -type d -name "L1_task-trust_model-01_type-act_run-*_sm-6.feat" | sort
echo
echo "Counting downloaded Level-2 .gfeat directories across the sample ..."
find ~/trust_example_higherlevel/derivatives/fsl -maxdepth 2 -type d -name "L2_task-trust_model-01_type-act_sm-6.gfeat" | wc -l
Checking sub-104 run-level Level-1 FEAT inputs ...
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-01_sm-6.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-02_sm-6.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-03_sm-6.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-04_sm-6.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-05_sm-6.feat
Counting downloaded Level-2 .gfeat directories across the sample ...
48
!find ~/trust_example_higherlevel/derivatives/fsl -maxdepth 2 -type d -name "L2_task-trust_model-01_type-act_sm-6.gfeat" | sort | head -20
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-105/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-106/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-107/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-108/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-109/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-110/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-111/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-112/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-113/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-115/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-116/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-117/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-118/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-120/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-121/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-122/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-124/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-125/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-126/L2_task-trust_model-01_type-act_sm-6.gfeat
If one or more Level-1 runs are missing for sub-104, stop here and fix that first. If the Level-2 directories are missing across the sample, the later Level-3 group analyses will not work.
The original scripts include more bookkeeping for edge cases, but this teaching version stays simple on purpose.
One practical point is still worth noting: these archived FEAT derivatives were generated with FSL 6.0.7.16, and this notebook assumes the same version for consistency. In principle, higher-level FEAT often works across nearby FSL versions, but for a teaching example it is better to keep the software version fixed so the file layout and behavior stay predictable.
5. Render the Level-2 FEAT template¶
The original L2stats.sh script uses sed to replace a small set of placeholders in the .fsf template. For the 5-run activation model, the important placeholders are:
OUTPUTfor the new higher-level output directoryINPUT1throughINPUT5for the five run-level.featdirectories
This is the key idea of scripted FEAT workflows: rather than point-and-clicking through the GUI every time, you render a text template with the correct paths and then hand the finished .fsf file to FEAT.
%%bash
set -e
EXAMPLE_DIR="$HOME/trust_example_higherlevel"
INPUT_DIR="$EXAMPLE_DIR/derivatives/fsl/sub-104"
OUTPUT_DIR="$EXAMPLE_DIR/derivatives/fsl/sub-104"
ITEMPLATE="$EXAMPLE_DIR/templates/L2_task-trust_model-01_type-act_nruns-5.fsf"
OTEMPLATE="$OUTPUT_DIR/L2_task-trust_model-01_type-act.fsf"
OUTPUT="$OUTPUT_DIR/L2_task-trust_model-01_type-act_sm-6"
INPUT1="$INPUT_DIR/L1_task-trust_model-01_type-act_run-01_sm-6.feat"
INPUT2="$INPUT_DIR/L1_task-trust_model-01_type-act_run-02_sm-6.feat"
INPUT3="$INPUT_DIR/L1_task-trust_model-01_type-act_run-03_sm-6.feat"
INPUT4="$INPUT_DIR/L1_task-trust_model-01_type-act_run-04_sm-6.feat"
INPUT5="$INPUT_DIR/L1_task-trust_model-01_type-act_run-05_sm-6.feat"
sed \
-e "s@OUTPUT@${OUTPUT}@g" \
-e "s@INPUT1@${INPUT1}@g" \
-e "s@INPUT2@${INPUT2}@g" \
-e "s@INPUT3@${INPUT3}@g" \
-e "s@INPUT4@${INPUT4}@g" \
-e "s@INPUT5@${INPUT5}@g" \
< "$ITEMPLATE" > "$OTEMPLATE"
echo "Rendered template: $OTEMPLATE"
Rendered template: /home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act.fsf
!grep -E 'outputdir|multiple|ncopeinputs|feat_files' ~/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act.fsf | head -20
set fmri(outputdir) "/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6"
set fmri(multiple) 5
set fmri(ncopeinputs) 18
set feat_files(1) "/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-01_sm-6.feat"
set feat_files(2) "/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-02_sm-6.feat"
set feat_files(3) "/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-03_sm-6.feat"
set feat_files(4) "/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-04_sm-6.feat"
set feat_files(5) "/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-05_sm-6.feat"
That quick check is worth doing. It lets you confirm that the rendered .fsf now points to the correct output directory and the correct five inputs before you launch FEAT.
6. Run the Level-2 FEAT model¶
The next two cells prepare and launch FEAT on the rendered Level-2 .fsf file. Compared with fMRIPrep, this step is usually much faster, but it can still take a while depending on the system and the size of the run-level inputs.
In conceptual terms, this model uses fixed effects to combine the five trust-task runs within one participant. The result is a single .gfeat directory that contains one higher-level FEAT result for each lower-level cope.
%%bash
set -e
OUTPUT_DIR="$HOME/trust_example_higherlevel/derivatives/fsl/sub-104"
L2_BASENAME="L2_task-trust_model-01_type-act_sm-6"
rm -rf "${OUTPUT_DIR}/${L2_BASENAME}.gfeat"
rm -rf "${OUTPUT_DIR}/${L2_BASENAME}+"*.gfeat
rm -rf "${OUTPUT_DIR}/logs"
echo "Removed any previous notebook-generated Level-2 derivatives:"
echo " ${OUTPUT_DIR}/${L2_BASENAME}.gfeat"
echo " ${OUTPUT_DIR}/${L2_BASENAME}+*.gfeat"
Removed any previous notebook-generated Level-2 derivatives:
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6+*.gfeat
%%bash
set -e
OTEMPLATE="$HOME/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act.fsf"
feat "$OTEMPLATE"
To view the FEAT progress and final report, point your web browser at /home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/report_log.html
7. Review the Level-2 output¶
The Level-2 output should now live in a .gfeat directory under:
~/trust_example_higherlevel/derivatives/fsl/sub-104/
At a minimum, you want to confirm that:
the
.gfeatdirectory existsthe expected
cope*.featsubdirectories existthe FEAT report exists
the thresholded map for cope10 (reciprocate > defect) exists
The next few cells give you quick visual checks in NiiVue.
from pathlib import Path
outroot = EXAMPLE_DIR / "derivatives" / "fsl" / "sub-104"
matches = sorted(
outroot.glob("L2_task-trust_model-01_type-act_sm-6*.gfeat"),
key=lambda p: p.stat().st_mtime,
reverse=True,
)
if not matches:
raise FileNotFoundError("No matching Level-2 .gfeat directory found.")
gfeat_dir = matches[0]
print("Using Level-2 gfeat directory:", gfeat_dir)
for rel in [
"report.html",
"cope1.feat",
"cope10.feat",
"cope18.feat",
"cope10.feat/thresh_zstat1.nii.gz",
]:
p = gfeat_dir / rel
print(f"{p}: {p.exists()}")
Using Level-2 gfeat directory: /home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/report.html: True
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope1.feat: True
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope10.feat: True
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope18.feat: True
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope10.feat/thresh_zstat1.nii.gz: True
cope_dirs = sorted(gfeat_dir.glob("cope*.feat"))
for p in cope_dirs[:20]:
print(p)
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope1.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope10.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope11.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope12.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope13.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope14.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope15.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope16.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope17.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope18.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope2.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope3.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope4.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope5.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope6.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope7.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope8.feat
/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope9.feat
report_html = gfeat_dir / "report.html"
print("Level-2 report exists:", report_html.exists(), report_html)
Level-2 report exists: True /home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/report.html
In this section we move directly to quick visual checks of the Level-2 cope10 map. The goal is to confirm that the within-subject fixed-effects analysis ran and to inspect the main result before moving to the group model.
The first overlay below uses cope10.feat/thresh_zstat1.nii.gz, which corresponds to the reciprocate > defect contrast combined across runs.
from ipyniivue import NiiVue
bg_meanfunc = gfeat_dir / "bg_image.nii.gz"
zmap = gfeat_dir / "cope10.feat" / "thresh_zstat1.nii.gz"
print("Background exists:", bg_meanfunc.exists(), bg_meanfunc)
print("Contrast exists:", zmap.exists(), zmap)
if bg_meanfunc.exists() and zmap.exists():
bg_data = nib.load(str(bg_meanfunc)).get_fdata()
bg_nonzero = bg_data[bg_data > 0]
lo = float(np.percentile(bg_nonzero, 2))
hi = float(np.percentile(bg_nonzero, 98))
nv = NiiVue()
nv.load_volumes([
{
"path": str(bg_meanfunc),
"name": "bg_image",
"colormap": "gray",
"opacity": 1.0,
"cal_min": lo,
"cal_max": hi,
},
{
"path": str(zmap),
"name": "reciprocate > defect across runs",
"colormap": "red",
"opacity": 0.75,
},
])
display(nv)
else:
print("Run FEAT first, then come back to this cell.")
Background exists: True /home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/bg_image.nii.gz
Contrast exists: True /home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope10.feat/thresh_zstat1.nii.gz
The next cell shows the same Level-2 map on an MNI T1 background with better anatomical contrast.
from ipyniivue import NiiVue
# Try a few common FSL locations for the MNI T1 background.
bg_candidates = [
Path(os.environ.get("FSLDIR", "")) / "data" / "standard" / "MNI152_T1_2mm_brain.nii.gz" if os.environ.get("FSLDIR") else None,
Path("/opt/fsl/data/standard/MNI152_T1_2mm_brain.nii.gz"),
Path("/opt/fsl-6.0.7.16/data/standard/MNI152_T1_2mm_brain.nii.gz"),
Path("/usr/share/fsl/5.0/data/standard/MNI152_T1_2mm_brain.nii.gz"),
]
bg_path = None
for cand in bg_candidates:
if cand is not None and cand.exists():
bg_path = cand
break
zmap = gfeat_dir / "cope10.feat" / "thresh_zstat1.nii.gz"
print("Background exists:", bg_path is not None, bg_path)
print("Contrast exists:", zmap.exists(), zmap)
if bg_path is not None and zmap.exists():
bg_data = nib.load(str(bg_path)).get_fdata()
bg_nonzero = bg_data[bg_data > 0]
lo = float(np.percentile(bg_nonzero, 2))
hi = float(np.percentile(bg_nonzero, 98))
nv = NiiVue()
nv.load_volumes([
{
"path": str(bg_path),
"name": "MNI152_T1_2mm_brain",
"colormap": "gray",
"opacity": 1.0,
"cal_min": lo,
"cal_max": hi,
},
{
"path": str(zmap),
"name": "reciprocate > defect across runs",
"colormap": "red",
"opacity": 0.75,
},
])
display(nv)
else:
print("Could not find the MNI T1 background or the thresholded map.")
Background exists: True /cvmfs/neurodesk.ardc.edu.au/containers/fsl_6.0.7.16_20250131/fsl_6.0.7.16_20250131.simg/opt/fsl-6.0.7.16/data/standard/MNI152_T1_2mm_brain.nii.gz
Contrast exists: True /home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope10.feat/thresh_zstat1.nii.gz
8. Render and run the initial Level-3 FEAT model¶
We now turn to the first group-level analysis, while staying focused on the same lower-level cope: cope10 (reciprocate > defect).
For the teachable moment below, we begin with the original one-group template and the original shared Level-2 archive:
L3_template_n48_trust_onegroup.fsfone-sample t-test across the full sample
output of interest:
cope1.feat/thresh_zstat1.nii.gz
We deliberately keep this first Level-3 run simple. That makes it easier to see the problem when the group activation looks less impressive than expected.
%%bash
set -e
EXAMPLE_DIR="$HOME/trust_example_higherlevel"
DERIV_DIR="$EXAMPLE_DIR/derivatives/fsl"
ITEMPLATE_ONE="$EXAMPLE_DIR/templates/L3_template_n48_trust_onegroup.fsf"
OTEMPLATE_ONE="$DERIV_DIR/L3_task-trust_model-01_type-act_cope10_onegroup.fsf"
OUTPUT_ONE="$DERIV_DIR/L3_task-trust_model-01_type-act_cope10_onegroup"
sed \
-e "s@OUTPUT@${OUTPUT_ONE}@g" \
-e "s@BASEDIR@${EXAMPLE_DIR}@g" \
-e "s@REPLACEME@type-act@g" \
-e "s@COPENUM@10@g" \
< "$ITEMPLATE_ONE" > "$OTEMPLATE_ONE"
echo "Rendered:"
echo " $OTEMPLATE_ONE"
Rendered:
/home/jovyan/trust_example_higherlevel/derivatives/fsl/L3_task-trust_model-01_type-act_cope10_onegroup.fsf
!grep -E 'outputdir|feat_files\(1\)|feat_files\(48\)|conname_real' ~/trust_example_higherlevel/derivatives/fsl/L3_task-trust_model-01_type-act_cope10_onegroup.fsfset fmri(outputdir) "/home/jovyan/trust_example_higherlevel/derivatives/fsl/L3_task-trust_model-01_type-act_cope10_onegroup"
set feat_files(1) "/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope10.feat/stats/cope1.nii.gz"
set feat_files(48) "/home/jovyan/trust_example_higherlevel/derivatives/fsl/sub-159/L2_task-trust_model-01_type-act_sm-6.gfeat/cope10.feat/stats/cope1.nii.gz"
set fmri(conname_real.1) "pos"
set fmri(conname_real.2) "neg"
The rendered .fsf should point to the archived Level-2 .gfeat directories in the original shared derivative tree. Because this first group model is just a one-sample t-test, the bookkeeping stays simple enough that you can inspect the paths directly before running FEAT.
%%bash
set -e
DERIV_DIR="$HOME/trust_example_higherlevel/derivatives/fsl"
rm -rf "${DERIV_DIR}/L3_task-trust_model-01_type-act_cope10_onegroup.gfeat"
rm -rf "${DERIV_DIR}/L3_task-trust_model-01_type-act_cope10_onegroup+"*.gfeat
rm -rf "${DERIV_DIR}/logs"
echo "Removed any previous notebook-generated initial Level-3 derivatives."
Removed any previous notebook-generated initial Level-3 derivatives.
%%bash
set -e
ONEGROUP_FSF="$HOME/trust_example_higherlevel/derivatives/fsl/L3_task-trust_model-01_type-act_cope10_onegroup.fsf"
feat "$ONEGROUP_FSF"
To view the FEAT progress and final report, point your web browser at /home/jovyan/trust_example_higherlevel/derivatives/fsl/L3_task-trust_model-01_type-act_cope10_onegroup.gfeat/report_log.html
9. Review the initial Level-3 output and check the mask¶
For the initial one-group model, the main map we want is:
cope1.feat/thresh_zstat1.nii.gz
This is where the teachable moment begins. If the activation pattern looks surprisingly limited, do not immediately assume the underlying effect is absent. First inspect the group mask that FEAT actually used for the inference step.
initial_onegroup_dir = EXAMPLE_DIR / "derivatives" / "fsl" / "L3_task-trust_model-01_type-act_cope10_onegroup.gfeat"
for rel in [
"report.html",
"design.png",
"cope1.feat",
"cope1.feat/mask.nii.gz",
"cope1.feat/thresh_zstat1.nii.gz",
]:
p = initial_onegroup_dir / rel
print(f"{p}: {p.exists()}")
# Reuse the MNI T1 background logic for the Level-3 visualizations.
bg_candidates = [
Path(os.environ.get("FSLDIR", "")) / "data" / "standard" / "MNI152_T1_2mm_brain.nii.gz" if os.environ.get("FSLDIR") else None,
Path("/opt/fsl/data/standard/MNI152_T1_2mm_brain.nii.gz"),
Path("/opt/fsl-6.0.7.16/data/standard/MNI152_T1_2mm_brain.nii.gz"),
Path("/usr/share/fsl/5.0/data/standard/MNI152_T1_2mm_brain.nii.gz"),
]
group_bg = None
for cand in bg_candidates:
if cand is not None and cand.exists():
group_bg = cand
break
print("MNI background exists:", group_bg is not None, group_bg)
/home/jovyan/trust_example_higherlevel/derivatives/fsl/L3_task-trust_model-01_type-act_cope10_onegroup.gfeat/report.html: True
/home/jovyan/trust_example_higherlevel/derivatives/fsl/L3_task-trust_model-01_type-act_cope10_onegroup.gfeat/design.png: True
/home/jovyan/trust_example_higherlevel/derivatives/fsl/L3_task-trust_model-01_type-act_cope10_onegroup.gfeat/cope1.feat: True
/home/jovyan/trust_example_higherlevel/derivatives/fsl/L3_task-trust_model-01_type-act_cope10_onegroup.gfeat/cope1.feat/mask.nii.gz: True
/home/jovyan/trust_example_higherlevel/derivatives/fsl/L3_task-trust_model-01_type-act_cope10_onegroup.gfeat/cope1.feat/thresh_zstat1.nii.gz: True
MNI background exists: True /cvmfs/neurodesk.ardc.edu.au/containers/fsl_6.0.7.16_20250131/fsl_6.0.7.16_20250131.simg/opt/fsl-6.0.7.16/data/standard/MNI152_T1_2mm_brain.nii.gz
The first visualization below shows the original one-group result for reciprocate > defect. The result is not wrong in the narrow sense that FEAT ran, but it is incomplete in a scientifically important way. This is exactly why it is worth checking the mask before spending much time on interpretation.
from ipyniivue import NiiVue
zmap = initial_onegroup_dir / "cope1.feat" / "thresh_zstat1.nii.gz"
print("Background exists:", group_bg is not None, group_bg)
print("Contrast exists:", zmap.exists(), zmap)
if group_bg is not None and zmap.exists():
zdata = nib.load(str(zmap)).get_fdata()
zmax = float(np.nanmax(zdata))
print("Max thresholded value:", zmax)
if zmax > 0:
bg_data = nib.load(str(group_bg)).get_fdata()
bg_nonzero = bg_data[bg_data > 0]
lo = float(np.percentile(bg_nonzero, 2))
hi = float(np.percentile(bg_nonzero, 98))
nv = NiiVue()
nv.load_volumes([
{
"path": str(group_bg),
"name": "MNI152_T1_2mm_brain",
"colormap": "gray",
"opacity": 1.0,
"cal_min": lo,
"cal_max": hi,
},
{
"path": str(zmap),
"name": "initial mean_pos",
"colormap": "red",
"opacity": 0.75,
},
])
display(nv)
else:
print("The thresholded map contains no voxels above zero, so we skip plotting it.")
else:
print("Could not find the MNI background or the initial thresholded group map.")
Background exists: True /cvmfs/neurodesk.ardc.edu.au/containers/fsl_6.0.7.16_20250131/fsl_6.0.7.16_20250131.simg/opt/fsl-6.0.7.16/data/standard/MNI152_T1_2mm_brain.nii.gz
Contrast exists: True /home/jovyan/trust_example_higherlevel/derivatives/fsl/L3_task-trust_model-01_type-act_cope10_onegroup.gfeat/cope1.feat/thresh_zstat1.nii.gz
Max thresholded value: 4.791534900665283
Now check the Level-3 mask directly. The lesson here is simple and general: always check your mask before you check your activation.
In this case, the mask reveals that FEAT only analyzed a small and obviously incorrect subset of voxels—mostly in the temporal lobe, with some voxels even extending outside the brain. That pattern tells us something went seriously wrong upstream.
These original higher-level inputs were derived from an older preprocessing run using fMRIPrep 20.2.3. We chose that older version because it came closer to the preprocessing vintage of the original paper, even though the Neurodesk module options do not go that far back. That likely contributed to the failure mode here, which is why we reran the shared derivatives with a different fMRIPrep version before trusting the group result.
old_mask = initial_onegroup_dir / "cope1.feat" / "mask.nii.gz"
print("Background exists:", group_bg is not None, group_bg)
print("Mask exists:", old_mask.exists(), old_mask)
if old_mask.exists():
mask_data = nib.load(str(old_mask)).get_fdata()
mask_nvox = int(np.count_nonzero(mask_data > 0))
print("Nonzero mask voxels:", mask_nvox)
nz = np.argwhere(mask_data > 0)
if nz.size > 0:
print("Mask bounding box (voxel indices):")
print(" min:", nz.min(axis=0))
print(" max:", nz.max(axis=0))
if group_bg is not None and old_mask.exists():
bg_data = nib.load(str(group_bg)).get_fdata()
bg_nonzero = bg_data[bg_data > 0]
lo = float(np.percentile(bg_nonzero, 2))
hi = float(np.percentile(bg_nonzero, 98))
nv = NiiVue()
nv.load_volumes([
{
"path": str(group_bg),
"name": "MNI152_T1_2mm_brain",
"colormap": "gray",
"opacity": 1.0,
"cal_min": lo,
"cal_max": hi,
},
{
"path": str(old_mask),
"name": "initial group mask",
"colormap": "red",
"opacity": 0.55,
"cal_min": 0.5,
"cal_max": 1.0,
},
])
display(nv)
else:
print("Could not find the MNI background or the initial group mask.")
Background exists: True /cvmfs/neurodesk.ardc.edu.au/containers/fsl_6.0.7.16_20250131/fsl_6.0.7.16_20250131.simg/opt/fsl-6.0.7.16/data/standard/MNI152_T1_2mm_brain.nii.gz
Mask exists: True /home/jovyan/trust_example_higherlevel/derivatives/fsl/L3_task-trust_model-01_type-act_cope10_onegroup.gfeat/cope1.feat/mask.nii.gz
Nonzero mask voxels: 1214
Mask bounding box (voxel indices):
min: [ 8 33 16]
max: [25 62 29]
10. Refresh the Level-3 inputs and rerun the group model¶
To fix that problem, we keep the Level-2 example as-is but swap in a refreshed shared Level-2 archive that was generated after rerunning preprocessing with fMRIPrep 25.2.5.
The public file page for that refreshed archive is:
The refreshed archive itself is named:
osfstorage/revised-fsl-activation.tar.gz
The cell below uses that exact archive name. It also detects the top-level extracted folder automatically, so the notebook stays stable even if the archive unpacks into a folder such as __forHigherLevel-Act.
%%bash
set -e
EXAMPLE_DIR="$HOME/trust_example_higherlevel"
PROJECT="ktxug"
REFRESH_ROOT="$EXAMPLE_DIR/refreshed_2525"
REFRESH_DOWNLOAD_DIR="$REFRESH_ROOT/downloads"
REFRESH_DERIV_DIR="$REFRESH_ROOT/derivatives/fsl"
REMOTE_ARCHIVE_NEW="osfstorage/revised-fsl-activation.tar.gz"
LOCAL_ARCHIVE_NEW="$REFRESH_DOWNLOAD_DIR/revised-fsl-activation.tar.gz"
mkdir -p "$REFRESH_DOWNLOAD_DIR"
mkdir -p "$REFRESH_DERIV_DIR"
echo "Files visible in OSF project $PROJECT:"
osf -p "$PROJECT" ls
echo
if [ ! -f "$LOCAL_ARCHIVE_NEW" ]; then
echo "Downloading refreshed archive from OSF ..."
osf -p "$PROJECT" fetch "$REMOTE_ARCHIVE_NEW" "$LOCAL_ARCHIVE_NEW"
else
echo "Refreshed archive already exists locally. Reusing it:"
echo " $LOCAL_ARCHIVE_NEW"
fi
echo
echo "Refreshing unpacked archive contents ..."
find "$REFRESH_DOWNLOAD_DIR" -mindepth 1 -maxdepth 1 -type d -name "__for*" -exec rm -rf {} +
tar -xzf "$LOCAL_ARCHIVE_NEW" -C "$REFRESH_DOWNLOAD_DIR"
# Detect the top-level folder created by the archive so the notebook stays robust
# if we rename that folder in a future archive refresh.
ARCHIVE_ROOT="$(find "$REFRESH_DOWNLOAD_DIR" -mindepth 1 -maxdepth 1 -type d -name "__for*" | head -1)"
echo "Detected archive root:"
echo " $ARCHIVE_ROOT"
if [ -z "$ARCHIVE_ROOT" ] || [ ! -d "$ARCHIVE_ROOT" ]; then
echo "Could not detect the refreshed archive root after unpacking."
exit 1
fi
echo
ls "$REFRESH_DOWNLOAD_DIR"
ls "$LOCAL_ARCHIVE_NEW"
echo
echo "Refreshing the shared derivative tree ..."
rm -rf "$REFRESH_DERIV_DIR"
mkdir -p "$REFRESH_DERIV_DIR"
cp -r "$ARCHIVE_ROOT/." "$REFRESH_DERIV_DIR/"
echo
echo "Refreshed higher-level derivatives are now here:"
echo " $REFRESH_DERIV_DIR"
find "$REFRESH_DERIV_DIR" -maxdepth 2 -type d | sort | head -60
Files visible in OSF project ktxug:
osfstorage/revised-fsl-activation.tar.gz
osfstorage/fareri-2022-neuroimage_example-activation.tar.gz
Downloading refreshed archive from OSF ...
Refreshing unpacked archive contents ...
Detected archive root:
/home/jovyan/trust_example_higherlevel/refreshed_2525/downloads/__forHigherLevel-Act
__forHigherLevel-Act
revised-fsl-activation.tar.gz
/home/jovyan/trust_example_higherlevel/refreshed_2525/downloads/revised-fsl-activation.tar.gz
Refreshing the shared derivative tree ...
Refreshed higher-level derivatives are now here:
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-104
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-01_sm-6.feat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-02_sm-6.feat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-03_sm-6.feat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-04_sm-6.feat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-104/L1_task-trust_model-01_type-act_run-05_sm-6.feat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-105
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-105/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-106
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-106/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-107
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-107/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-108
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-108/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-109
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-109/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-110
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-110/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-111
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-111/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-112
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-112/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-113
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-113/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-115
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-115/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-116
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-116/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-117
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-117/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-118
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-118/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-120
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-120/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-121
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-121/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-122
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-122/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-124
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-124/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-125
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-125/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-126
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-126/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-127
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-127/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-128
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-128/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-129
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-129/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-130
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-130/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-131
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-131/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-132
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-132/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-133
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-133/L2_task-trust_model-01_type-act_sm-6.gfeat
100%|██████████| 2.76G/2.76G [03:16<00:00, 14.0Mbytes/s]
%%bash
set -e
echo "Counting refreshed Level-2 .gfeat directories across the sample ..."
find ~/trust_example_higherlevel/refreshed_2525/derivatives/fsl -maxdepth 2 -type d -name "L2_task-trust_model-01_type-act_sm-6.gfeat" | wc -l
echo
echo "Showing a few refreshed Level-2 input paths ..."
find ~/trust_example_higherlevel/refreshed_2525/derivatives/fsl -maxdepth 2 -type d -name "L2_task-trust_model-01_type-act_sm-6.gfeat" | sort | head -5
Counting refreshed Level-2 .gfeat directories across the sample ...
48
Showing a few refreshed Level-2 input paths ...
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-105/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-106/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-107/L2_task-trust_model-01_type-act_sm-6.gfeat
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-108/L2_task-trust_model-01_type-act_sm-6.gfeat
We now rerender the same one-group Level-3 template so that BASEDIR points to the refreshed derivative tree. This lets us keep the original example intact while also showing how the group result changes when the Level-2 inputs are regenerated appropriately.
%%bash
set -e
EXAMPLE_DIR="$HOME/trust_example_higherlevel"
REFRESH_ROOT="$EXAMPLE_DIR/refreshed_2525"
REFRESH_DERIV_DIR="$REFRESH_ROOT/derivatives/fsl"
ITEMPLATE_ONE="$EXAMPLE_DIR/templates/L3_template_n48_trust_onegroup.fsf"
OTEMPLATE_ONE="$REFRESH_DERIV_DIR/L3_task-trust_model-01_type-act_cope10_onegroup_fmriprep2525.fsf"
OUTPUT_ONE="$REFRESH_DERIV_DIR/L3_task-trust_model-01_type-act_cope10_onegroup_fmriprep2525"
sed \
-e "s@OUTPUT@${OUTPUT_ONE}@g" \
-e "s@BASEDIR@${REFRESH_ROOT}@g" \
-e "s@REPLACEME@type-act@g" \
-e "s@COPENUM@10@g" \
< "$ITEMPLATE_ONE" > "$OTEMPLATE_ONE"
echo "Rendered refreshed template:"
echo " $OTEMPLATE_ONE"
Rendered refreshed template:
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/L3_task-trust_model-01_type-act_cope10_onegroup_fmriprep2525.fsf
!grep -E 'outputdir|feat_files\(1\)|feat_files\(48\)|conname_real' ~/trust_example_higherlevel/refreshed_2525/derivatives/fsl/L3_task-trust_model-01_type-act_cope10_onegroup_fmriprep2525.fsf
set fmri(outputdir) "/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/L3_task-trust_model-01_type-act_cope10_onegroup_fmriprep2525"
set feat_files(1) "/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-104/L2_task-trust_model-01_type-act_sm-6.gfeat/cope10.feat/stats/cope1.nii.gz"
set feat_files(48) "/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/sub-159/L2_task-trust_model-01_type-act_sm-6.gfeat/cope10.feat/stats/cope1.nii.gz"
set fmri(conname_real.1) "pos"
set fmri(conname_real.2) "neg"
Now rerun FEAT on the refreshed Level-3 template. This is the same FEAT logic as before. The only thing that changes is the shared Level-2 derivative tree that feeds the group model.
%%bash
set -e
REFRESH_DERIV_DIR="$HOME/trust_example_higherlevel/refreshed_2525/derivatives/fsl"
rm -rf "${REFRESH_DERIV_DIR}/L3_task-trust_model-01_type-act_cope10_onegroup_fmriprep2525.gfeat"
rm -rf "${REFRESH_DERIV_DIR}/L3_task-trust_model-01_type-act_cope10_onegroup_fmriprep2525+"*.gfeat
rm -rf "${REFRESH_DERIV_DIR}/logs"
echo "Removed any previous refreshed Level-3 derivatives."
Removed any previous refreshed Level-3 derivatives.
%%bash
set -e
ONEGROUP_FSF="$HOME/trust_example_higherlevel/refreshed_2525/derivatives/fsl/L3_task-trust_model-01_type-act_cope10_onegroup_fmriprep2525.fsf"
feat "$ONEGROUP_FSF"
To view the FEAT progress and final report, point your web browser at /home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/L3_task-trust_model-01_type-act_cope10_onegroup_fmriprep2525.gfeat/report_log.html
11. Review the refreshed Level-3 output¶
After rerunning the group model with the refreshed Level-2 derivatives, we want to check two things:
the expected Level-3 outputs exist in the refreshed derivative tree
the one-group reciprocate > defect result now looks much more like the ventral striatal effect we expected
For this notebook, that single refreshed map is enough to make the main teaching point.
refreshed_onegroup_dir = EXAMPLE_DIR / "refreshed_2525" / "derivatives" / "fsl" / "L3_task-trust_model-01_type-act_cope10_onegroup_fmriprep2525.gfeat"
for rel in [
"report.html",
"cope1.feat",
"cope1.feat/mask.nii.gz",
"cope1.feat/thresh_zstat1.nii.gz",
]:
p = refreshed_onegroup_dir / rel
print(f"{p}: {p.exists()}")
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/L3_task-trust_model-01_type-act_cope10_onegroup_fmriprep2525.gfeat/report.html: True
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/L3_task-trust_model-01_type-act_cope10_onegroup_fmriprep2525.gfeat/cope1.feat: True
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/L3_task-trust_model-01_type-act_cope10_onegroup_fmriprep2525.gfeat/cope1.feat/mask.nii.gz: True
/home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/L3_task-trust_model-01_type-act_cope10_onegroup_fmriprep2525.gfeat/cope1.feat/thresh_zstat1.nii.gz: True
The refreshed visualization below repeats the same contrast as before: cope10 (reciprocate > defect). The important difference is that the shared Level-2 inputs were rebuilt after rerunning preprocessing with fMRIPrep 25.2.5. This time, the group map should reveal the expected ventral striatal activation much more clearly.
from ipyniivue import NiiVue
zmap = refreshed_onegroup_dir / "cope1.feat" / "thresh_zstat1.nii.gz"
print("Background exists:", group_bg is not None, group_bg)
print("Contrast exists:", zmap.exists(), zmap)
if group_bg is not None and zmap.exists():
zdata = nib.load(str(zmap)).get_fdata()
zmax = float(np.nanmax(zdata))
print("Max thresholded value:", zmax)
if zmax > 0:
bg_data = nib.load(str(group_bg)).get_fdata()
bg_nonzero = bg_data[bg_data > 0]
lo = float(np.percentile(bg_nonzero, 2))
hi = float(np.percentile(bg_nonzero, 98))
nv = NiiVue()
nv.load_volumes([
{
"path": str(group_bg),
"name": "MNI152_T1_2mm_brain",
"colormap": "gray",
"opacity": 1.0,
"cal_min": lo,
"cal_max": hi,
},
{
"path": str(zmap),
"name": "refreshed mean_pos",
"colormap": "red",
"opacity": 0.75,
},
])
display(nv)
else:
print("The thresholded map contains no voxels above zero, so we skip plotting it.")
else:
print("Could not find the MNI background or the refreshed thresholded group map.")
Background exists: True /cvmfs/neurodesk.ardc.edu.au/containers/fsl_6.0.7.16_20250131/fsl_6.0.7.16_20250131.simg/opt/fsl-6.0.7.16/data/standard/MNI152_T1_2mm_brain.nii.gz
Contrast exists: True /home/jovyan/trust_example_higherlevel/refreshed_2525/derivatives/fsl/L3_task-trust_model-01_type-act_cope10_onegroup_fmriprep2525.gfeat/cope1.feat/thresh_zstat1.nii.gz
Max thresholded value: 6.677373886108398
If you want to generalize this notebook later, the main changes are still straightforward:
change the participant whose Level-1 runs you rerender at Level 2
change the lower-level cope number you want to carry forward to Level 3
change the refreshed archive filename if the OSF file changes
keep the old and refreshed derivative trees separate so the teachable comparison stays explicit
and, most importantly, check the mask before you interpret the activation
12. Dependencies in Jupyter/Python¶
Using the package watermark to document system environment and software versions used in this notebook, alongside the Neurodesktop version extracted from the
JUPYTER_IMAGEorNEURODESKTOP_VERSIONenvironment variables.
import os
%load_ext watermark
%watermark
%watermark --iversions
neurodesktop_version = (
os.environ.get('JUPYTER_IMAGE', '').split(':')[-1] or
os.environ.get('NEURODESKTOP_VERSION', 'unknown')
)
print(f"Neurodesktop version: {neurodesktop_version}")Last updated: 2026-08-20T02:37:22.230890+00:00
Python implementation: CPython
Python version : 3.13.14
IPython version : 9.12.0
Compiler : GCC 14.3.0
OS : Linux
Release : 6.8.0-111-generic
Machine : x86_64
Processor : x86_64
CPU cores : 16
Architecture: 64bit
IPython : 9.12.0
ipyniivue: 2.4.4
nibabel : 5.4.2
numpy : 2.5.1
Neurodesktop version: 2026-07-11
- Smith, D. V. (2026). Fareri 2022 NeuroImage Trust Game: Example Archive for Neurodesk. 10.17605/OSF.IO/KTXUG