From b0ddf51cbae4e5e0290509a99ac0639eb39bc18a Mon Sep 17 00:00:00 2001 From: tctco Date: Sun, 2 Aug 2026 22:10:46 +0800 Subject: [PATCH] Fix bundled DCCCcore launch from UI --- localizer/lib/ai_decoupling.py | 6 ++++-- localizer/lib/core_executable.py | 12 ++++++++++++ localizer/lib/metric_calculator.py | 6 ++++-- localizer/localizer.py | 3 ++- localizer/src/CMakeLists.txt | 2 +- localizer/src/conanfile.py | 2 +- localizer/src/core/config/Version.h | 2 +- .../tests/test_ui_metric_command_builder.py | 19 +++++++++++++++++-- 8 files changed, 42 insertions(+), 10 deletions(-) create mode 100644 localizer/lib/core_executable.py diff --git a/localizer/lib/ai_decoupling.py b/localizer/lib/ai_decoupling.py index c4f6ba1..13ee35e 100644 --- a/localizer/lib/ai_decoupling.py +++ b/localizer/lib/ai_decoupling.py @@ -11,8 +11,10 @@ try: from .macos_security import append_macos_security_hint + from .core_executable import dccccore_executable_path except ImportError: from macos_security import append_macos_security_hint + from core_executable import dccccore_executable_path class AIDecouplingLogic: @@ -31,7 +33,7 @@ def __init__(self, plugin_path): plugin_path: Plugin directory path """ self.plugin_path = Path(plugin_path) - self.executable_path = self.plugin_path / "cpp" / "CentiloidCalculator" + self.executable_path = dccccore_executable_path(self.plugin_path) self.executable_dir = self.plugin_path / "cpp" self.last_volume_name = None @@ -138,7 +140,7 @@ def _load_result_volumes(self): Returns: tuple: (foreground_node, background_node, stripped_node) """ - # Expected output file patterns (may vary based on CentiloidCalculator version) + # Expected output file patterns (may vary based on DCCCcore version) potential_files = { "foreground": "Normalized_AD_prob_map.nii", "background": "Normalized.nii", diff --git a/localizer/lib/core_executable.py b/localizer/lib/core_executable.py new file mode 100644 index 0000000..d50cc95 --- /dev/null +++ b/localizer/lib/core_executable.py @@ -0,0 +1,12 @@ +"""Resolve the bundled DCCCcore executable path.""" + +import sys +from pathlib import Path + + +def dccccore_executable_path(plugin_path, platform=None): + """Return the platform-specific DCCCcore executable bundled with the UI.""" + + platform = platform or sys.platform + executable_name = "DCCCcore.exe" if platform == "win32" else "DCCCcore" + return Path(plugin_path) / "cpp" / executable_name diff --git a/localizer/lib/metric_calculator.py b/localizer/lib/metric_calculator.py index 59f950e..61e0a84 100644 --- a/localizer/lib/metric_calculator.py +++ b/localizer/lib/metric_calculator.py @@ -2,7 +2,7 @@ Metric calculation module for PET semi-quantitative analysis Contains functionality for Centiloid, CenTauR, and CenTauRz calculations -using the new subcommand-based CentiloidCalculator executable +using the subcommand-based DCCCcore executable """ import os @@ -14,8 +14,10 @@ try: from .macos_security import append_macos_security_hint + from .core_executable import dccccore_executable_path except ImportError: from macos_security import append_macos_security_hint + from core_executable import dccccore_executable_path class MetricCalculatorLogic: @@ -42,7 +44,7 @@ def __init__(self, plugin_path): plugin_path: Plugin directory path """ self.plugin_path = Path(plugin_path) - self.executable_path = self.plugin_path / "cpp" / "CentiloidCalculator" + self.executable_path = dccccore_executable_path(self.plugin_path) self.last_volume_name = None self._current_process = None self._process_stdout = [] diff --git a/localizer/localizer.py b/localizer/localizer.py index deeef62..813a7bd 100644 --- a/localizer/localizer.py +++ b/localizer/localizer.py @@ -20,6 +20,7 @@ from lib.metric_calculator import MetricCalculatorLogic from lib.ai_decoupling import AIDecouplingLogic from lib.atlas_manager import AtlasManager +from lib.core_executable import dccccore_executable_path from lib.ui_components import TimeConsumingMessageBox, MarkupManager @@ -92,7 +93,7 @@ def __init__(self, parent=None) -> None: def _setPaths(self): self.PLUGIN_PATH = Path(os.path.dirname(__file__)) - self.EXECUTABLE_PATH = self.PLUGIN_PATH / "cpp" / "CentiloidCalculator" + self.EXECUTABLE_PATH = dccccore_executable_path(self.PLUGIN_PATH) self.EXECUTABLE_DIR = self.PLUGIN_PATH / "cpp" def _setNodes(self): diff --git a/localizer/src/CMakeLists.txt b/localizer/src/CMakeLists.txt index 2e7c733..92ec770 100644 --- a/localizer/src/CMakeLists.txt +++ b/localizer/src/CMakeLists.txt @@ -1,7 +1,7 @@ # CMakeList.txt: DCCCcore Refactored Version cmake_minimum_required(VERSION 3.21) -project(DCCCcore VERSION 4.2.4) +project(DCCCcore VERSION 4.2.5) set(DCCCCORE_VERSION_SUFFIX "") set(DCCCCORE_SOFTWARE_VERSION "${PROJECT_VERSION}${DCCCCORE_VERSION_SUFFIX}") diff --git a/localizer/src/conanfile.py b/localizer/src/conanfile.py index 6d74bdb..a558a7e 100644 --- a/localizer/src/conanfile.py +++ b/localizer/src/conanfile.py @@ -4,7 +4,7 @@ class AppConan(ConanFile): name = "DCCCcore" - version = "4.2.4" + version = "4.2.5" settings = "os", "arch", "compiler", "build_type" generators = "CMakeDeps", "CMakeToolchain" diff --git a/localizer/src/core/config/Version.h b/localizer/src/core/config/Version.h index 5525386..9248faf 100644 --- a/localizer/src/core/config/Version.h +++ b/localizer/src/core/config/Version.h @@ -1,4 +1,4 @@ #pragma once #include -const std::string SOFTWARE_VERSION = "4.2.4"; +const std::string SOFTWARE_VERSION = "4.2.5"; diff --git a/localizer/src/tests/test_ui_metric_command_builder.py b/localizer/src/tests/test_ui_metric_command_builder.py index 4b4671e..1e09d52 100644 --- a/localizer/src/tests/test_ui_metric_command_builder.py +++ b/localizer/src/tests/test_ui_metric_command_builder.py @@ -26,6 +26,21 @@ class _DummyQProcess: MetricCalculatorLogic = _load_metric_calculator_logic() +def test_bundled_core_executable_matches_packaged_name(): + logic = MetricCalculatorLogic("/tmp/plugin") + executable_name = "DCCCcore.exe" if sys.platform == "win32" else "DCCCcore" + + assert logic.executable_path == Path("/tmp/plugin/cpp") / executable_name + + +def test_bundled_core_executable_uses_exe_suffix_on_windows(): + from core_executable import dccccore_executable_path + + assert dccccore_executable_path( + "/tmp/plugin", platform="win32" + ) == Path("/tmp/plugin/cpp/DCCCcore.exe") + + def test_build_command_uses_subcommand_cli_for_centaur(): logic = MetricCalculatorLogic("/tmp/plugin") @@ -92,10 +107,10 @@ def test_macos_security_hint_mentions_quarantine_command(monkeypatch): message = append_macos_security_hint( "Operation not permitted", - "/tmp/plugin/cpp/CentiloidCalculator", + "/tmp/plugin/cpp/DCCCcore", returncode=126, ) assert "macOS may have blocked DCCCcore" in message assert "xattr -dr com.apple.quarantine" in message - assert "/tmp/plugin/cpp/CentiloidCalculator" in message + assert "/tmp/plugin/cpp/DCCCcore" in message