Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,15 @@ The images we provide on [Docker Hub](https://hub.docker.com/r/deepmi/fastsurfer
### Usage
All installation methods use the `run_fastsurfer.sh` call interface (replace the placeholder `<fastsurfer_flags>` with [FastSurfer flags](doc/scripts/RUN_FASTSURFER.md#required-arguments)), which is the general starting point for FastSurfer. However, there are different ways to call this script depending on the installation, which we explain here:

1. For container installations, you need to set up the container (`<singularity_flags>` or `<docker_flags>`) in addition to the `<fastsurfer_flags>`:
1. For container installations, the [launcher](doc/overview/CONTAINERS.md#the-launcher) is the easiest way: it takes the `<fastsurfer_flags>` and writes and runs the container command, with the image for your NVIDIA GPU (or AMD GPU, experimental, or the CPU):

```bash
curl -fsSLO https://deep-mi.org/FastSurfer/stable/fastsurfer
chmod +x fastsurfer
./fastsurfer <fastsurfer_flags>
```

Written by hand, the container command needs the container's setup (`<singularity_flags>` or `<docker_flags>`) in addition to the `<fastsurfer_flags>`:
1. For __Singularity__, the syntax is

```text
Expand Down
11 changes: 10 additions & 1 deletion doc/CONVENTIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,13 @@ Names are snake_case, except `subjectX` and the file names of container images.
example `-v C:/Users/user/my_mri_data:/home/user/my_mri_data`. The license file is mounted from its made-up path:
`-v C:/path/to/your/freesurfer/license_file:/home/user/freesurfer_license`.

## Shared setup

What each system needs before FastSurfer runs (a container runtime, WSL2, Docker Desktop) is written once, in
`doc/overview/install/setup/`, and included in the quick start and the install page of that system with
`:relative-docs: .`. Links in these files are relative to that folder. `exclude_patterns` in `doc/conf.py` keeps them
from becoming pages of their own.

## Line length

Lines in code fences in the documentation are at most 80 characters, so there is no scroll bar. Count the rendered
Expand Down Expand Up @@ -157,7 +164,9 @@ supported versions.
`doc/conf.py`), with a separate text for `{{ FASTSURFER_VERSION }}`, `{{ CUDA_STRING }}` and both: that the commands
use the latest release (in the development documentation), and that images for other CUDA versions are available on
Docker Hub. Do not add such notes by hand. Where the version is not about an image, such as the folder of the macOS
package, use `{{ PACKAGE_VERSION }}`, the same version without the note.
package, use `{{ PACKAGE_VERSION }}`, the same version without the note. The download of the launcher uses
`{{ LAUNCHER_URL }}`, the copy published next to the pages of the same tree (`stable` or `dev`). `README.md` is
shown on GitHub, where nothing is substituted, so it names the `stable` copy.

What this tree builds comes from this tree, not from that release: `{{ CUDA_DEFAULT_STRING }}` and
`{{ ROCM_DEFAULT_STRING }}` (with `{{ CUDA_DEFAULT_VERSION }}` and `{{ ROCM_DEFAULT_VERSION }}`) are the default CUDA
Expand Down
6 changes: 6 additions & 0 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ def _tool_values_gitref(ref: str | None, *keys: str) -> tuple[str, ...]:
"PYTHON_VERSION": version_python,
"UBUNTU_VERSION": version_ubuntu,
"FREESURFER_VERSION": version_freesurfer,
# the launcher published next to this tree's pages (html_extra_path), so each tree links to its own copy
"LAUNCHER_URL": f"https://deep-mi.org/FastSurfer/{'stable' if documents_a_release else 'dev'}/fastsurfer",
}

templates_path = ["_templates"]
Expand All @@ -220,6 +222,8 @@ def _tool_values_gitref(ref: str | None, *keys: str) -> tuple[str, ...]:
# instructions for writing the documentation, not part of it
"AGENTS.md",
"CONVENTIONS.md",
# the setup of each system, included in the quick start and the install pages rather than pages of their own
"overview/install/setup/*",
]


Expand All @@ -239,6 +243,8 @@ def _tool_values_gitref(ref: str | None, *keys: str) -> tuple[str, ...]:
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
html_theme = "furo"
html_static_path = ["_static"]
# served next to the pages, so the launcher downloads from deep-mi.org/FastSurfer/<stable|dev>/
html_extra_path = ["../tools/fastsurfer"]
html_js_files = ["doc-version-link.js"] # points the announcement bar at the sibling doc tree
html_title = project
html_show_sphinx = False
Expand Down
51 changes: 42 additions & 9 deletions doc/overview/CONTAINERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ as a "simulated computer inside the computer".

The launcher
------------
`fastsurfer_container.py` writes and runs the container command for you. It takes the same flags as
The launcher `fastsurfer` writes and runs the container command for you. It takes the same flags as
`run_fastsurfer.sh` and needs only Python 3.8 or newer, not FastSurfer itself. It

- uses Apptainer, Singularity or Docker, whichever is installed (choose one with `--runtime`),
- picks the image that runs on your NVIDIA GPU and driver, or the CPU image without one, see
[which image fits your GPU](install/LINUX.md#nvidia-gpus); with several GPUs and no
`--device cuda:<index>`, it uses the newest one with enough memory and says which,
- runs the [ROCm image](install/LINUX.md#amd-gpus-experimental) on an AMD GPU (experimental) if there
is no NVIDIA GPU, or with `--image rocm`,
- downloads the image once (for Apptainer, into `$HOME/my_singularity_images`),
- shares the files and directories the flags name with the container, at the same paths, so relative
paths work too,
Expand All @@ -37,8 +39,9 @@ The launcher
Download it, and run FastSurfer:

```bash
curl -fsSLO https://raw.githubusercontent.com/Deep-MI/FastSurfer/stable/tools/fastsurfer_container.py
python3 fastsurfer_container.py \
curl -fsSLO {{ LAUNCHER_URL }}
chmod +x fastsurfer
./fastsurfer \
--t1 $HOME/my_mri_data/subjectX/t1_weighted.nii.gz \
--sid subjectX --sd $HOME/my_fastsurfer_analysis \
--3T --threads 4
Expand All @@ -59,18 +62,48 @@ version, it says how many releases it is behind. A GPU that the newest images no
them on the CPU. The image of an older release may still support that GPU, but the launcher
recommends the newest release on the CPU, or a machine with a newer GPU, over an old version.

With `--brun`, it runs `brun_fastsurfer.sh` for several subjects; the paths in a subjects list have
to be absolute. `--print_only` prints the commands instead of running them, `--update_launcher`
`--exec <program>` runs another program of the image instead of `run_fastsurfer.sh`. It comes last, as
all arguments after the program go to the program. The other FastSurfer scripts take FastSurfer's flags
and are handled like `run_fastsurfer.sh`:

```bash
# several subjects; the paths in a subjects list have to be absolute
./fastsurfer --exec brun_fastsurfer.sh \
--subjects_list $HOME/my_mri_data/subjects_list.txt \
--sd $HOME/my_fastsurfer_analysis
# the time points of one person (longitudinal processing)
./fastsurfer --exec long_fastsurfer.sh --tid subjectX \
--t1s $HOME/my_mri_data/subjectX/t1_weighted_20210315.nii.gz \
$HOME/my_mri_data/subjectX/t1_weighted_20230920.nii.gz \
--tpids subjectX_20210315 subjectX_20230920 \
--sd $HOME/my_fastsurfer_analysis
```

([long_fastsurfer.sh](../scripts/long_fastsurfer.rst) explains longitudinal processing.) Any other
program runs in the current directory, for example to convert a segmentation to NIfTI:

```bash
./fastsurfer --exec nib-convert \
subjectX/mri/aparc.DKTatlas+aseg.deep.mgz aparc.nii.gz
```

The launcher shares the current directory with the container, as it does the directories of absolute
paths in the arguments, so relative paths only work inside the current directory. If several FastSurfer
images are installed, such a program uses the newest instead of asking.

`--print_only` prints the commands instead of running them, `--update_launcher`
replaces the launcher with the current one, and `--help` lists all launcher options. The sections
below explain the commands it runs.

Before starting many runs at once, e.g. a SLURM array, run the launcher once (e.g. on one subject),
so the image is downloaded and built only once rather than by every job.

On a Mac with Apple silicon, use the [macOS package](install/MACOS.md) instead: the images are built for
Intel and AMD processors, which such a Mac only emulates, much more slowly and without its GPU. The
launcher therefore stops there and points to the package, unless you pass `--runtime docker`. With
Docker, it also warns if Docker may use less memory than FastSurfer needs.
On a Mac with Apple silicon, the launcher runs the installed [macOS package](install/MACOS.md) instead,
with the same flags and `--exec`: the images are built for Intel and AMD processors, which such a Mac
only emulates, much more slowly and without its GPU. It chooses among installed package versions as
among images, and `--image 2.6.0` keeps a study on one version. Without a package, `--update`
downloads it and opens the macOS Installer. To run an image in Docker anyway, pass `--runtime docker`.
With Docker, the launcher also warns if Docker may use less memory than FastSurfer needs.

Using Apptainer (or Singularity)
--------------------------------
Expand Down
5 changes: 3 additions & 2 deletions doc/overview/INSTALL.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
Installation
============
FastSurfer works the same way on every system: you call `run_fastsurfer.sh` with a T1-weighted MRI image. How you
install it depends on your system. Pick yours:
FastSurfer works the same way on every system: you call `run_fastsurfer.sh` with a T1-weighted MRI image. To try it,
the [quick start](QUICKSTART.md#set-up-your-computer) sets up your computer and runs FastSurfer with the launcher in
a few steps. How you install it for your own work depends on your system. Pick yours:

````{grid} 1 2 2 2
:gutter: 3
Expand Down
135 changes: 65 additions & 70 deletions doc/overview/QUICKSTART.md
Original file line number Diff line number Diff line change
@@ -1,114 +1,109 @@
Quick Start
===========
This example segments one brain MRI in a few minutes. Choose how you run FastSurfer: in a container on Linux
(Apptainer, Singularity or Docker), with the [macOS package](install/MACOS.md), or without installing anything in
[Google Colab](#google-colab). Other systems are covered in the [installation guide](INSTALL.md).
This example segments one brain MRI in a few minutes with `fastsurfer`, a launcher that runs FastSurfer with the
same commands on Linux, Windows and macOS. It takes the flags of `run_fastsurfer.sh` and sets up the rest: on Linux,
Windows and Intel Macs, it picks, downloads and runs the right container image; on a Mac with Apple silicon, it runs
the installed macOS package. You can also try FastSurfer without installing anything in
[Google Colab](#google-colab).

Segment an example image
------------------------
With a GPU (8 GB of graphics memory) this takes well under a minute; without one, FastSurfer uses the CPU and takes
a few minutes longer. You can use your own T1-weighted full head MRI (0.7 to 1 mm voxel sizes, no preprocessing,
`.nii`, `.nii.gz` or `.mgz`), or the example image the commands download.
The launcher is meant for getting started and for single images. For larger projects, such as whole datasets or
runs on an HPC cluster, we recommend running FastSurfer directly, which gives full control over images, paths and
resources: see the [installation guide](INSTALL.md), [Running FastSurfer in a container](CONTAINERS.md), and the
scripts for [many subjects](../scripts/BATCH.md) and for [SLURM clusters](../scripts/SLURM.md).

Set up your computer
--------------------
Once, set up what the launcher runs FastSurfer with:

`````{tab-set}

````{tab-item} Apptainer / Singularity
```bash
# 0. Create a directory for this test
mkdir fastsurfer_test
cd fastsurfer_test
````{tab-item} Linux
:sync: linux

# 1. Build the Apptainer image from our Docker image (only the first time)
mkdir -p $HOME/my_singularity_images
singularity build \
$HOME/my_singularity_images/fastsurfer-{{ CUDA_STRING }}-v{{ FASTSURFER_VERSION }}.sif \
docker://deepmi/fastsurfer:{{ CUDA_STRING }}-v{{ FASTSURFER_VERSION }}
```{include} install/setup/linux.md
:relative-docs: .
```

# 2. Download an example brain MRI (if you don't have your own)
# If you have your own, copy it to this directory and adjust
# the filename after --t1 below.
curl -k \
https://surfer.nmr.mgh.harvard.edu/pub/data/tutorial_data/buckner_data/tutorial_subjs/140/mri/orig.mgz \
-o "./140_orig.mgz"
The launcher picks the image for your NVIDIA GPU (or AMD GPU, experimental, or the CPU) and downloads it on the
first run. [Linux](install/LINUX.md) explains the images.
````

# 3. Run FastSurfer (full brain segmentation only)
singularity exec --nv \
--no-mount home,cwd -e \
-B "$PWD" \
$HOME/my_singularity_images/fastsurfer-{{ CUDA_STRING }}-v{{ FASTSURFER_VERSION }}.sif \
/fastsurfer/run_fastsurfer.sh \
--t1 "$PWD/140_orig.mgz" \
--sid subjectX --sd "$PWD" \
--seg_only --no_biasfield --no_cereb --no_hypothal
````{tab-item} Windows
:sync: windows

```{include} install/setup/windows.md
:relative-docs: .
```

[Windows](install/WINDOWS.md) has more details.
````

````{tab-item} Docker
```bash
# 0. Create a directory for this test
mkdir fastsurfer_test
cd fastsurfer_test
````{tab-item} Mac with Apple silicon
:sync: macos

# 1. Download an example brain MRI (if you don't have your own)
# If you have your own, copy it to this directory and adjust
# the filename after --t1 below.
curl -k \
https://surfer.nmr.mgh.harvard.edu/pub/data/tutorial_data/buckner_data/tutorial_subjs/140/mri/orig.mgz \
-o "./140_orig.mgz"
FastSurfer runs natively with the [macOS package](install/MACOS.md), which uses the Mac's GPU (M1 or newer).
Download and install it with the button on that page, or let the launcher do it: after step 1 below,
`./fastsurfer --update` downloads the package and opens the macOS Installer. macOS may block the installer, because
it is not signed by Apple yet; [Install](install/MACOS.md#install) explains how to allow it.
````

````{tab-item} Intel Mac
:sync: macos-intel

FastSurfer runs in Docker, on the CPU (the macOS package needs Apple silicon):

# 2. Run FastSurfer (full brain segmentation only)
docker run --gpus all -v "$PWD:$PWD" \
--rm --user $(id -u):$(id -g) \
deepmi/fastsurfer:{{ CUDA_STRING }}-v{{ FASTSURFER_VERSION }} \
--t1 "$PWD/140_orig.mgz" \
--sid subjectX --sd "$PWD" \
--seg_only --no_biasfield --no_cereb --no_hypothal
```{include} install/setup/macos_intel.md
:relative-docs: .
```
````

````{tab-item} macOS package
[Install the package](install/MACOS.md), open the FastSurfer app from your Applications folder, and run these
commands in the Terminal window it opens:
`````

If the launcher still cannot run FastSurfer, it says what is missing and how to fix it.

Segment an example image
------------------------
With a GPU (8 GB of graphics memory) this takes well under a minute; without one, FastSurfer uses the CPU and takes
a few minutes longer. You can use your own T1-weighted full head MRI (0.7 to 1 mm voxel sizes, no preprocessing,
`.nii`, `.nii.gz` or `.mgz`), or the example image the commands download. On Windows, run the commands in the
Ubuntu terminal.

```bash
# 0. Create a directory for this test
mkdir fastsurfer_test
cd fastsurfer_test

# 1. Download an example brain MRI (if you don't have your own)
# 1. Download the launcher (only the first time)
curl -fsSLO {{ LAUNCHER_URL }}
chmod +x fastsurfer

# 2. Download an example brain MRI (if you don't have your own)
# If you have your own, copy it to this directory and adjust
# the filename after --t1 below.
curl -k \
https://surfer.nmr.mgh.harvard.edu/pub/data/tutorial_data/buckner_data/tutorial_subjs/140/mri/orig.mgz \
-o "./140_orig.mgz"

# 2. Run FastSurfer (full brain segmentation only)
run_fastsurfer.sh --t1 "$PWD/140_orig.mgz" \
--sid subjectX --sd "$PWD" \
# 3. Run FastSurfer (full brain segmentation only)
./fastsurfer --t1 140_orig.mgz --sid subjectX --sd . \
--seg_only --no_biasfield --no_cereb --no_hypothal
```
````

`````

That's it, it will run the full brain segmentation. For speed, we switched off the cerebellum and hypothalamic sub-segmentation (would add a couple minutes).
We also switched off the bias field correction, which is used to compute partial volume estimates for the statsfiles, so you might want to switch it on again if you want the volume statistics text file (under ```subjectX/stats```).
Also if you need the estimated total intracranial volume for correcting the stats, you would either need to run the surface stream or switch on the Talairach registration with
`--tal_reg` in the segmentation module. For the full surface stream, just remove the ```--seg_only```; you then need a [FreeSurfer license file](INSTALL.md#freesurfer-license) and pass it into the container, see [Running FastSurfer in a container](CONTAINERS.md).
`--tal_reg` in the segmentation module. For the full surface stream, just remove the ```--seg_only```; you then need a [FreeSurfer license file](INSTALL.md#freesurfer-license): pass it with `--fs_license <path>`, or set the environment variable `FS_LICENSE` to its path, which the launcher passes on.

You will find the full brain segmentation in ```./subjectX/mri/aparc.DKTatlas+aseg.deep.mgz``` in FreeSurfer's MGZ file format. To convert it back to nifti (if you prefer), run `nib-convert`, which comes with FastSurfer, for example with the Singularity image (in the macOS console, call `nib-convert` directly):
You will find the full brain segmentation in ```./subjectX/mri/aparc.DKTatlas+aseg.deep.mgz``` in FreeSurfer's MGZ file format. To convert it back to nifti (if you prefer), run `nib-convert`, which comes with FastSurfer:

```bash
# Convert mgz to nifti
singularity exec --nv \
--no-mount home -e \
-B "$PWD" \
$HOME/my_singularity_images/fastsurfer-{{ CUDA_STRING }}-v{{ FASTSURFER_VERSION }}.sif \
nib-convert "$PWD/subjectX/mri/aparc.DKTatlas+aseg.deep.mgz" \
"$PWD/subjectX/mri/aparc.DKTatlas+aseg.deep.nii.gz"
./fastsurfer --exec nib-convert \
subjectX/mri/aparc.DKTatlas+aseg.deep.mgz \
subjectX/mri/aparc.DKTatlas+aseg.deep.nii.gz
```

and find the segmentation in ```./subjectX/mri/aparc.DKTatlas+aseg.deep.nii.gz```. If you have FreeSurfer installed, just use FreeView to look at the result (or really any other image viewer):
Then find the segmentation in ```./subjectX/mri/aparc.DKTatlas+aseg.deep.nii.gz```. If you have FreeSurfer installed, just use FreeView to look at the result (or really any other image viewer):

```bash
# FreeView
Expand Down
Loading
Loading