%global pypi_name pyRadPlan Name: python-pyradplan Version: 0.8.0 Release: 2%{?dist} Summary: Radiotherapy treatment planning: photon and ion dose calculation and optimisation # The bundled generic machine data, the TG119 phantom and the RBE table come from matRad # (GPL-3.0). The same copyright holder (DKFZ) distributes them in pyRadPlan under the # repository's BSD-3-Clause licence, and no file in the sdist carries another licence. License: BSD-3-Clause URL: https://github.com/e0404/pyRadPlan Source0: %{pypi_source pyradplan} BuildArch: noarch BuildRequires: python3-devel BuildRequires: pyproject-rpm-macros BuildRequires: python3-pytest # pyRadPlan's conftest makes array-api-strict the preferred non-NumPy backend; it needs the # 2024.12 standard, so this repository's array-api-strict 2.6 (Fedora has 2.0.1). BuildRequires: python3-array-api-strict >= 2.4 # DICOM import needs ITK's DCMTKImageIO pixel-spacing fix (5.4.7-27, Patch7); before it x # and y spacing came back swapped. docs/KNOWN-ISSUES.md "ITK DCMTKImageIO". BuildRequires: InsightToolkit5 >= 5.4.7-27 %global _description %{expand: pyRadPlan is a multi-modality radiotherapy treatment planning toolkit in Python, a reimplementation of the MATLAB toolkit matRad (DKFZ). It provides CT and structure-set models, beam steering geometry, pencil-beam dose engines for photons (SVD kernel) and ions (protons, helium, carbon, oxygen; Hong model), dose-influence matrices, fluence optimisation with clinical objectives, DVH analysis, and Monte Carlo recalculation through TOPAS or FRED. 3D Slicer's SlicerRT External Beam Planning module uses it as a dose engine and optimiser. Research use only.} %description %_description %package -n python3-pyradplan Summary: %{summary} # Monte Carlo recalculation through the TOPAS engine runs the topas executable. Recommends: opentopas # The default fluence solver is IPOPT through ipyopt, which Fedora does not ship; scipy and # ipax (both required) are the working solvers. The GUI extra needs PySide6 and pyqtgraph. Suggests: python3-pyside6 Suggests: python3-pyqtgraph Requires: python3-array-api-strict >= 2.4 Requires: InsightToolkit5 >= 5.4.7-27 %description -n python3-pyradplan %_description %prep %autosetup -n pyradplan-%{version} # pydantic_ai only backs pyRadPlan.ai.agents (LLM planning helpers), which imports it on # use; types-array-api is typing-only (imported under TYPE_CHECKING). Neither is needed to # plan. NumPy is capped below 2.4 and Python below 3.15 upstream without a stated reason; # Fedora ships NumPy 2.4 and, on f45, Python 3.15, and %%check runs against both. # numpydantic is capped below 2: 2.0 came out the day after this release and breaks the # matRad serializer (an NDArray type is no longer a NumPy dtype). sed -i -e '/"pydantic_ai/d' -e '/"types-array-api"/d' \ -e 's/"numpy>=2.0,<2.4"/"numpy>=2.0"/' \ -e 's/requires-python = ">=3.10,<3.15"/requires-python = ">=3.10"/' \ -e 's/"numpydantic>=1.6.9"/"numpydantic>=1.6.9,<2"/' pyproject.toml grep -q '"numpy>=2.0"' pyproject.toml grep -q 'requires-python = ">=3.10"$' pyproject.toml grep -q '"numpydantic>=1.6.9,<2"' pyproject.toml ! grep -E '"pydantic_ai|"types-array-api' pyproject.toml # test_lazy_imports.py imports pyRadPlan.ai.agents (pydantic_ai, genai_prices) at module level # for one parametrised case; keep the file's light-import tests and drop that case. sed -i -e '/^import pyRadPlan\.ai\.agents$/d' \ -e 's/\[pyRadPlan, pyRadPlan\.ai\.agents\]/[pyRadPlan]/' test/test_lazy_imports.py ! grep -n 'ai\.agents' test/test_lazy_imports.py %generate_buildrequires %pyproject_buildrequires %build %pyproject_wheel %install %pyproject_install %pyproject_save_files %{pypi_name} %check # ai.agents needs pydantic_ai (dropped above); gui needs the Qt extra; matRad needs MATLAB # or Octave engines; ipopt needs ipyopt. None are importable here by design. %pyproject_check_import -e 'pyRadPlan.ai.*' -e 'pyRadPlan.gui*' -e 'pyRadPlan.matRad*' -e 'pyRadPlan.optimization.solvers._ipopt' # Not run: ai (pydantic_ai, torch, network model downloads), gui (Qt), packaging (briefcase # app bundles), and the MATLAB/Octave bridge tests. %pytest -p no:cacheprovider test \ --ignore=test/ai --ignore=test/gui --ignore=test/packaging \ --ignore=test/test_matlabEngine.py --ignore=test/test_matrad_octave.py \ --ignore=test/test_octaveEngine.py \ --deselect=test/io/test_io_dicom.py::test_load_data_from_dicom_folder \ --deselect=test/io/test_io_dicom.py::test_dicom_roundtrip_dose # The two RTDOSE tests fail on this repository's ITK, not on pyRadPlan: SimpleITK picks # ITK's DCMTKImageIO first, and it ignores GridFrameOffsetVector (3004,000C), so a # multi-frame RTDOSE comes back with z spacing 1 mm instead of the frame offset (GDCMImageIO # reads it right; ITK main has the same gap). tests/radplan.bats PKG-6; # docs/KNOWN-ISSUES.md "ITK DCMTKImageIO ignores RTDOSE GridFrameOffsetVector". %files -n python3-pyradplan -f %{pyproject_files} # The GUI launcher; it needs the Suggests above (PySide6, pyqtgraph) to start. %{_bindir}/pyRadPlanGUI %license LICENSE %doc README.md CHANGELOG.md CITATION.cff %changelog * Sat Nov 07 2026 Morgan Hough - 0.8.0-2 - Run four of the six DICOM import tests again: InsightToolkit5 5.4.7-27 fixes the DCMTKImageIO pixel-spacing swap. Require that ITK. The two RTDOSE tests stay off: DCMTKImageIO ignores GridFrameOffsetVector. * Fri Nov 06 2026 Morgan Hough - 0.8.0-1 - Initial package, for SlicerRT's pyRadPlan dose engine and optimiser. The LLM agent helpers (pydantic_ai) are not packaged; NumPy is allowed at 2.4.