diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 4558e1fe95..a8438871c0 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -2,70 +2,54 @@ There is a single github action file with multiple jobs, which builds both the conda package and documentation, and optionally publishes the documentation: [build](https://github.com/TomographicImaging/CIL/blob/master/.github/workflows/build.yml) -## Building the Conda Package: conda job +The jobs are: -This github action builds and tests the conda package, by using the [conda-package-publish-action](https://github.com/TomographicImaging/conda-package-publish-action) +- `test-cuda` + + uses our self-hosted (STFC Cloud) CUDA-enabled runners to run GPU tests + + `TESTS_FORCE_GPU=1 python -m unittest discover -v -k tigre -k TIGRE -k astra -k ASTRA -k gpu -k GPU ./Wrappers/Python/test` +- `test` + + uses default (GitHub-hosted) runners to run tests on the min & max supported Python & NumPy versions + + `python -m unittest discover -v ./Wrappers/Python/test` +- conda + + uses `mambabuild` to build the conda package (saved as a build artifact named `cil-package`) +- docs + + uses `docs/docs_environment.yml` plus `make -C docs` to build the documentation (saved as a build artifact named `DocumentationHTML`) + + renders to the `gh-pages` branch on `master` (nightly) pushes or on tag (release) pushes + * this in turn is hosted at as per +- docker + + builds a docker image from [`Dockerfile`](../../Dockerfile) (pushed to `ghcr.io/tomographicimaging/cil` as per [the CIL README section on Docker](../../README.md#docker)) -When pushing to master or creating an [annotated tag](https://git-scm.com/book/en/v2/Git-Basics-Tagging), *all* variants are built and tested. +Details on some of these jobs are given below. -When opening or modifying a pull request to master, a single variant is built and tested. This variant is for linux with `python=3.9` and `numpy=1.22`. +## conda -The action does not publish to conda, instead this is done by jenkins. This is because github-actions do not have a GPU. +When opening or modifying a pull request to `master`, a single variant is built and tested. This variant is for linux with `python=3.9` and `numpy=1.22`. -It looks for conda-build dependencies in the channels listed [here](https://github.com/TomographicImaging/CIL/blob/master/.github/workflows/build.yml#L49). If you add any new dependencies, the appropriate channels need to be added to this line. +> [!NOTE] +> The action does not publish to conda, instead this is done by jenkins. We will eventually move from jenkins to conda-forge instead. +> When pushing to `master` or creating an [annotated tag](https://git-scm.com/book/en/v2/Git-Basics-Tagging), *all* variants are built and tested. -An artifact of the resulting tar.bz2 file is made available in the 'Summary' section of the action. It is called `cil-package`. This is used by the **docs** job. It can be found by going to the ‘Actions’ tab, and selecting the appropriate run of `.github/workflows/build.yml`, or by clicking on the tick on the action in the "All checks have passed/failed" section of a PR. When viewing the summary for the run of the action, there is an `Artifact` section at the bottom of the page. Clicking on `cil-package` allows you to download a zip folder containing the tar.bz2 file. +It looks for conda-build dependencies in the channels listed [here](https://github.com/TomographicImaging/CIL/blob/master/.github/workflows/build.yml#L118). If you add any new dependencies, the appropriate channels need to be added to this line. -## Building/Publishing Documentation: docs job +> [!TIP] +> The `conda` job builds the `*.tar.bz2` package and uploads it as an artifact called `cil-package`. +> It can be found by going to the "Actions" tab, and selecting the appropriate run of `.github/workflows/build.yml`, or by clicking on the tick on the action in the "All checks have passed/failed" section of a PR. When viewing the "Summary" for the run of the action, there is an "Artifact" section at the bottom of the page. +> Clicking on `cil-package` allows you to download a zip folder containing the `*.tar.bz2` file. -This github action builds and optionally publishes the documentation located in [docs/source](https://github.com/TomographicImaging/CIL/tree/master/docs/source). To do this it uses a forked version of the [build-sphinx-action](https://github.com/lauramurgatroyd/build-sphinx-action). - -The [docs](https://github.com/TomographicImaging/CIL/blob/master/.github/workflows/build.yml#L59) job: - -- creates a miniconda environment from [docs_environment.yml](https://github.com/TomographicImaging/CIL/blob/master/.github/workflows/docs/docs_environment.yml) -- installs cil into the miniconda environment, using the tar.bz2 artifact (cil-package) created in the **conda** job -- builds the documentation with sphinx -- uses upload-artifact to upload the html files: `HTMLDocumentation`, which can be downloaded to view -- pushes the html files to the `nightly` folder on the gh-pages branch - -If opening or modifying a pull request to master, `docs` is run, but the final gh-pages step is skipped. -If pushing to master or tagging, the documentation is built *and* published to gh-pages. - -### Viewing Built Documentation - -The `docs` job builds the documentation and uploads it as an artifact, in a folder named `DocumentationHTML`. -This can be found by going to the ‘Actions’ tab, and selecting the appropriate run of `.github/workflows/build.yml`, or by clicking on the tick on the action in the "All checks have passed/failed" section of a PR. - -When viewing the `Summary` for the run of the action, there is an `Artifact` section at the bottom of the page. -Clicking on `DocumentationHTML` allows you to download a zip folder containing the built html files. This allows you to preview the documentation site before it is published. - -### Publication of the Documentation +## docs -The documentation is hosted on the [github site](https://tomographicimaging.github.io/CIL/) associated with the repository. -This is built from the [gh-pages branch](https://github.com/TomographicImaging/CIL/tree/gh-pages). - -If you are an admin of the CIL repository you are able to see the settings for the site by going to `Settings->Pages`. - -To publish the documentation, the publish job of the gh-action pushes the documentation changes to the `gh-pages` branch. -Any push to this branch automatically updates the github site. - -### Initial Setup of the Docs Site & Action - -To get the action to work I first had to: - -1. [Create a gh-pages branch](https://gist.github.com/ramnathv/2227408) - note this only worked in bash, not windows command line. -2. [Set the source](https://github.com/TomographicImaging/CIL/settings/pages) for our github pages to be the gh-pages branch. - -I followed the examples on the [sphinx build action page](https://github.com/marketplace/actions/sphinx-build), specifically this [example workflow](https://github.com/ammaraskar/sphinx-action-test/blob/master/.github/workflows/default.yml) - -## Building/Pushing the Docker Image: docker job +This github action builds and optionally publishes the documentation located in [docs/source](https://github.com/TomographicImaging/CIL/tree/master/docs/source). To do this it uses a forked version of the [build-sphinx-action](https://github.com/lauramurgatroyd/build-sphinx-action). -This builds a docker image using the `Dockerfile` at the root of this repository. +The [docs](https://github.com/TomographicImaging/CIL/blob/master/.github/workflows/build.yml#L124) job: -The image is also pushed to `ghcr.io/tomographicimaging/cil:TAG` (https://github.com/TomographicImaging/CIL/pkgs/container/cil), where `TAG` is given by: +- creates a `miniconda` environment from [requirements-test.yml](https://github.com/TomographicImaging/CIL/blob/master/scripts/requirements-test.yml) and [docs_environment.yml](https://github.com/TomographicImaging/CIL/blob/master/docs/docs_environment.yml) +- `cmake` builds & installs CIL into the `miniconda` environment +- builds the HTML documentation with `sphinx` +- uploads a `DocumentationHTML` artifact (which can be downloaded to view locally for debugging) +- pushes the HTML documentation to the `gh-pages` branch + + only if pushing to `master` or tagging (skipped if pushing to a branch or a PR) -git ref | docker tag(s) ---|-- -`master` branch | `master` -`vM.m.p` tag | `M.m.p`, `M.m`, `latest` -anything else | not pushed (only built) +> [!TIP] +> The `docs` job builds the documentation and uploads it as an artifact called `DocumentationHTML`. +> It can be found by going to the "Actions" tab, and selecting the appropriate run of `.github/workflows/build.yml`, or by clicking on the tick on the action in the "All checks have passed/failed" section of a PR. When viewing the "Summary" for the run of the action, there is an "Artifact" section at the bottom of the page. +> Clicking on `DocumentationHTML` allows you to download a zip folder containing the built HTML files. This allows you to preview the documentation site before it is published. diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 449efb1f7f..a632878894 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -35,21 +35,87 @@ on: - 'NOTICE.txt' - 'README.md' jobs: - conda: - runs-on: ubuntu-20.04 + test-cuda: + defaults: {run: {shell: 'bash -el {0}'}} + runs-on: [self-hosted, python, cuda] + strategy: + matrix: + python-version: [3.9] + numpy-version: [1.22] steps: - uses: actions/checkout@v4 + with: {fetch-depth: 0, submodules: recursive} + - id: reqs + name: set requirements + run: | + envname="${GITHUB_REPOSITORY##*/}-${GITHUB_RUN_ID}.${GITHUB_RUN_NUMBER}" + echo "envname=$envname" >> $GITHUB_OUTPUT + sed -ri -e 's/^(name: ).*/\1$envname/' -e '/ python=/d' -e 's/(.* numpy=).*/\1${{ matrix.numpy-version }}/' scripts/requirements-test.yml + - uses: conda-incubator/setup-miniconda@v3 with: - fetch-depth: 0 - - name: conda-build - uses: TomographicImaging/conda-package-publish-action@v2 + python-version: ${{ matrix.python-version }} + environment-file: scripts/requirements-test.yml + activate-environment: ${{ steps.reqs.outputs.envname}} + run-post: false + - id: build + name: build + run: | + cmake -S . -B ./build -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCONDA_BUILD=ON -DCMAKE_INSTALL_PREFIX="$CONDA_PREFIX" + cmake --build ./build --target install + - name: test + run: TESTS_FORCE_GPU=1 python -m unittest discover -v -k tigre -k TIGRE -k astra -k ASTRA -k gpu -k GPU ./Wrappers/Python/test + - if: always() + name: Post Run conda-incubator/setup-miniconda@v3 + run: | + conda deactivate + conda env remove -n "${{ steps.reqs.outputs.envname }}" + sed -i '/${{ steps.reqs.outputs.envname }}/d' ~/.profile + test: + defaults: {run: {shell: 'bash -el {0}'}} + runs-on: ubuntu-latest + strategy: + matrix: + include: + - python-version: 3.8 + numpy-version: 1.21 + - python-version: '3.10' + numpy-version: 1.24 + steps: + - uses: actions/checkout@v4 + with: {fetch-depth: 0, submodules: recursive} + - name: set requirements + run: sed -ri -e '/ python=/d' -e 's/(.* numpy=).*/\1${{ matrix.numpy-version }}/' scripts/requirements-test.yml + - uses: conda-incubator/setup-miniconda@v3 + with: + python-version: ${{ matrix.python-version }} + environment-file: scripts/requirements-test.yml + activate-environment: cil_dev + - name: build + run: | + cmake -S . -B ./build -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCONDA_BUILD=ON -DCMAKE_INSTALL_PREFIX="$CONDA_PREFIX" + cmake --build ./build --target install + - name: test + run: python -m unittest discover -v ./Wrappers/Python/test + conda: + defaults: {run: {shell: 'bash -el {0}'}} + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [3.9] + numpy-version: [1.22] + steps: + - uses: actions/checkout@v4 + with: {fetch-depth: 0, submodules: recursive} + - uses: conda-incubator/setup-miniconda@v3 with: - subDir: recipe - channels: -c conda-forge -c intel -c ccpi - convert_win: false - convert_osx: false - test_pyver: 3.9 - test_npver: 1.22 + python-version: ${{ matrix.python-version }} + mamba-version: "*" + channels: conda-forge + - name: conda build & test + working-directory: recipe + run: | + conda install boa + conda mambabuild . -c conda-forge -c intel -c ccpi --python=${{ matrix.python-version }} --numpy=${{ matrix.numpy-version }} --output-folder . - name: Upload artifact of the conda package uses: actions/upload-artifact@v4 with: @@ -60,9 +126,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - with: - fetch-depth: 0 - submodules: recursive + with: {fetch-depth: 0, submodules: recursive} - uses: conda-incubator/setup-miniconda@v3 with: {python-version: '3.10'} - name: install dependencies @@ -74,8 +138,8 @@ jobs: conda list - name: build cil run: | - cmake -S . -B ../build -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCONDA_BUILD=ON -DCMAKE_INSTALL_PREFIX="$CONDA_PREFIX" - cmake --build ../build --target install + cmake -S . -B ./build -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCONDA_BUILD=ON -DCMAKE_INSTALL_PREFIX="$CONDA_PREFIX" + cmake --build ./build --target install - name: checkout docs uses: actions/checkout@v4 with: @@ -113,8 +177,8 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 - ref: ${{ github.event.pull_request.head.sha || github.ref }} # fix SHA submodules: recursive + ref: ${{ github.event.pull_request.head.sha || github.ref }} # fix SHA - uses: jlumbroso/free-disk-space@v1.3.1 with: docker-images: false @@ -156,6 +220,6 @@ jobs: tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} pass: - needs: [conda, docs, docker] + needs: [test-cuda, test, conda, docs, docker] runs-on: ubuntu-latest steps: [{run: echo success}] diff --git a/README.md b/README.md index 4f14103c84..1dead2d1bc 100644 --- a/README.md +++ b/README.md @@ -167,6 +167,17 @@ git submodule update --init --recursive docker build . -t ghcr.io/tomographicimaging/cil ``` + +### Testing + +One installed, CIL functionality can be tested using the following command: + +```sh +export TESTS_FORCE_GPU=1 # optional, makes GPU test failures noisy +python -m unittest discover -v ./Wrappers/Python/test +``` + + ## Citing CIL diff --git a/Wrappers/Python/test/test_DataProcessor.py b/Wrappers/Python/test/test_DataProcessor.py index e3c6b41b36..bea31dcdf5 100644 --- a/Wrappers/Python/test/test_DataProcessor.py +++ b/Wrappers/Python/test/test_DataProcessor.py @@ -49,9 +49,8 @@ from cil.processors.cilacc_binner import Binner_IPP +@unittest.skipUnless(has_ipp, "Requires IPP libraries") class TestBinner_cillacc(unittest.TestCase): - - @unittest.skipUnless(has_ipp, "Requires IPP libraries") def test_binning_cpp(self): shape_in = [4,12,16,32] @@ -73,8 +72,6 @@ def test_binning_cpp(self): with self.assertRaises(ValueError): binner_cpp = Binner_IPP(shape_in,shape_out,start_index,binning) - - @unittest.skipUnless(has_ipp, "Requires IPP libraries") def test_binning_cpp_2D_data(self): data = dataexample.SIMULATED_SPHERE_VOLUME.get() @@ -104,8 +101,6 @@ def test_binning_cpp_2D_data(self): numpy.testing.assert_allclose(binned_by_hand,binned_arr,atol=1e-6) - - @unittest.skipUnless(has_ipp, "Requires IPP libraries") def test_binning_cpp_4D(self): shape_in = [9,21,40,92] @@ -137,8 +132,6 @@ def test_binning_cpp_4D(self): numpy.testing.assert_allclose(binned_by_hand,binned_arr,atol=1e-6) - - @unittest.skipUnless(has_ipp, "Requires IPP libraries") def test_binning_cpp_2D(self): shape_in = [1,1,3,3] @@ -172,9 +165,7 @@ def test_binning_cpp_2D(self): class TestBinner(unittest.TestCase): - def test_set_up_processor(self): - ig = ImageGeometry(20,22,23,0.1,0.2,0.3,0.4,0.5,0.6,channels=24) data = ig.allocate('random') @@ -666,7 +657,7 @@ def test_process_data_container(self): @unittest.skipUnless(has_tigre and has_nvidia, "TIGRE GPU not installed") - def test_imagedata_full(self): + def test_imagedata_full_tigre(self): """ This test bins a reconstructed volume. It then uses that geometry as the reconstruction window and reconstructs again. @@ -697,7 +688,7 @@ def test_imagedata_full(self): @unittest.skipUnless(has_astra and has_nvidia, "ASTRA GPU not installed") - def test_aqdata_full(self): + def test_aqdata_full_astra(self): """ This test bins a sinogram. It then uses that geometry for the forward projection. @@ -732,7 +723,7 @@ def test_aqdata_full(self): @unittest.skipUnless(has_astra and has_nvidia, "ASTRA GPU not installed") - def test_aqdata_full_origin(self): + def test_aqdata_full_origin_astra(self): """ This test bins a sinogram. It then uses that geometry for the forward projection. @@ -1200,7 +1191,7 @@ def test_slice_acquisition_data(self): @unittest.skipUnless(has_tigre and has_nvidia, "TIGRE GPU not installed") - def test_imagedata_full(self): + def test_imagedata_full_tigre(self): """ This test slices a reconstructed volume. It then uses that geometry as the reconstruction window and reconstructs again. @@ -1230,7 +1221,7 @@ def test_imagedata_full(self): @unittest.skipUnless(has_astra and has_nvidia, "ASTRA GPU not installed") - def test_aqdata_full(self): + def test_aqdata_full_astra(self): """ This test slices a sinogram. It then uses that geometry for the forward projection. @@ -1266,7 +1257,7 @@ def test_aqdata_full(self): @unittest.skipUnless(has_astra and has_nvidia, "ASTRA GPU not installed") - def test_aqdata_full_origin(self): + def test_aqdata_full_origin_astra(self): """ This test slices a sinogram. It then uses that geometry for the forward projection. @@ -2126,7 +2117,7 @@ def test_results_wrap(self): @unittest.skipUnless(has_tigre and has_nvidia, "TIGRE GPU not installed") - def test_pad_ad_full(self): + def test_pad_ad_full_tigre(self): """ This test pads a acquisition data asymmetrically. It then compares the FBP of the padded and unpadded data on the same ImageGeometry. @@ -2168,7 +2159,7 @@ def test_pad_ad_full(self): @unittest.skipUnless(has_astra and has_nvidia, "ASTRA GPU not installed") - def test_pad_id_full(self): + def test_pad_id_full_astra(self): """ This test pads an image data asymmetrically. It then compares the forward projection of the padded and unpadded phantom on the same AcquisitionGeometry. diff --git a/Wrappers/Python/test/test_PluginsAstra_GPU.py b/Wrappers/Python/test/test_PluginsAstra_GPU.py index e398012e0b..ae7c8febc2 100644 --- a/Wrappers/Python/test/test_PluginsAstra_GPU.py +++ b/Wrappers/Python/test/test_PluginsAstra_GPU.py @@ -35,9 +35,8 @@ def setup_parameters(self): self.ProjectionOperator = ProjectionOperator self.PO_args={'device':'gpu'} +@unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA and GPU") class Test_basic_astra(unittest.TestCase): - - @unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA and GPU") def test_astra_basic_cuda(self): try: disable_print() @@ -46,27 +45,24 @@ def test_astra_basic_cuda(self): except: self.assertFalse('ASTRA GPU test failed') +@unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") class Test_Cone3D_Projectors_GPU_basic(unittest.TestCase, TestCommon_ProjectionOperator): - - @unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") def setUp(self): setup_parameters(self) self.Cone3D() self.tolerance_fp=0 +@unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") class Test_Cone3D_Projectors_GPU_sim(unittest.TestCase, TestCommon_ProjectionOperator_SIM): - - @unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") def setUp(self): setup_parameters(self) self.Cone3D() self.tolerance_fp = 0.16 +@unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") class Test_Cone3D_Projectors_GPU_toy(unittest.TestCase, TestCommon_ProjectionOperator_TOY): - - @unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") def setUp(self): setup_parameters(self) self.Cone3D() @@ -74,27 +70,24 @@ def setUp(self): self.tolerance_norm = 0.1 +@unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") class Test_Cone2D_Projectors_GPU_basic(unittest.TestCase, TestCommon_ProjectionOperator): - - @unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") def setUp(self): setup_parameters(self) self.Cone2D() self.tolerance_fp=0 +@unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") class Test_Cone2D_Projectors_GPU_sim(unittest.TestCase, TestCommon_ProjectionOperator_SIM): - - @unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") def setUp(self): setup_parameters(self) self.Cone2D() self.tolerance_fp = 0.16 +@unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") class Test_Cone2D_Projectors_GPU_toy(unittest.TestCase, TestCommon_ProjectionOperator_TOY): - - @unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") def setUp(self): setup_parameters(self) self.Cone2D() @@ -102,27 +95,24 @@ def setUp(self): self.tolerance_norm = 0.1 +@unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") class Test_Parallel3D_Projectors_GPU_basic(unittest.TestCase, TestCommon_ProjectionOperator): - - @unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") def setUp(self): setup_parameters(self) self.Parallel3D() self.tolerance_fp=0 +@unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") class Test_Parallel3D_Projectors_GPU_sim(unittest.TestCase, TestCommon_ProjectionOperator_SIM): - - @unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") def setUp(self): setup_parameters(self) self.Parallel3D() self.tolerance_fp = 0.16 +@unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") class Test_Parallel3D_Projectors_GPU_toy(unittest.TestCase, TestCommon_ProjectionOperator_TOY): - - @unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") def setUp(self): setup_parameters(self) self.Parallel3D() @@ -130,26 +120,23 @@ def setUp(self): self.tolerance_norm = 1e-6 +@unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") class Test_Parallel2D_Projectors_GPU_basic(unittest.TestCase, TestCommon_ProjectionOperator): - - @unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") def setUp(self): setup_parameters(self) self.Parallel2D() self.tolerance_fp=0 +@unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") class Test_Parallel2D_Projectors_GPU_sim(unittest.TestCase, TestCommon_ProjectionOperator_SIM): - - @unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") def setUp(self): setup_parameters(self) self.Parallel2D() self.tolerance_fp = 0.16 +@unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") class Test_Parallel2D_Projectors_GPU_toy(unittest.TestCase, TestCommon_ProjectionOperator_TOY): - - @unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") def setUp(self): setup_parameters(self) self.Parallel2D() diff --git a/Wrappers/Python/test/test_PluginsAstra_Projectors.py b/Wrappers/Python/test/test_PluginsAstra_Projectors.py index 8652f3a902..9f0f41ba0e 100644 --- a/Wrappers/Python/test/test_PluginsAstra_Projectors.py +++ b/Wrappers/Python/test/test_PluginsAstra_Projectors.py @@ -70,7 +70,6 @@ def setUp(self): self.norm = 14.85 - def foward_projection(self, A, ig, ag): image_data = ig.allocate(None) image_data.fill(1) @@ -85,7 +84,6 @@ def foward_projection(self, A, ig, ag): self.assertAlmostEqual(acq_data_0.array.item(0), 12.800, places=3) #check not zeros np.testing.assert_allclose(acq_data_0.as_array(),acq_data_1.as_array()) - def backward_projection(self, A, ig, ag): acq_data = ag.allocate(None) acq_data.fill(1) @@ -104,7 +102,6 @@ def projector_norm(self, A): n = A.norm() self.assertAlmostEqual(n, self.norm, places=2) - @unittest.skipUnless(has_astra, "Requires ASTRA") def test_AstraProjector2D_cpu(self): @@ -114,7 +111,6 @@ def test_AstraProjector2D_cpu(self): self.backward_projection(A,self.ig, self.ag) self.projector_norm(A) - @unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") def test_AstraProjector2D_gpu(self): @@ -124,7 +120,6 @@ def test_AstraProjector2D_gpu(self): self.backward_projection(A,self.ig, self.ag) self.projector_norm(A) - @unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") def test_AstraProjector3D_2Ddata(self): @@ -144,7 +139,6 @@ def test_AstraProjector3D_2Ddata(self): with self.assertRaises(ValueError): A = AstraProjector3D(ig_2, self.ag) - @unittest.skipUnless(has_astra and has_nvidia, "Requires ASTRA GPU") def test_AstraProjector3D_3Ddata(self): # test exists @@ -171,7 +165,6 @@ def setUp(self): ig = self.data.geometry.get_ImageGeometry() self.datasplit = self.data.partition(10, 'sequential') - K = ProjectionOperator(image_geometry=ig, acquisition_geometry=self.datasplit.geometry) A = ProjectionOperator(image_geometry=ig, acquisition_geometry=self.data.geometry) self.projectionOperator = (A, K) diff --git a/Wrappers/Python/test/test_PluginsTigre_FBP.py b/Wrappers/Python/test/test_PluginsTigre_FBP.py index b45a34d774..29f7b332f7 100644 --- a/Wrappers/Python/test/test_PluginsTigre_FBP.py +++ b/Wrappers/Python/test/test_PluginsTigre_FBP.py @@ -26,15 +26,13 @@ from cil.plugins.tigre import FBP def setup_parameters(self): - self.backend = 'tigre' self.FBP = FBP self.FBP_args={} -class Test_Cone3D_FBP(unittest.TestCase, TestCommon_FBP_SIM): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Cone3D_FBP_tigre(unittest.TestCase, TestCommon_FBP_SIM): def setUp(self): setup_parameters(self) self.Cone3D() @@ -42,9 +40,8 @@ def setUp(self): self.tolerance_fbp_roi = 1e-3 -class Test_Cone2D_FBP(unittest.TestCase, TestCommon_FBP_SIM): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Cone2D_FBP_tigre(unittest.TestCase, TestCommon_FBP_SIM): def setUp(self): setup_parameters(self) self.Cone2D() @@ -52,9 +49,8 @@ def setUp(self): self.tolerance_fbp_roi = 1e-3 -class Test_Parallel3D_FBP(unittest.TestCase, TestCommon_FBP_SIM): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Parallel3D_FBP_tigre(unittest.TestCase, TestCommon_FBP_SIM): def setUp(self): setup_parameters(self) self.Parallel3D() @@ -62,9 +58,8 @@ def setUp(self): self.tolerance_fbp_roi = 1e-3 -class Test_Parallel2D_FBP(unittest.TestCase, TestCommon_FBP_SIM): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Parallel2D_FBP_tigre(unittest.TestCase, TestCommon_FBP_SIM): def setUp(self): setup_parameters(self) self.Parallel2D() diff --git a/Wrappers/Python/test/test_PluginsTigre_General.py b/Wrappers/Python/test/test_PluginsTigre_General.py index 44a50d8d36..a55f14958e 100644 --- a/Wrappers/Python/test/test_PluginsTigre_General.py +++ b/Wrappers/Python/test/test_PluginsTigre_General.py @@ -275,9 +275,8 @@ def test_parallel3D_offset(self): np.testing.assert_allclose(tg_geometry.dVoxel, [self.ig.voxel_size_z,self.ig.voxel_size_y,self.ig.voxel_size_x]) -class TestMechanics(unittest.TestCase): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class TestMechanics_tigre(unittest.TestCase): def setUp(self): self.ag = AcquisitionGeometry.create_Cone2D([0,-500],[0,500]).set_angles([0]).set_panel(5,1) @@ -323,7 +322,6 @@ def setUp(self): ig = self.data.geometry.get_ImageGeometry() self.datasplit = self.data.partition(10, 'sequential') - K = ProjectionOperator(image_geometry=ig, acquisition_geometry=self.datasplit.geometry) A = ProjectionOperator(image_geometry=ig, acquisition_geometry=self.data.geometry) self.projectionOperator = (A, K) diff --git a/Wrappers/Python/test/test_PluginsTigre_Siddon.py b/Wrappers/Python/test/test_PluginsTigre_Siddon.py index c07c9eaa7c..39e8051186 100644 --- a/Wrappers/Python/test/test_PluginsTigre_Siddon.py +++ b/Wrappers/Python/test/test_PluginsTigre_Siddon.py @@ -32,27 +32,24 @@ def setup_parameters(self): self.PO_args={'direct_method':'Siddon','adjoint_weights':'matched'} -class Test_Cone3D_Projectors_basic(unittest.TestCase, TestCommon_ProjectionOperator): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Cone3D_Projectors_basic_tigre(unittest.TestCase, TestCommon_ProjectionOperator): def setUp(self): setup_parameters(self) self.Cone3D() self.tolerance_fp=0.16 -class Test_Cone3D_Projectors_sim(unittest.TestCase, TestCommon_ProjectionOperator_SIM): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Cone3D_Projectors_sim_tigre(unittest.TestCase, TestCommon_ProjectionOperator_SIM): def setUp(self): setup_parameters(self) self.Cone3D() self.tolerance_fp = 0.35 -class Test_Cone3D_Projectors_toy(unittest.TestCase, TestCommon_ProjectionOperator_TOY): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Cone3D_Projectors_toy_tigre(unittest.TestCase, TestCommon_ProjectionOperator_TOY): def setUp(self): setup_parameters(self) self.Cone3D() @@ -60,27 +57,24 @@ def setUp(self): self.tolerance_norm = 0.1 -class Test_Cone2D_Projectors_basic(unittest.TestCase, TestCommon_ProjectionOperator): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Cone2D_Projectors_basic_tigre(unittest.TestCase, TestCommon_ProjectionOperator): def setUp(self): setup_parameters(self) self.Cone2D() self.tolerance_fp=0.16 -class Test_Cone2D_Projectors_sim(unittest.TestCase, TestCommon_ProjectionOperator_SIM): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Cone2D_Projectors_sim_tigre(unittest.TestCase, TestCommon_ProjectionOperator_SIM): def setUp(self): setup_parameters(self) self.Cone2D() self.tolerance_fp = 0.2 -class Test_Cone2D_Projectors_toy(unittest.TestCase, TestCommon_ProjectionOperator_TOY): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Cone2D_Projectors_toy_tigre(unittest.TestCase, TestCommon_ProjectionOperator_TOY): def setUp(self): setup_parameters(self) self.Cone2D() @@ -88,27 +82,24 @@ def setUp(self): self.tolerance_norm = 0.1 -class Test_Parallel3D_Projectors_basic(unittest.TestCase, TestCommon_ProjectionOperator): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Parallel3D_Projectors_basic_tigre(unittest.TestCase, TestCommon_ProjectionOperator): def setUp(self): setup_parameters(self) self.Parallel3D() self.tolerance_fp=1e-5 -class Test_Parallel3D_Projectors_sim(unittest.TestCase, TestCommon_ProjectionOperator_SIM): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Parallel3D_Projectors_sim_tigre(unittest.TestCase, TestCommon_ProjectionOperator_SIM): def setUp(self): setup_parameters(self) self.Parallel3D() self.tolerance_fp = 0.25 -class Test_Parallel3D_Projectors_toy(unittest.TestCase, TestCommon_ProjectionOperator_TOY): - - #@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Parallel3D_Projectors_toy_tigre(unittest.TestCase, TestCommon_ProjectionOperator_TOY): @unittest.skip("TIGRE backprojector weights bug") def setUp(self): setup_parameters(self) @@ -117,27 +108,24 @@ def setUp(self): self.tolerance_norm = 1e-5 -class Test_Parallel2D_Projectors_basic(unittest.TestCase, TestCommon_ProjectionOperator): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Parallel2D_Projectors_basic_tigre(unittest.TestCase, TestCommon_ProjectionOperator): def setUp(self): setup_parameters(self) self.Parallel2D() self.tolerance_fp=1e-5 -class Test_Parallel2D_Projectors_sim(unittest.TestCase, TestCommon_ProjectionOperator_SIM): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Parallel2D_Projectors_sim_tigre(unittest.TestCase, TestCommon_ProjectionOperator_SIM): def setUp(self): setup_parameters(self) self.Parallel2D() self.tolerance_fp = 0.15 -class Test_Parallel2D_Projectors_toy(unittest.TestCase, TestCommon_ProjectionOperator_TOY): - -# @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Parallel2D_Projectors_toy_tigre(unittest.TestCase, TestCommon_ProjectionOperator_TOY): @unittest.skip("TIGRE backprojector weights bug") def setUp(self): setup_parameters(self) diff --git a/Wrappers/Python/test/test_PluginsTigre_interpolated.py b/Wrappers/Python/test/test_PluginsTigre_interpolated.py index 16d5ba34d7..1945434397 100644 --- a/Wrappers/Python/test/test_PluginsTigre_interpolated.py +++ b/Wrappers/Python/test/test_PluginsTigre_interpolated.py @@ -33,27 +33,24 @@ def setup_parameters(self): self.PO_args={'direct_method':'interpolated','adjoint_weights':'matched'} -class Test_Cone3D_Projectors_basic(unittest.TestCase, TestCommon_ProjectionOperator): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Cone3D_Projectors_basic_tigre(unittest.TestCase, TestCommon_ProjectionOperator): def setUp(self): setup_parameters(self) self.Cone3D() self.tolerance_fp=0 -class Test_Cone3D_Projectors_sim(unittest.TestCase, TestCommon_ProjectionOperator_SIM): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Cone3D_Projectors_sim_tigre(unittest.TestCase, TestCommon_ProjectionOperator_SIM): def setUp(self): setup_parameters(self) self.Cone3D() self.tolerance_fp = 0.16 -class Test_Cone3D_Projectors_toy(unittest.TestCase, TestCommon_ProjectionOperator_TOY): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Cone3D_Projectors_toy_tigre(unittest.TestCase, TestCommon_ProjectionOperator_TOY): def setUp(self): setup_parameters(self) self.Cone3D() @@ -61,27 +58,24 @@ def setUp(self): self.tolerance_norm = 0.1 -class Test_Cone2D_Projectors_basic(unittest.TestCase, TestCommon_ProjectionOperator): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Cone2D_Projectors_basic_tigre(unittest.TestCase, TestCommon_ProjectionOperator): def setUp(self): setup_parameters(self) self.Cone2D() self.tolerance_fp=0 -class Test_Cone2D_Projectors_sim(unittest.TestCase, TestCommon_ProjectionOperator_SIM): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Cone2D_Projectors_sim_tigre(unittest.TestCase, TestCommon_ProjectionOperator_SIM): def setUp(self): setup_parameters(self) self.Cone2D() self.tolerance_fp = 0.1 -class Test_Cone2D_Projectors_toy(unittest.TestCase, TestCommon_ProjectionOperator_TOY): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Cone2D_Projectors_toy_tigre(unittest.TestCase, TestCommon_ProjectionOperator_TOY): def setUp(self): setup_parameters(self) self.Cone2D() @@ -89,27 +83,24 @@ def setUp(self): self.tolerance_norm = 0.1 -class Test_Parallel3D_Projectors_basic(unittest.TestCase, TestCommon_ProjectionOperator): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Parallel3D_Projectors_basic_tigre(unittest.TestCase, TestCommon_ProjectionOperator): def setUp(self): setup_parameters(self) self.Parallel3D() self.tolerance_fp=0.0004 -class Test_Parallel3D_Projectors_sim(unittest.TestCase, TestCommon_ProjectionOperator_SIM): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Parallel3D_Projectors_sim_tigre(unittest.TestCase, TestCommon_ProjectionOperator_SIM): def setUp(self): setup_parameters(self) self.Parallel3D() self.tolerance_fp = 0.12 -class Test_Parallel3D_Projectors_toy(unittest.TestCase, TestCommon_ProjectionOperator_TOY): - - #@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Parallel3D_Projectors_toy_tigre(unittest.TestCase, TestCommon_ProjectionOperator_TOY): @unittest.skip("TIGRE backprojector weights bug") def setUp(self): setup_parameters(self) @@ -118,27 +109,23 @@ def setUp(self): self.tolerance_norm = 0.1 -class Test_Parallel2D_Projectors_basic(unittest.TestCase, TestCommon_ProjectionOperator): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Parallel2D_Projectors_basic_tigre(unittest.TestCase, TestCommon_ProjectionOperator): def setUp(self): setup_parameters(self) self.Parallel2D() self.tolerance_fp=0.006 -class Test_Parallel2D_Projectors_sim(unittest.TestCase, TestCommon_ProjectionOperator_SIM): - - @unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Parallel2D_Projectors_sim_tigre(unittest.TestCase, TestCommon_ProjectionOperator_SIM): def setUp(self): setup_parameters(self) self.Parallel2D() self.tolerance_fp = 0.1 - -class Test_Parallel2D_Projectors_toy(unittest.TestCase, TestCommon_ProjectionOperator_TOY): - - #@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +@unittest.skipUnless(has_tigre and has_nvidia, "Requires TIGRE GPU") +class Test_Parallel2D_Projectors_toy_tigre(unittest.TestCase, TestCommon_ProjectionOperator_TOY): @unittest.skip("TIGRE backprojector weights bug") def setUp(self): setup_parameters(self) diff --git a/Wrappers/Python/test/test_functions.py b/Wrappers/Python/test/test_functions.py index 41b7e45126..2390ff4c56 100644 --- a/Wrappers/Python/test/test_functions.py +++ b/Wrappers/Python/test/test_functions.py @@ -90,7 +90,7 @@ def test_Function(self): # Compare call of g a2 = alpha * (d - noisy_data).power(2).sum() - self.assertEqual(a2, g(d)) + self.assertAlmostEqual(a2, g(d)) # Compare convex conjugate of g a3 = 0.5 * d.squared_norm() + d.dot(noisy_data) diff --git a/Wrappers/Python/test/test_reconstructors.py b/Wrappers/Python/test/test_reconstructors.py index 64e0e66105..2b5459e4d4 100644 --- a/Wrappers/Python/test/test_reconstructors.py +++ b/Wrappers/Python/test/test_reconstructors.py @@ -525,8 +525,8 @@ def test_set_backend(self): reconstructor = FBP(ad, backend='tigre') -class Test_FDK_results(unittest.TestCase): - +@unittest.skipUnless(has_tigre and has_nvidia and has_ipp, "TIGRE or IPP not installed") +class Test_FDK_results_tigre_ipp(unittest.TestCase): def setUp(self): self.acq_data = SIMULATED_CONE_BEAM_DATA.get() @@ -538,8 +538,6 @@ def setUp(self): self.ig = self.img_data.geometry self.ag = self.acq_data.geometry - - @unittest.skipUnless(has_tigre and has_nvidia and has_ipp, "TIGRE or IPP not installed") def test_results_3D(self): reconstructor = FDK(self.acq_data) @@ -552,8 +550,6 @@ def test_results_3D(self): reconstructor.run(out=reco2, verbose=0) np.testing.assert_allclose(reco.as_array(), reco2.as_array(), atol=1e-8) - - @unittest.skipUnless(has_tigre and has_nvidia and has_ipp, "TIGRE or IPP not installed") def test_results_2D(self): data2D = self.acq_data.get_slice(vertical='centre') @@ -568,8 +564,6 @@ def test_results_2D(self): reconstructor.run(out=reco2, verbose=0) np.testing.assert_allclose(reco.as_array(), reco2.as_array(), atol=1e-8) - - @unittest.skipUnless(has_tigre and has_nvidia and has_ipp, "TIGRE or IPP not installed") def test_results_with_tigre(self): fbp_tigre = FBP_tigre(self.ig, self.ag) @@ -588,8 +582,6 @@ def test_results_with_tigre(self): #with the same filter results should be virtually identical np.testing.assert_allclose(reco_cil.as_array(), reco_tigre.as_array(),atol=1e-8) - - @unittest.skipUnless(has_tigre and has_nvidia and has_ipp, "TIGRE or IPP not installed") def test_results_inplace_filtering(self): reconstructor = FDK(self.acq_data) @@ -604,10 +596,9 @@ def test_results_inplace_filtering(self): self.assertGreater(diff,0.8) -class Test_FBP_results(unittest.TestCase): - +@unittest.skipUnless(has_tigre and has_nvidia and has_ipp, "TIGRE or IPP not installed") +class Test_FBP_tigre_ipp(unittest.TestCase): def setUp(self): - self.acq_data = SIMULATED_PARALLEL_BEAM_DATA.get() self.img_data = SIMULATED_SPHERE_VOLUME.get() @@ -617,10 +608,7 @@ def setUp(self): self.ig = self.img_data.geometry self.ag = self.acq_data.geometry - - @unittest.skipUnless(has_tigre and has_nvidia and has_ipp, "TIGRE or IPP not installed") def test_results_3D_tigre(self): - reconstructor = FBP(self.acq_data) reco = reconstructor.run(verbose=0) @@ -631,10 +619,7 @@ def test_results_3D_tigre(self): reconstructor.run(out=reco2, verbose=0) np.testing.assert_allclose(reco.as_array(), reco2.as_array(), atol=1e-8) - - @unittest.skipUnless(has_astra and has_nvidia and has_ipp, "ASTRA or IPP not installed") def test_results_3D_astra(self): - self.acq_data.reorder('astra') reconstructor = FBP(self.acq_data, backend='astra') @@ -646,8 +631,6 @@ def test_results_3D_astra(self): reconstructor.run(out=reco2, verbose=0) np.testing.assert_allclose(reco.as_array(), reco2.as_array(), atol=1e-8) - - @unittest.skipUnless(has_tigre and has_nvidia and has_ipp, "TIGRE or IPP not installed") def test_results_3D_split(self): reconstructor = FBP(self.acq_data) @@ -661,10 +644,7 @@ def test_results_3D_split(self): reconstructor.run(out=reco2, verbose=0) np.testing.assert_allclose(reco.as_array(), reco2.as_array(), atol=1e-8) - - @unittest.skipUnless(has_tigre and has_nvidia and has_ipp, "TIGRE or IPP not installed") def test_results_3D_split_reverse(self): - acq_data = self.acq_data.copy() acq_data.geometry.config.panel.origin = 'top-left' @@ -681,11 +661,7 @@ def test_results_3D_split_reverse(self): reconstructor.run(out=reco2, verbose=0) np.testing.assert_allclose(reco.as_array(), reco2.as_array(), atol=1e-8) - - - @unittest.skipUnless(has_tigre and has_nvidia and has_ipp, "TIGRE or IPP not installed") def test_results_2D_tigre(self): - data2D = self.acq_data.get_slice(vertical='centre') img_data2D = self.img_data.get_slice(vertical='centre') @@ -698,10 +674,7 @@ def test_results_2D_tigre(self): reconstructor.run(out=reco2, verbose=0) np.testing.assert_allclose(reco.as_array(), reco2.as_array(), atol=1e-8) - - @unittest.skipUnless(has_astra and has_nvidia and has_ipp, "ASTRA or IPP not installed") def test_results_2D_astra(self): - data2D = self.acq_data.get_slice(vertical='centre') data2D.reorder('astra') img_data2D = self.img_data.get_slice(vertical='centre') @@ -715,10 +688,7 @@ def test_results_2D_astra(self): reconstructor.run(out=reco2, verbose=0) np.testing.assert_allclose(reco.as_array(), reco2.as_array(), atol=1e-8) - - @unittest.skipUnless(has_tigre and has_nvidia and has_ipp, "TIGRE or IPP not installed") def test_results_with_tigre(self): - fbp_tigre = FBP_tigre(self.ig, self.ag) reco_tigre = fbp_tigre(self.acq_data) @@ -735,10 +705,7 @@ def test_results_with_tigre(self): #with the same filter results should be virtually identical np.testing.assert_allclose(reco_cil.as_array(), reco_tigre.as_array(),atol=1e-8) - - @unittest.skipUnless(has_tigre and has_nvidia and has_ipp, "TIGRE or IPP not installed") def test_results_inplace_filtering(self): - reconstructor = FBP(self.acq_data) reco = reconstructor.run(verbose=0) diff --git a/Wrappers/Python/test/utils.py b/Wrappers/Python/test/utils.py index fa46395343..148bc6abd7 100644 --- a/Wrappers/Python/test/utils.py +++ b/Wrappers/Python/test/utils.py @@ -57,12 +57,16 @@ def initialise_tests(): subprocess.check_output('nvidia-smi') has_nvidia = True except: + if os.environ.get("TESTS_FORCE_GPU", ""): + raise ImportError has_nvidia = False system_state['has_nvidia']=has_nvidia #astra module_info = importlib.util.find_spec("astra") if module_info is None: + if os.environ.get("TESTS_FORCE_GPU", ""): + raise ImportError has_astra = False else: has_astra = True @@ -71,6 +75,8 @@ def initialise_tests(): #tigre module_info = importlib.util.find_spec("tigre") if module_info is None: + if os.environ.get("TESTS_FORCE_GPU", ""): + raise ImportError has_tigre = False else: has_tigre = True diff --git a/scripts/requirements-test.yml b/scripts/requirements-test.yml index 12a35b6aca..eb72894e91 100644 --- a/scripts/requirements-test.yml +++ b/scripts/requirements-test.yml @@ -40,7 +40,9 @@ dependencies: - matplotlib - h5py - pillow - - libgcc-ng + - libgcc-ng # [linux] + - libstdcxx-ng # [linux] + - _openmp_mutex # [linux] - dxchange - olefile - pywavelets