# brainvisa-anatomist -- Anatomist, the BrainVISA viewer: 2D/3D display and # fusion of volumes, meshes, textures, fibre bundles, ROIs and the cortical # sulci graphs of Morphologist, with pyanatomist (Python bindings and the # scripted-view API). Built on its own against the installed BrainVISA core # (brainvisa-aims-devel), as upstream's bv_maker does for the "anatomist" # project. # # Layout facts the spec depends on (checked against the pinned commits): # - Two repositories in one CMake tree: anatomist-free (CeCILL-B; the viewer, # its libraries and plugins) and anatomist-gpl (CeCILL 2.0; pyanatomist). # Pins are the soma-env 6.0 branch's (brainvisa/soma-env@6.0 # conf/sources.d/soma-env.json), dated 2026-08-06. # - Building against an installed AIMS needed fixes below Anatomist too # (brainvisa-cmake -3, brainvisa-soma -6); here: Patch0 (Qt 6 definitions # and the Qt tool lookup) and Patch1 (pyanatomist with SIP 6.17 and its # template generation). # - anatomist-free's src/lib/gradientwidget (five files) is from Fraqtive, # (C) 2005 Michal Mecinski, "licensed under the GNU General Public License" # with no version, hence COPYING (GPL-2) next to LICENSE and # GPL-1.0-or-later below. src/anavtk is not built (needs vtkINRIA3D). # - "anatomist" is a Python launcher that runs Anatomist inside an IPython # kernel (soma.qt_gui.ipkernel_tools); anatomist-bin is the C++ program. %global bvver 6.0 %global snapdate 20260806 %global free_c 07b99e3aff4ed232fd9f0ac76695b275ca46429e %global gpl_c 6a0570dcefb4702dde2c35cc34a5d398993281fd %global free_s %(c=%{free_c}; echo ${c:0:7}) %global pyreldir %(echo %{python3_sitearch} | sed 's|^%{_prefix}/||') %global somaver 6.0.20^20260806git9ea2121-6 Name: brainvisa-anatomist Version: 6.0.18^%{snapdate}git%{free_s} Release: 1%{?dist} Summary: Anatomist: BrainVISA's viewer for brain volumes, meshes and graphs # CeCILL-B: anatomist-free. CECILL-2.0: anatomist-gpl (pyanatomist). # GPL-1.0-or-later: anatomist-free's Fraqtive gradient widget (no version). License: CECILL-B AND CECILL-2.0 AND GPL-1.0-or-later URL: https://brainvisa.info/ Source0: https://github.com/brainvisa/anatomist-free/archive/%{free_c}/anatomist-free-%{free_c}.tar.gz Source1: https://github.com/brainvisa/anatomist-gpl/archive/%{gpl_c}/anatomist-gpl-%{gpl_c}.tar.gz Source2: brainvisa-anatomist.desktop Source3: brainvisa-anatomist.metainfo.xml # anatomist-free (submitted upstream by the packager): do not # add_definitions() Qt 6's module definitions (a generator expression broke # every compile command); call find_package(QtVersion) so a standalone build # has moc and lrelease. Patch0: brainvisa-anatomist-free-fedora-fixes.patch # anatomist-gpl (submitted upstream by the packager): import aims.sip after # the Qt modules (SIP 6.17); run maketemplates.py with execute_process (the # shell of exec_program split its arguments and nothing was generated). Patch1: brainvisa-anatomist-gpl-fedora-fixes.patch BuildRequires: brainvisa-cmake >= 6.0.0^20260918git850b6f3-3 BuildRequires: brainvisa-aims-devel >= %{somaver} BuildRequires: python3-brainvisa-aims >= %{somaver} BuildRequires: cmake BuildRequires: make BuildRequires: gcc-c++ BuildRequires: python3-devel BuildRequires: python3-numpy BuildRequires: sip6 BuildRequires: python3-pyqt6-devel BuildRequires: qt6-qtbase-devel BuildRequires: qt6-qtmultimedia-devel BuildRequires: qt6-qtwebengine-devel BuildRequires: qt6-qttools-devel BuildRequires: qt6-linguist BuildRequires: mesa-libGL-devel BuildRequires: mesa-libGLU-devel BuildRequires: zlib-devel BuildRequires: desktop-file-utils BuildRequires: libappstream-glib # %%check: a headless session with Mesa's software renderer. BuildRequires: xorg-x11-server-Xvfb BuildRequires: xorg-x11-xauth BuildRequires: mesa-dri-drivers BuildRequires: python3-ipykernel # qtwebengine is not built for every architecture. ExclusiveArch: %{qt6_qtwebengine_arches} Requires: python3-brainvisa-anatomist%{?_isa} = %{version}-%{release} Requires: python3-brainvisa-aims%{?_isa} >= %{somaver} Requires: python3-ipykernel Requires: hicolor-icon-theme Recommends: python3-qtconsole %description Anatomist is the visualisation application of the BrainVISA suite. It displays and fuses 3D and 4D images, triangular meshes with textures, fibre bundles, regions of interest and the cortical sulci graphs produced by Morphologist, in linked 2D and 3D views with shared referentials. It reads the formats of the AIMS library (NIfTI, GIFTI, DICOM, MINC and the AIMS formats). %package devel Summary: Development files for the Anatomist libraries Requires: %{name}%{?_isa} = %{version}-%{release} Requires: python3-brainvisa-anatomist%{?_isa} = %{version}-%{release} Requires: brainvisa-aims-devel%{?_isa} >= %{somaver} %description devel Headers, CMake configuration and SIP files for building Anatomist plugins and other BrainVISA components against Anatomist. %package -n python3-brainvisa-anatomist Summary: Python bindings and scripting API for Anatomist (pyanatomist) Requires: %{name}%{?_isa} = %{version}-%{release} Requires: python3-brainvisa-aims%{?_isa} >= %{somaver} Requires: python3-pyqt6 %description -n python3-brainvisa-anatomist pyanatomist: the "anatomist" Python package (anatomist.api, the direct and headless implementations, and the SIP bindings anatomist.cpp) to drive Anatomist from Python, plus the Python tools anasimpleviewer.py, anaAtlasViewer.py, anaSulciSnapshot.py, ana_atlas_nonlin.py and ana_demo.py. %prep %setup -q -c -T tar -xzf %{SOURCE0} && mv anatomist-free-%{free_c} anatomist-free tar -xzf %{SOURCE1} && mv anatomist-gpl-%{gpl_c} anatomist-gpl %patch -P0 -p1 -d anatomist-free %patch -P1 -p1 -d anatomist-gpl %build %set_build_flags mkdir -p bvbuild cd bvbuild S=$PWD/.. cat > bv_maker.cmake < CMakeLists.txt </dev/null \ | xargs -0r sed -i -e 's|%{_prefix}/lib/|%{_libdir}/|g' -e 's|${prefix}/lib\b|${prefix}/%{_lib}|g' %endif # The Python tools have no "#!" line at all; the launcher says "env python". for f in %{buildroot}%{_bindir}/*.py; do head -c2 "$f" | grep -q '^#!' || sed -i '1i #!%{python3}' "$f" done %py3_shebang_fix %{buildroot}%{_bindir}/* # Generic names do not belong in %%{_bindir}; these are pyanatomist helpers. mkdir -p %{buildroot}%{_libexecdir}/anatomist mv %{buildroot}%{_bindir}/autocrop.py %{buildroot}%{_bindir}/mosaic.py %{buildroot}%{_libexecdir}/anatomist/ # Modules and data with a "#!" but no execute bit are not run directly. find %{buildroot}%{python3_sitearch} %{buildroot}%{_datadir} -type f ! -perm /111 \ -exec sed -i '1{/^#!/d}' {} + find %{buildroot}%{_datadir} -type f -perm /111 -exec sed -i '1{/^#!/d}' {} + -exec chmod 0644 {} + desktop-file-install --dir=%{buildroot}%{_datadir}/applications %{SOURCE2} install -Dpm 0644 %{SOURCE3} %{buildroot}%{_metainfodir}/info.brainvisa.anatomist.metainfo.xml install -Dpm 0644 ../anatomist-free/doc/images/anaLogo.png \ %{buildroot}%{_datadir}/icons/hicolor/96x96/apps/brainvisa-anatomist.png install -Dpm 0644 ../anatomist-free/sphinxman/images/anaicon.png \ %{buildroot}%{_datadir}/icons/hicolor/64x64/apps/brainvisa-anatomist.png # File lists instead of %%exclude on ELF files (an excluded file still gets # its build-id link in the excluding package). (cd %{buildroot} ls -1d .%{_libdir}/lib*.so.* | sed 's|^\.||' | grep -v '/libpyanatomist' > %{_builddir}/anatomist-libs.files) %check desktop-file-validate %{buildroot}%{_datadir}/applications/brainvisa-anatomist.desktop appstream-util validate-relax --nonet %{buildroot}%{_metainfodir}/info.brainvisa.anatomist.metainfo.xml export LD_LIBRARY_PATH=%{buildroot}%{_libdir} export PYTHONPATH=%{buildroot}%{python3_sitearch} export HOME=$PWD/check-home QT_QPA_PLATFORM=xcb LIBGL_ALWAYS_SOFTWARE=1 mkdir -p $HOME # A volume in an axial window and a mesh in a 3D window, a 3D snapshot # through Mesa (llvmpipe), then a clean close. xvfb-run -a -s "-screen 0 1024x768x24" %{python3} -W ignore - <<'EOF' import numpy as np, os from soma import aims import anatomist.direct.api as ana a = ana.Anatomist('-b') v = aims.Volume(np.arange(16 * 16 * 8, dtype=np.int16).reshape(16, 16, 8)) v.header()['voxel_size'] = [1., 1., 1.] av = a.toAObject(v) w = a.createWindow('Axial') w.addObjects(av) m = aims.SurfaceGenerator.sphere(aims.Point3df(8, 8, 4), 5., 50) am = a.toAObject(m) w3 = a.createWindow('3D') w3.addObjects(am) f = os.path.abspath('snapshot.png') w3.snapshot(f, 200, 200) assert os.path.getsize(f) > 10000, os.path.getsize(f) from PyQt6.QtGui import QImage img = QImage(f) grey = {img.pixelColor(x, y).lightness() for x in range(0, 200, 5) for y in range(0, 200, 5)} assert len(grey) > 20, 'blank snapshot: %d grey levels' % len(grey) w.removeObjects(av); w3.removeObjects(am) del w, w3, av, am a.close() print('Anatomist: volume and mesh displayed, snapshot rendered, closed cleanly') EOF %files -f %{_builddir}/anatomist-libs.files %license anatomist-free/LICENSE anatomist-free/COPYING %doc anatomist-free/README.md %{_bindir}/anatomist %{_bindir}/anatomist-bin %{_bindir}/mkhierarchy-anatomist %{_datadir}/anatomist-%{bvver}/ %exclude %{_datadir}/anatomist-%{bvver}/sip %{_datadir}/applications/brainvisa-anatomist.desktop %{_metainfodir}/info.brainvisa.anatomist.metainfo.xml %{_datadir}/icons/hicolor/*/apps/brainvisa-anatomist.png %files devel %{_includedir}/anatomist/ %{_includedir}/pyanatomist/ %{_libdir}/lib*.so %{_datadir}/anatomist-%{bvver}/sip/ %{_datadir}/anatomist-free-%{bvver}/ %{_datadir}/anatomist-gpl-%{bvver}/ %files -n python3-brainvisa-anatomist %license anatomist-gpl/LICENSE %{_bindir}/ana*.py %{_libexecdir}/anatomist/ %{_libdir}/libpyanatomist*.so.* %{python3_sitearch}/anatomist/ %changelog * Thu Oct 15 2026 Morgan Hough - 6.0.18^20260806git07b99e3-1 - Initial package: anatomist-free and anatomist-gpl at the soma-env 6.0 pins, built against brainvisa-aims-devel with Qt 6 and SIP 6. Desktop entry, AppStream metadata and icons added (none upstream); generic helper scripts moved out of %%{_bindir}. %%check renders a volume and a mesh headless through Mesa.