Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/workflows/quicktest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ concurrency:

on:
pull_request:
types: [labeled, unlabeled]
types: [labeled]
workflow_dispatch:
inputs:
docker-image:
Expand Down
4 changes: 2 additions & 2 deletions FastSurferCNN/run_prediction.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,8 +249,8 @@ def __init__(
raise ValueError(
f"Could not find the ColorLUT in {lut}, please make sure the --lut argument is valid."
) from err
self.labels = self.lut["ID"].values
self.torch_labels = torch.from_numpy(np.asarray(self.lut["ID"].values))
self.labels = np.asarray(self.lut["ID"].values).copy()
self.torch_labels = torch.from_numpy(self.labels)
self.names = ["SubjectName", "Average", "Subcortical", "Cortical"]
self.cfg_fin, cfg_cor, cfg_sag, cfg_ax = args2cfg(cfg_ax, cfg_cor, cfg_sag, batch_size=batch_size)
# the order in this dictionary dictates the order in the view aggregation
Expand Down
33 changes: 18 additions & 15 deletions tools/Docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@
# - AUTHOR:
# The author string to include in image labels.
# - default: "David Kügler <david.kuegler@dzne.de>"
# - DEVICE:
# The device type to build the python environment for, this affects the installed torch packages.
# Supported values are what is supported by uv, e.g.: cu128, xpu, rocm6.2.4, etc.
# - default: cu128
# - DEBUG:
# If set to "true", retains build debug output during build.
# - default: false
# - INSECURE_FLAG:
# If set to "--insecure", will download freesurfer without verifying the ssl certificate.
# - default: ""

# DOCUMENTATION FOR TARGETS (use '--target <VALUE>'):
# To select which imaged will be tagged with '-t'
Expand Down Expand Up @@ -91,6 +101,7 @@ ARG AUTHOR="David Kügler <david.kuegler@dzne.de>"
ARG BUILDKIT_SBOM_SCAN_CONTEXT="true"
ARG DEVICE="cu128"
ARG DEBUG="false"
ARG INSECURE_FLAG=""

FROM ghcr.io/astral-sh/uv:$UV_VERSION AS selected_uv_install_image

Expand Down Expand Up @@ -200,7 +211,13 @@ RUN --mount=type=bind,source=tools/build/install_fs_pruned.sh,target=/install/in
--mount=type=bind,source=tools/build/link_fs.sh,target=/install/link_fs.sh \
--mount=type=cache,target=/install/download \
--mount=type=bind,source=pyproject.toml,target=/install/pyproject.toml <<EOF
/install/install_fs_pruned.sh /opt --upx --url $FREESURFER_URL
# the INSECURE_FLAG build arg may be set to "--insecure" to skip ssl certificate verification during download
# for production environments, this should never be used. This option is only provided to deal with an outdated
# ssl certificate on the freesurfer download server.
if [[ -n "$INSECURE_FLAG" ]]; then
echo "SECURITY NOTICE: Downloading freesurfer for the build image without ssl validation."
fi
/install/install_fs_pruned.sh /opt --upx --url $FREESURFER_URL $INSECURE_FLAG
/install/link_fs.sh /opt/freesurfer
EOF

Expand Down Expand Up @@ -299,20 +316,6 @@ ENV PYTHONPATH=/fastsurfer:/opt/freesurfer/python/packages \

RUN <<EOF
source /venv/bin/activate
# Fix for cuda11.8+cudnn8.7 bug+warning: https://github.com/pytorch/pytorch/issues/97041
if [[ "$DEVICE" == "cu118" ]]
then
python3 <<CU118FIX
from pathlib import Path
import torch

p = Path(torch.__file__).parent / "lib"
targets = list(p.glob("libnvrtc-*.so.11.2"))
if len(targets) != 1:
raise RuntimeError(f"Could not find libnvrtc-*.so.11.2 in {p}!")
(p / "libnvrtc.so").symlink_to(p / targets[0])
CU118FIX
fi
cd /fastsurfer
# Download all remote network checkpoints already
python3 FastSurferCNN/download_checkpoints.py --all
Expand Down
38 changes: 16 additions & 22 deletions tools/Docker/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

# Author: David Kuegler
# June 27th 2023
# Modified February 2026

import argparse
import logging
Expand Down Expand Up @@ -325,6 +326,11 @@ def make_parser() -> argparse.ArgumentParser:
help=f"explicitly specifies the base image to build the build images from "
f"(default: {DEFAULTS.BUILD_BASE_IMAGE}).",
)
expert.add_argument(
"--insecure",
action="store_true",
help="disables certificate check for downloads, e.g. freesurfer.",
)
expert.add_argument(
"--debug",
action="store_true",
Expand Down Expand Up @@ -628,6 +634,7 @@ def main(
dry_run: bool = False,
tag_dev: bool = True,
fastsurfer_home: Path | None = None,
insecure: bool = False,
**keywords,
) -> int | str:
from FastSurferCNN.version import has_git, parse_build_file
Expand All @@ -644,7 +651,9 @@ def main(
fastsurfer_home = Path(fastsurfer_home) if fastsurfer_home else default_home()
# read the freesurfer download url from pyproject.toml
with open(fastsurfer_home / "pyproject.toml", "rb") as fp:
pyproject_freesurfer = tomllib.load(fp)["tool"]["freesurfer"]
pyproject_toml = tomllib.load(fp)
pyproject_repository_url = pyproject_toml["project"]["urls"]["source"]
pyproject_freesurfer = pyproject_toml["tool"]["freesurfer"]

if target not in get_args(Target):
raise ValueError(f"Invalid target: {target}")
Expand All @@ -660,6 +669,7 @@ def main(
f"DEVICE={DEFAULTS.MapDeviceType.get(device, 'cpu')}",
f"FREESURFER_URL={pyproject_freesurfer['urls']['linux'].format(version=pyproject_freesurfer['version'])}",
f"FREESURFER_VERSION={pyproject_freesurfer['version']}",
f"INSECURE_FLAG={'--insecure' if insecure else ''}",
]
if debug:
kwargs["build_arg"].append("DEBUG=true")
Expand Down Expand Up @@ -700,13 +710,14 @@ def main(
build_info = parse_build_file(build_file)

if has_git():
repository_url = get_repository_url(build_info["git_status"], build_info["git_branch"])
kwargs["build_arg"].extend([
f"REPOSITORY_URL={repository_url}",
f"GIT_HASH={build_info['git_hash']}",
f"GIT_HASH={build_info['git_hash']}",
f"REPOSITORY_URL={pyproject_repository_url}/tree/{build_info['git_branch']}",
])
if "github.com/tree/stable" in repository_url:
if build_info["git_branch"] == "stable":
kwargs["build_arg"].append("DOC_URL=https://deep-mi.org/fastsurfer/stable")
else:
kwargs["build_arg"].append(f"REPOSITORY_URL={pyproject_repository_url}/tree/dev")
kwargs["build_arg"].append(f"FASTSURFER_VERSION={build_info['version_tag']}")
version_tag = build_info["version_tag"]
image_prefix = ""
Expand Down Expand Up @@ -750,23 +761,6 @@ def main(
return 0


def get_repository_url(git_status_text: str, branch: str) -> str:
"""Get the repository URL of the current git repository."""
from FastSurferCNN.utils.run_tools import Popen

remote = git_status_text.removeprefix(f"## {branch}...").split("/")[0]
repository_process = Popen(["git", "remote", "get-url", remote], stdout=subprocess.PIPE).finish()
if repository_process.retcode != 0:
logger.error(repository_process.err_str())
raise RuntimeError("Could not get the repository URL from git.")
repository_url = repository_process.out_str().strip()
if repository_url.endswith(".git"):
repository_url = repository_url[:-4]
if repository_url.startswith("git@"):
repository_url = "https://" + repository_url[4:].replace(":/", "/")
return repository_url + "/tree/" + branch


def default_home() -> Path:
"""
Find the fastsurfer path.
Expand Down