BIDS: run_fastsurfer_bids.py¶
run_fastsurfer_bids.py is a BIDS-App-style entrypoint for FastSurfer.
It discovers subjects and sessions in a BIDS dataset and hands them to the existing entrypoints: it writes a subject
list and calls brun_fastsurfer.sh, or srun_fastsurfer.sh with --slurm. No part of the
pipeline is reimplemented here, and every option it does not define itself is passed through unchanged.
It needs no additional dependencies. What it reads from a dataset (subject, session, T1w/T2w) is spelled out by the
BIDS directory layout itself, so discovery is a glob over sub-<label>/[ses-<label>/]anat/.
Usage¶
$ ./run_fastsurfer_bids.py --help
usage: run_fastsurfer_bids.py [-h] [--participant_label LABEL [LABEL ...]]
[--session_label LABEL [LABEL ...]] [--use_t2]
[--skip_bids_validator]
[--fs_license FS_LICENSE] [--slurm] [--dry]
bids_dir output_dir {participant,group}
BIDS-App entrypoint for FastSurfer.
Discovers subjects and sessions in a BIDS dataset and hands them to the existing FastSurfer
entrypoints: it writes a subject list and calls brun_fastsurfer.sh, or srun_fastsurfer.sh with
--slurm. It does not reimplement any part of the pipeline, and every option it does not define
itself is passed through unchanged.
Each session is processed on its own, as one cross-sectional case. Longitudinal processing, where
the timepoints of a subject are conditioned on a person-specific template, is a different
scientific method rather than a different spelling of this one, and is run with long_fastsurfer.sh.
positional arguments:
bids_dir Path to the BIDS-valid input dataset.
output_dir Output directory, used as FastSurfer's SUBJECTS_DIR.
Each session becomes the directory
<output_dir>/sub-<label>_ses-<label>.
{participant,group} Level of analysis. Only 'participant' performs
processing; 'group' is a no-op.
options:
-h, --help show this help message and exit
--participant_label LABEL [LABEL ...], --participant-label LABEL [LABEL ...]
Restrict processing to these participant labels (with
or without 'sub-' prefix). Default: process all
subjects found.
--session_label LABEL [LABEL ...], --session-label LABEL [LABEL ...]
Restrict processing to these session labels (with or
without 'ses-' prefix). Default: process all sessions
found.
--use_t2 Also pass the T2w image of each session, which
switches the hypothalamus module to its multimodal
mode. Off by default, because whether a T2 is used
changes the result, so it is a choice for the whole
study rather than something the presence of a file
decides. Sessions without a T2w are still processed,
without one.
--skip_bids_validator
Skip validation of the input dataset against the BIDS
specification. Validation uses the external bids-
validator tool and is skipped with a warning if it is
not installed.
--fs_license FS_LICENSE
Path to the FreeSurfer license file (passed through to
run_fastsurfer.sh).
--slurm EXPERIMENTAL. Submit the cases to slurm via
srun_fastsurfer.sh instead of running them locally via
brun_fastsurfer.sh. Cluster options such as
--partition or --work are passed through after the
literal '--'. Check the output of --dry before relying
on it.
--dry, --dry_run Print the commands that would be run, without
executing them (same spelling as srun_fastsurfer.sh).
Any options after a literal '--' are passed through unchanged to brun_fastsurfer.sh (or srun_fastsurfer.sh), e.g.:
run_fastsurfer_bids.py /bids /out participant -- --seg_only --3T
Basic example¶
./run_fastsurfer_bids.py /data/my_bids_dataset /data/fastsurfer_output participant \
--participant_label 01 02 --fs_license /data/license.txt -- --threads 4
This processes sub-01 and sub-02 from the dataset at /data/my_bids_dataset. Any options after a literal --
are passed through unchanged to brun_fastsurfer.sh or srun_fastsurfer.sh (see RUN_FASTSURFER.md,
BATCH.md and SLURM.md for the full set).
In Docker¶
The image’s entrypoint is run_fastsurfer.sh, so a BIDS run overrides it. Override it with
tools/Docker/entrypoint.sh rather than with the script itself: that is what activates the virtual environment the
pipeline runs in, and it takes the script to run as its first argument.
docker run --gpus all -v $HOME/my_bids_dataset:/data:ro -v $HOME/my_fastsurfer_analysis:/output \
-v $HOME/my_fs_license.txt:/fs_license/license.txt \
--entrypoint "/fastsurfer/tools/Docker/entrypoint.sh" \
--rm --user $(id -u):$(id -g) deepmi/fastsurfer:latest \
/fastsurfer/run_fastsurfer_bids.py \
/data /output participant --fs_license /fs_license/license.txt \
-- --3T --threads 4
On a cluster, --slurm submits the same cases through srun_fastsurfer.sh instead, with its options given after the
-- as well:
./run_fastsurfer_bids.py /data/my_bids_dataset /data/fastsurfer_output participant --slurm \
--fs_license /data/license.txt -- --partition gpu --work /scratch/fastsurfer
Warning
--slurm is experimental. Check the output of --dry before relying on it. Two things differ from the local route:
--data is set to bids_dir, because srun_fastsurfer.sh rewrites every path in the subject list relative to it
before binding it into the container, and the paths are written unquoted, because that rewrite is done with awk and a
quote stops it from matching. A dataset whose path holds a space is therefore refused with --slurm, which is a
limitation of srun_fastsurfer.sh rather than of BIDS input: neither of its input routes handles a space.
Output naming¶
output_dir is used directly as FastSurfer’s SUBJECTS_DIR, and every session becomes one directory in it, named
sub-<label>_ses-<label>:
fastsurfer_output/
├── dataset_description.json
├── bids_subjects.txt
├── sub-01_ses-1/
├── sub-01_ses-2/
└── sub-02_ses-1/
Flat, not nested under sub-<label>/ses-<label>/. This is the layout FreeSurfer tooling expects of a SUBJECTS_DIR,
so every downstream FreeSurfer or FastSurfer command works on the output directory unchanged. A dataset with no
session level keeps the plain sub-<label> as the directory name. Note this means output_dir is a FreeSurfer
subjects directory that carries a dataset_description.json for provenance, not a valid BIDS-derivatives dataset,
which would require the nested layout.
dataset_description.json is written if there is not one there already, and records which of the two processing
models produced the directory. The longitudinal pipeline names its timepoints the same way this names its sessions,
so sub-01_ses-1 from a cross-sectional run and sub-01_ses-1 from a longitudinal run are the same directory name
holding results of different methods. One output directory therefore holds one model, and a run into a directory
recorded as the other one is refused rather than silently mixed.
The generated subject list is kept as output_dir/bids_subjects.txt, so a run can be repeated or amended with
brun_fastsurfer.sh directly.
output_dir must not be the dataset itself or lie inside one of its subjects, since the output would then be found as
input by the next run. <bids_dir>/derivatives/fastsurfer is the usual place inside a dataset.
Sessions¶
Every session is processed on its own, as one cross-sectional case. Longitudinal processing, where the timepoints of a
subject are conditioned on a person-specific template, is run with long_fastsurfer.sh; it is a
different scientific method rather than a different spelling of this one, and this entrypoint does not choose it for
you.
T1w and T2w input¶
Only *_T1w.nii[.gz] and *_T2w.nii[.gz] are considered.
A T2w image is used only with --use_t2, which passes it as --t2 and switches the
HypVINN hypothalamus module to its multimodal mode. That changes what
the module computes, so it is a choice for the whole study rather than something the presence of a file decides:
using a T2 where one happens to exist and not where it does not would put two methods in one set of results. Where
--use_t2 is given and some sessions have no T2w, those sessions are processed without one and a warning names them.
A session with several T1w images (for example several run- or acq- entities) is an error rather than a silent
pick of the first, since which image to process is a statement about the data. Restrict the dataset, or process that
session with run_fastsurfer.sh directly. An image that is a link to content that is not there, as in a DataLad
dataset before datalad get, is an error too.
--participant_label and --session_label restrict what is processed and accept the labels with or without their
sub-/ses- prefix. A label that the dataset does not hold is an error rather than an empty run, and where
--session_label is given, a subject with no session level is skipped, since none of its data can be the session that
was asked for.
Validation¶
The dataset is validated with the bids-validator command line tool
if it is installed, and skipped with a warning if it is not. --skip_bids_validator says that this is intended.
Dry run¶
--dry prints the subject list and the command that would be executed, and writes nothing, which is the cheap way to
check what was discovered before committing to a full run. The flag is spelled as in srun_fastsurfer.sh, which also
accepts --dry_run.
test/integration/openneuro_check.sh does the same against real data. It fetches public OpenNeuro data for a few BIDS
layouts (several sessions of one subject, a T2w in only some sessions, no session level), runs them to a chosen depth
(dry, segmentation or full), and checks the outputs. With --slurm it submits the cases instead, and a later call
with --check_only checks the output once the jobs are done. It is run by hand, not by CI.