# Upstream's last release, v2.5.1 (2021-05), is 64 commits behind master, # which carries CMake modernisation and typo fixes and has been quiet since # 2023-04; the snapshot is what upstream itself builds. %global commit 84ba5fd7672ca7d08f9f60a95ef4b68f0c81a090 %global shortcommit %(c=%{commit}; echo ${c:0:7}) %global snapdate 20230407 # ImplicitFunction (the Implicit Model tool's library): SCIInstitute repo, # untagged; this is its last commit, which the Superbuild also fetched. %global if_commit 93316ba44340f7b6162bf0121d1c519a4960cd60 %global if_shortcommit %(c=%{if_commit}; echo ${c:0:7}) %global if_snapdate 20200709 Name: seg3d Version: 2.5.1^%{snapdate}git%{shortcommit} # Explicit, not %%autorelease -- that macro is inert in this COPR # (ci/PROCEDURES.md golden rule 3). Release: 3%{?dist} Summary: Interactive segmentation of 3D medical and microscopy volumes # src/License.txt is MIT (SCI Institute); 1235 of the 1257 compiled sources # carry the MIT text and 19 carry no header. # # Core/ITKLiveWire/itkLiveWireImageFunction.h is an ITK 3.x-era file # ("Copyright (c) Insight Software Consortium ... See ITKCopyright.txt"), # whose licence was BSD-3-Clause before ITK 4 moved to Apache-2.0. # # Application/Tools/Algorithm/fibheap.{h,cc} is John Boyer's 1996 Fibonacci # heap from Dr. Dobb's Journal: "permission to use and distribute the # software is granted provided that this copyright notice remains in the # source and the author (John Boyer) is acknowledged". SPDX has no # identifier for it and fedora-license-data does not classify it. Fine for # the COPR; needs a fedora-license-data request before any Fedora submission # (KNOWN-ISSUES). The same file already ships in InsightToolkit5 through the # ITKGrowCut remote module. # # ImplicitFunction (Source5) is built into the binary. Its sources carry # the same MIT permission text with no copyright line, two .cpp files carry # no header (their .h files carry the MIT text), and the repository has no # licence file; its authors are SCI Institute staff, as for Seg3D, so it is # taken as MIT. # # TetGen (AGPL-3.0-or-later) is not part of this package: the Implicit # Model tool links Fedora's libtet.so.0 from the tetgen package # dynamically, so its licence does not enter this License: field. # # The bundled tinyxml and the empty googletest submodule are deleted in # %%prep; the Superbuild (which would download Boost, ITK, Python, Qt # helpers, TetGen ...) is not used. License: MIT AND BSD-3-Clause URL: https://github.com/SCIInstitute/Seg3D Source0: %{url}/archive/%{commit}/Seg3D-%{commit}.tar.gz Source1: seg3d.desktop Source2: seg3d.metainfo.xml # %%check: build a test volume and count the voxels of Seg3D's exports. Source3: seg3d-volume-check.py # %%check: the Seg3D side, run with --headless --python. Source4: seg3d-headless-check.py Source5: https://github.com/SCIInstitute/ImplicitFunction/archive/%{if_commit}/ImplicitFunction-%{if_commit}.tar.gz # Build from src/ against system libraries (find_package instead of the # Superbuild's config files), system tinyxml and GoogleTest, Boost compat # defines, ITK IO factories linked, ImplicitFunction built against the # system TetGen. Patch0: seg3d-system-libraries.patch # Boost.Filesystem/Asio/Lambda/tribool changes up to Boost 1.90. Patch1: seg3d-boost-1.90.patch # Embed the system Python 3 through PyConfig instead of a bundled 3.4. Patch2: seg3d-python3-embed.patch # includes (GCC 16), HDF5 1.12+ API, teem's private header. Patch3: seg3d-build-fixes.patch # Report Implicit Model failures; LayerFilter swallows exceptions silently. Patch4: seg3d-implicitmodel-errors.patch # ImplicitFunction (applied in src/ThirdParty/ImplicitFunction): hull normals # that do not depend on TetGen's face winding (1.5 reversed it, inverting # the model), planar input refused instead of aborting in TetGen, two # out-of-bounds reads in the 2D hull path (an abort under Fedora's # _GLIBCXX_ASSERTIONS), test fixes. Patch5: implicitfunction-tetgen-1.5.patch BuildRequires: cmake BuildRequires: ninja-build BuildRequires: gcc-c++ BuildRequires: boost-devel BuildRequires: python3-devel BuildRequires: zlib-ng-compat-devel BuildRequires: libpng-devel BuildRequires: sqlite-devel BuildRequires: teem-devel BuildRequires: glew-devel BuildRequires: mesa-libGLU-devel BuildRequires: freetype-devel BuildRequires: tinyxml-devel BuildRequires: libX11-devel BuildRequires: qt5-qtbase-devel BuildRequires: qt5-qtsvg-devel BuildRequires: gtest-devel BuildRequires: gmock-devel BuildRequires: InsightToolkit5-devel >= 5.4 # ImplicitFunction BuildRequires: tetgen-devel BuildRequires: eigen3-static # ITK's CMake config loads ITKVtkGlue -> find_package(VTK), whose transitive # dependencies vtk-devel does not pull in itself (same list as c3d.spec). BuildRequires: hdf5-devel BuildRequires: eigen3-devel BuildRequires: qt6-qtdeclarative-devel %if 0%{?fedora} BuildRequires: libminc-devel %endif BuildRequires: desktop-file-utils BuildRequires: /usr/bin/appstream-util # GUI smoke test in %%check (xvfb-run comes with the Xvfb package) BuildRequires: xorg-x11-server-Xvfb BuildRequires: mesa-dri-drivers # ITK freezes sonames across releases while adding symbols, so rpm's soname # dependencies cannot see a too-old ITK; floor on the version built against. # The two-part expansion is required: ">= UNSET" is satisfied, so an undefined # macro would make the floor vacuous, which the %%build guard catches. Requires: InsightToolkit5%{?_isa} >= %{?itk_ver}%{!?itk_ver:UNSET} # itk(abi): ITK_LEGACY_REMOVE changes class layouts at unchanged sonames, so the itk_ver floor alone let a # consumer built against the removed state install over the present one (python3-simpleitk -11 on ITK -23 # returned all-zero images). Equality on the legacy-state token; see InsightToolkit5.spec. Requires: itk(abi) = %{?itk_abi}%{!?itk_abi:UNSET} # The viewer's text overlay opens /usr/share/fonts/gnu-free/FreeSerif.ttf by # path (Core/TextRenderer/TextRenderer.cc) and logs an error without it. Requires: gnu-free-serif-fonts Requires: hicolor-icon-theme Provides: bundled(implicitfunction) = 0^%{if_snapdate}git%{if_shortcommit} %description Seg3D is an interactive volume segmentation tool from the SCI Institute, University of Utah. It works on layered data and mask volumes (MRI, CT, microscopy stacks) with manual painting, polyline and speedline tools, ITK filters for thresholding, region growing, level sets and smoothing, image registration, an isosurface view, and an embedded Python console that can script every action. It reads and writes NRRD, NIfTI, DICOM, MATLAB, MRC, TIFF/PNG stacks and the other formats ITK supports. The large-volume converter is installed as Seg3D2-CreateLargeVolume. %prep %autosetup -N -n Seg3D-%{commit} -a 5 %autopatch -p1 -M 4 mv ImplicitFunction-%{if_commit} src/ThirdParty/ImplicitFunction %patch -P 5 -p1 -d src/ThirdParty/ImplicitFunction rm -r src/ThirdParty/tinyxml src/ThirdParty/submodules/googletest Superbuild %build test -n "%{?itk_ver}" || { echo "ERROR: itk_ver undefined - needs InsightToolkit5-devel's macros.itk" >&2; exit 1; } test -n "%{?itk_abi}" || { echo "ERROR: itk_abi undefined - needs InsightToolkit5-devel >= 5.4.7-24 (macros.itk)" >&2; exit 1; } # -fpermissive: GCC 16 rejects a few pre-C++17 idioms in the tree. # -DNDEBUG: upstream builds Release; without it the Python start-up and the # log streamer print debug output to stderr. export CXXFLAGS="%{build_cxxflags} -fpermissive -DNDEBUG" # SEG3D_BITS=64 selects the 64-bit code paths (SCI_64BITS); the Superbuild # sets it from the pointer size, which is 64 on every Fedora architecture. %cmake -S src -G Ninja \ -DCMAKE_CXX_STANDARD=17 \ -DSEG3D_BITS=64 \ -DSEG3D_BUILD_INTERFACE=ON \ -DBUILD_WITH_PYTHON=ON \ -DBUILD_LARGE_VOLUME_TOOLS=ON \ -DBUILD_MOSAIC_TOOLS=OFF \ -DBUILD_TESTING=ON %cmake_build %install # Upstream has no Linux install rules (only CPack bundles for macOS and # Windows); resources are compiled in through Qt's resource system. install -Dpm 0755 %{__cmake_builddir}/Seg3D2 %{buildroot}%{_bindir}/Seg3D2 install -Dpm 0755 %{__cmake_builddir}/CreateLargeVolume \ %{buildroot}%{_bindir}/Seg3D2-CreateLargeVolume desktop-file-install --dir=%{buildroot}%{_datadir}/applications %{SOURCE1} install -Dpm 0644 src/Resources/Icons/seg3d2_128.png \ %{buildroot}%{_datadir}/icons/hicolor/128x128/apps/seg3d.png install -Dpm 0644 src/Resources/Icons/seg3d2_256.png \ %{buildroot}%{_datadir}/icons/hicolor/256x256/apps/seg3d.png install -Dpm 0644 %{SOURCE2} %{buildroot}%{_metainfodir}/seg3d.metainfo.xml %check desktop-file-validate %{buildroot}%{_datadir}/applications/seg3d.desktop appstream-util validate-relax --nonet %{buildroot}%{_metainfodir}/seg3d.metainfo.xml export HOME=$(mktemp -d) # Upstream's unit tests (53 cases in 7 suites). Application_Socket_Tests # initialises the Python interpreter once per test case, and Python 3.14 # aborts on a second PyImport_AppendInittab in one process, so its two cases # run as separate processes. %ctest --exclude-regex 'Application_Socket_Tests|ImplicitFunction_Tests' for t in StartSocket ConnectToSocket; do %{__cmake_builddir}/Application_Socket_Tests --gtest_filter=ActionSocketTests.$t done # ImplicitFunction's suite, including upstream's Seg3DIntegrationTest of the # 3D (TetGen) path against reference values. The three Basic* cases ask for # a 3D convex hull of a planar triangle, which TetGen 1.5 cannot build; # Patch5 makes that an exception, checked by PlanarInputTo3DHullThrows. %{__cmake_builddir}/ImplicitFunction_Tests --gtest_filter='-RBFInterfaceTest.Basic*' # Functional test of the installed binary, headless and in the GUI under # Xvfb: read the same volume through teem (NRRD) and ITK (MetaImage), # threshold both, grow an ITK ConfidenceConnected region, fit an implicit # model through points on the ball (3D convex hull with TetGen, and 2D), export NRRD # masks and count their voxels. A broken ITK IO factory or ITK ABI shows up # as an empty mask, not a crash, so exact counts are the oracle; the fitted # model's edge voxels can differ between architectures, so it is checked by # Dice overlap with the ball (0.99 on x86_64; the inverted model scores 0.0002). exe=%{buildroot}%{_bindir}/Seg3D2 for mode in headless gui; do out=$(mktemp -d) %{python3} -I %{SOURCE3} make $out/in if [ $mode = headless ]; then run="$exe --headless" else run="xvfb-run -a -s '-screen 0 1280x1024x24' $exe --nosplash" fi SEG3D_CHECK_IN=$out/in SEG3D_CHECK_OUT=$out \ timeout 300 sh -c "$run --python=%{SOURCE4}" | tee $out/log grep -q '^seg3d-check: exported' $out/log %{python3} -I %{SOURCE3} count $out/both/*.nrrd 4351 %{python3} -I %{SOURCE3} count $out/ball/*.nrrd 3071 %{python3} -I %{SOURCE3} count $out/itkball/*.nrrd 3071 %{python3} -I %{SOURCE3} count $out/grown/*.nrrd 3071 %{python3} -I %{SOURCE3} ball $out/implicit/*.nrrd 0.97 # 2D hull path: only that it runs (it read past the end of its point # arrays before Patch5) and gives a mask; which side is positive there is # an open upstream question (docs/upstream/seg3d-system-libraries.md). %{python3} -I %{SOURCE3} nonempty $out/implicit2d/*.nrrd done %files %license src/License.txt %doc README.md src/ReleaseNotes.txt %{_bindir}/Seg3D2 %{_bindir}/Seg3D2-CreateLargeVolume %{_datadir}/applications/seg3d.desktop %{_datadir}/icons/hicolor/128x128/apps/seg3d.png %{_datadir}/icons/hicolor/256x256/apps/seg3d.png %{_metainfodir}/seg3d.metainfo.xml %changelog * Fri Oct 09 2026 Morgan Hough - 2.5.1^20230407git84ba5fd-3 - Enable the Implicit Model tool: ImplicitFunction (93316ba) built in and linked to Fedora's tetgen dynamically; License: unchanged - ImplicitFunction: orient hull normals towards the centroid (TetGen 1.5 reversed the face winding and inverted the model), refuse planar input to the 3D hull instead of aborting in TetGen, fix two out-of-bounds reads in the 2D hull path that abort Seg3D under _GLIBCXX_ASSERTIONS, test fixes - Report Implicit Model errors instead of dropping them - %%check: ImplicitFunction's test suite, and implicit models fitted to the test ball headless and under Xvfb (3D hull: Dice >= 0.97; 2D: runs) * Fri Oct 09 2026 Morgan Hough - 2.5.1^20230407git84ba5fd-2 - Link Boost.Chrono: Boost 1.83 on Fedora 43 does not resolve boost::chrono::steady_clock::now() otherwise (-1 failed to link there) * Thu Oct 08 2026 Morgan Hough - 2.5.1^20230407git84ba5fd-1 - Initial package: master 84ba5fd built from src/ against system libraries (ITK under itk(abi), Boost 1.90, Python 3.14, Qt 5, teem, tinyxml) - Implicit Model tool left out (TetGen is AGPL-3.0-or-later) - %%check: upstream unit tests and a headless + Xvfb GUI pipeline whose exported masks must have exact voxel counts