From 8841a6b4c596f444d60799c7eb36eb75f38a1335 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Coussat?= Date: Wed, 15 Apr 2026 16:50:17 +0200 Subject: [PATCH] ENH: Add application test for pctpairprotons --- .github/workflows/build-test-package.yml | 2 +- documentation/docs/installation.md | 24 +++++++++++++ pyproject.toml | 2 ++ test/pctapplicationtest.py | 45 ++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 test/pctapplicationtest.py diff --git a/.github/workflows/build-test-package.yml b/.github/workflows/build-test-package.yml index ef1e5eb..2bdcdeb 100644 --- a/.github/workflows/build-test-package.yml +++ b/.github/workflows/build-test-package.yml @@ -50,7 +50,7 @@ jobs: echo "Installing wheel: $wheel" pip install $wheel - pip install pytest + pip install pytest uproot # Run tests with warning detection. # SWIG < 4.4 triggers the Py_LIMITED_API "builtin type swig…" warning when diff --git a/documentation/docs/installation.md b/documentation/docs/installation.md index 9571195..0bee798 100644 --- a/documentation/docs/installation.md +++ b/documentation/docs/installation.md @@ -80,6 +80,23 @@ export PATH=/Wrapping/Generators/Python/itk/:${PATH} ``` in the user's `.bashrc` file. This allows to run PCT applications from anywhere on the computer. +### Testing + +To run PCT Python tests with pytest, install the test dependencies from the directory containing `pyproject.toml`: + +``` +pip install --group test +``` + +This installs: +* `pytest` - for running Python unit tests +* `uproot` - for loading ROOT files + +After installing, run the tests with: +``` +pytest test/*.py +``` + ## Optional dependencies ### GATE @@ -89,3 +106,10 @@ in the user's `.bashrc` file. This allows to run PCT applications from anywhere pip install opengate ``` An example of proton CT GATE simulation can be found in [`gate/protonct.py`](https://github.com/RTKConsortium/PCT/blob/main/gate/protonct.py). + +### Uproot + +[Uproot](https://uproot.readthedocs.io/) is a library for reading and writing ROOT files in pure Python and NumPy. Some applications of PCT require Uproot, such as `pctpairprotons` and `pctweplfit`. The simplest way to install Uproot is by running +```bash +pip install uproot +``` diff --git a/pyproject.toml b/pyproject.toml index 26ac8f0..68ecc1c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,6 +37,8 @@ requires-python = ">=3.8" dependencies = [ "itk-rtk == 2.7.*" ] +[dependency-groups] +test = ["pytest", "uproot"] [project.scripts] pctbinning = "itk.pctbinning:main" diff --git a/test/pctapplicationtest.py b/test/pctapplicationtest.py new file mode 100644 index 0000000..0314b0a --- /dev/null +++ b/test/pctapplicationtest.py @@ -0,0 +1,45 @@ +import pytest +import itk +import urllib.request +import numpy as np +from itk import PCT as pct + + +def download_file_fixture(file_key, filename): + + @pytest.fixture(scope="session") + def fixture(tmp_path_factory): + path = tmp_path_factory.getbasetemp() / filename + url = f"https://data.kitware.com/api/v1/file/{file_key}/download" + with urllib.request.urlopen(url) as response, open(path, "wb") as out_file: + out_file.write(response.read()) + return path + + return fixture + + +phasespacein_root = download_file_fixture( + "69cbef28303cec2e64feb78a", "PhaseSpaceIn.root" +) +phasespaceout_root = download_file_fixture( + "69cbef2a303cec2e64feb78d", "PhaseSpaceOut.root" +) +baseline_pairs_mhd = download_file_fixture("69cbefdf303cec2e64feb790", "pairs0000.mhd") +baseline_pairs_raw = download_file_fixture("69cbefe0303cec2e64feb793", "pairs0000.raw") + + +def test_pairprotons_application( + tmp_path, + phasespacein_root, + phasespaceout_root, + baseline_pairs_mhd, + baseline_pairs_raw, +): + output = tmp_path / "pairs_test.mhd" + pct.pctpairprotons( + f"-i {phasespacein_root} -j {phasespaceout_root} -o {output} --plane-in -110 --plane-out 110 --psin PhaseSpaceIn --psout PhaseSpaceOut" + ) + output0000 = tmp_path / "pairs_test0000.mhd" + pairs_test = itk.array_from_image(itk.imread(output0000)) + pairs_baseline = itk.array_from_image(itk.imread(baseline_pairs_mhd)) + assert np.array_equal(pairs_test, pairs_baseline)