From 661a407b81b702436f892eb73ccde4d2413ecaf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20K=C3=BCgler?= Date: Wed, 4 Feb 2026 18:58:14 +0100 Subject: [PATCH 1/5] Fix cuda 11.8 docker build --- tools/Docker/Dockerfile | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/tools/Docker/Dockerfile b/tools/Docker/Dockerfile index 06e1db13..76c143d2 100644 --- a/tools/Docker/Dockerfile +++ b/tools/Docker/Dockerfile @@ -299,20 +299,6 @@ ENV PYTHONPATH=/fastsurfer:/opt/freesurfer/python/packages \ RUN < Date: Fri, 30 Jan 2026 12:53:45 +0100 Subject: [PATCH 2/5] Expose the --insecure flag for install_fs_pruned through tools/Docker/build.py Add missing buildarg documentation in tools/Docker/Dockerfile --- tools/Docker/Dockerfile | 19 ++++++++++++++++++- tools/Docker/build.py | 7 +++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/tools/Docker/Dockerfile b/tools/Docker/Dockerfile index 76c143d2..b0295c90 100644 --- a/tools/Docker/Dockerfile +++ b/tools/Docker/Dockerfile @@ -62,6 +62,16 @@ # - AUTHOR: # The author string to include in image labels. # - default: "David Kügler " +# - 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 '): # To select which imaged will be tagged with '-t' @@ -91,6 +101,7 @@ ARG AUTHOR="David Kügler " 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 @@ -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 < 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", @@ -628,6 +633,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 @@ -660,6 +666,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") From 866ea59aeb2c197ecff2acb45961b8d16a801b11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20K=C3=BCgler?= Date: Mon, 2 Feb 2026 14:42:58 +0100 Subject: [PATCH 3/5] Only perform quicktest when adding the quicktest label (no longer when removing) --- .github/workflows/quicktest.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/quicktest.yaml b/.github/workflows/quicktest.yaml index 03c4a31f..eaa53437 100644 --- a/.github/workflows/quicktest.yaml +++ b/.github/workflows/quicktest.yaml @@ -24,7 +24,7 @@ concurrency: on: pull_request: - types: [labeled, unlabeled] + types: [labeled] workflow_dispatch: inputs: docker-image: From 27ea7c785fc90218b12d07a66b6774250140be5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20K=C3=BCgler?= Date: Wed, 4 Feb 2026 17:45:15 +0100 Subject: [PATCH 4/5] Get the repository URL from pyproject instead of git remote --- tools/Docker/build.py | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/tools/Docker/build.py b/tools/Docker/build.py index b0dc40aa..f76ce963 100755 --- a/tools/Docker/build.py +++ b/tools/Docker/build.py @@ -16,6 +16,7 @@ # Author: David Kuegler # June 27th 2023 +# Modified February 2026 import argparse import logging @@ -650,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}") @@ -707,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 = "" @@ -757,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. From 499c092dcf334b2b65b1a9cc3d10519e974cd7de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20K=C3=BCgler?= Date: Wed, 4 Feb 2026 19:33:56 +0100 Subject: [PATCH 5/5] Fix numpy array not writable warning in run_prediction.py --- FastSurferCNN/run_prediction.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FastSurferCNN/run_prediction.py b/FastSurferCNN/run_prediction.py index b5a6b30f..cd79317c 100644 --- a/FastSurferCNN/run_prediction.py +++ b/FastSurferCNN/run_prediction.py @@ -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