# SlicerElastix — image registration GUI for 3D Slicer wrapping the elastix # registration toolbox. PURE-SCRIPTED (Python) module, so — like 3dslicer-openlifu # — we replicate slicerMacroBuildScriptedModule directly (drop the module's # Python + resources into Slicer's qt-scripted-modules) rather than running its # CMake. This needs no find_package(Slicer) and no foundation -devel, so it is # independent of the C++ extension-build (foundation -45) work. # # elastix itself runs as an external CLI (the `elastix` binary, packaged # separately in this COPR); the module locates it at runtime. %global commit 507db1994cfd717cbf77cbfb0e2c6920caf9bbb0 %global shortcommit %(c=%{commit}; echo ${c:0:8}) %global snapdate 20260218 %global slicer_inst %{_prefix}/lib/slicer %global slicer_subdir Slicer-5.12 %global qtsm %{slicer_inst}/lib/%{slicer_subdir}/qt-scripted-modules Name: 3dslicer-elastix Version: 1.0 Release: 0.6.%{snapdate}git%{shortcommit}%{?dist} Summary: Elastix image-registration extension for 3D Slicer License: MIT URL: https://github.com/lassoan/SlicerElastix Source0: %{url}/archive/%{commit}/SlicerElastix-%{shortcommit}.tar.gz # The module cannot find a distribution-installed elastix: every path it tries is # relative to the module itself, and Fedora's binary is /usr/bin/elastix. It consults # PATH nowhere, so every operation raises 'Elastix not found' unless the user fills in # the custom-path setting by hand -- despite this package's Requires: elastix. Adds # shutil.which as a last resort. Found by the neurodebian session packaging this as a # .deb and confirmed to affect Fedora identically. Upstreamable as-is. Patch10: 3dslicer-elastix-find-elastix-on-path.patch BuildArch: noarch Requires: 3dslicer Requires: elastix >= 5.0 # Scripted modules need the bug#9 scriptability layer to load. Requires: ctk-python Requires: python3-vtkAddon %description SlicerElastix wraps the elastix intensity-based image-registration toolbox in 3D Slicer's GUI: rigid/affine/BSpline and multi-resolution registration driven by a database of 100+ ready-made elastix parameter presets, with forward/inverse transform application. elastix runs as an external command-line tool (packaged separately); this extension provides the Slicer-side interface and presets. %prep %autosetup -p1 -n SlicerElastix-%{commit} # Post-condition for Patch10. autosetup shipped without -p1 once and patch had no # file to work on; assert the fallback actually landed rather than trusting that # the patch step ran. grep -q 'shutil.which(self.elastixFilename)' Elastix/Elastix.py \ || { echo "Patch10 did not land: no PATH fallback in Elastix/Elastix.py" >&2; exit 1; } echo "Patch10 present: elastix is looked up on PATH as a last resort" %build # Pure-scripted: nothing to compile. %install mkdir -p %{buildroot}%{qtsm}/ElastixLib mkdir -p %{buildroot}%{qtsm}/Resources/Icons mkdir -p %{buildroot}%{qtsm}/Resources/UI mkdir -p %{buildroot}%{qtsm}/Resources/RegistrationParameters # Module script + its Python helper package install -m0644 Elastix/Elastix.py %{buildroot}%{qtsm}/ install -m0644 Elastix/ElastixLib/*.py %{buildroot}%{qtsm}/ElastixLib/ # Resources (icon, UI, the registration-parameter preset database) install -m0644 Elastix/Resources/Icons/Elastix.png %{buildroot}%{qtsm}/Resources/Icons/ install -m0644 Elastix/Resources/UI/*.ui %{buildroot}%{qtsm}/Resources/UI/ install -m0644 Elastix/Resources/RegistrationParameters/*.txt \ %{buildroot}%{qtsm}/Resources/RegistrationParameters/ # ElastixParameterSetDatabase.xml is the INDEX over those .txt files. # ElastixLib/database.py hard-codes that filename as DATABASE_FILE and reads it to # build the preset list, so without it getRegistrationPresets() raises # ValueError: Failed to open parameter set database: .../ElastixParameterSetDatabase.xml # the preset dropdown is empty, and all 102 parameter files we DO ship are unreachable. # The *.txt glob above silently skipped it. With it present the module reports 29 preset # sets over those 102 files. Found by the neurodebian session by running the module; # invisible to the build, to rpmlint and to any install test. install -m0644 Elastix/Resources/RegistrationParameters/ElastixParameterSetDatabase.xml \ %{buildroot}%{qtsm}/Resources/RegistrationParameters/ test -f %{buildroot}%{qtsm}/Resources/RegistrationParameters/ElastixParameterSetDatabase.xml || { echo "ERROR: the preset database index is missing; every preset would be unreachable." >&2 exit 1 } %files %license LICENSE %doc README.md %{qtsm}/Elastix.py # Elastix-owned dirs (NOT the shared qt-scripted-modules / Resources / UI / Icons # dirs, which the 3dslicer package owns). %dir %{qtsm}/ElastixLib %{qtsm}/ElastixLib/*.py %dir %{qtsm}/Resources/RegistrationParameters %{qtsm}/Resources/RegistrationParameters/*.txt %{qtsm}/Resources/RegistrationParameters/ElastixParameterSetDatabase.xml %{qtsm}/Resources/Icons/Elastix.png %{qtsm}/Resources/UI/Elastix.ui %{qtsm}/Resources/UI/PresetManager.ui %changelog * Tue Sep 29 2026 Morgan Hough - 1.0-0.6.20260218git507db199 - Apply Patch10 with -p1. autosetup was declared without it, so patch defaulted to -p0 and skipped Elastix/Elastix.py -- the build failed in %prep on both chroots (11046882). Same one-flag cause as pipelines and spharm-pdm; all three specs grew their first patch this cycle, and none of them had ever needed -p1 before. - Assert the post-condition too: grep for the shutil.which fallback after autosetup. * Mon Sep 28 2026 Morgan Hough - 1.0-0.5.20260218git507db199 - Ship ElastixParameterSetDatabase.xml. It is the INDEX over the 102 parameter files this package already installs, and the install glob was *.txt so it was silently skipped. ElastixLib/database.py hard-codes the filename, so without it getRegistrationPresets() raises and the preset dropdown is empty -- every one of those 102 files unreachable. Verified against the published rpm: 103 entries under RegistrationParameters, zero of them the XML. Now asserted at build time. - Patch10 makes the module find a distribution-installed elastix. Every path getElastixBinDir() tries is relative to the module, covering a Slicer build tree or a self-bundling extension but never /usr/bin/elastix, and the module consults PATH nowhere. So every operation raised 'Elastix not found' on a system where elastix is installed and this package Requires it. - Both found by the neurodebian session while packaging SlicerElastix as a .deb, by RUNNING the module rather than reading it. Neither is visible to the build, to rpmlint, to repoclosure or to an install test. I verified both against our own published rpm before changing anything. * Fri Sep 25 2026 Morgan Hough - 1.0-0.4.%%{snapdate}git%%{shortcommit} - Release 0.2 -> 0.4, to get git back ahead of the repo. f44 (both arches) serves 0.3 while git says 0.2, so any rebuild from git produced 0.4-less-than-0.3 and superseded nothing -- the package could not be updated on f44 at all. - No content to recover. The published 0.3 SRPM differs from git by exactly TWO LINES, the Release itself: someone bumped to 0.3, built it on f44, and the bump never reached git. Verified by fetching the 0.3 SRPM and diffing, for all three extensions, rather than assuming a lost spec revision. - Skips 0.3 deliberately: a 0.3 here would tie the published f44 builds rather than beat them, and COPR then adds a sibling at an existing NVR while dnf serves the oldest. - Found by rpi-the-great while reconciling the f45 arch gap; same class as mrtrix3 and ANTs3. * Wed Jul 22 2026 Morgan Hough - 1.0-0.2.20260218git507db199 - Retarget from Slicer-5.11 to Slicer-5.12 core (3dslicer 5.12.1); bump 3dslicer-devel floor to 5.12.1. * Tue Jun 16 2026 Morgan Hough - 1.0-0.1.20260218git507db199 - Initial package. SlicerElastix as a pure-scripted 3D Slicer extension: install the Elastix module + ElastixLib + 100+ registration-parameter presets into qt-scripted-modules (replicating slicerMacroBuildScriptedModule), no compilation / no foundation -devel needed. elastix CLI is a runtime Requires.