aprict 0.0.24.dev1__tar.gz → 0.0.27__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {aprict-0.0.24.dev1/src/aprict.egg-info → aprict-0.0.27}/PKG-INFO +1 -1
- {aprict-0.0.24.dev1 → aprict-0.0.27}/pyproject.toml +1 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/setup.py +3 -0
- aprict-0.0.27/src/aprict/__init__.py +92 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cb/flatpanel.py +21 -7
- aprict-0.0.27/src/aprict/examples/__init__.py +41 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/examples/composite_human_sirt.py +2 -2
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/examples/fan_beam_sirt.py +2 -2
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/examples/helical_sirt.py +2 -2
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/examples/trajtest_A_sirt.py +5 -5
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/examples/triangle_exp_fb.py +3 -3
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/phantoms/FORBILD_phantoms.py +56 -41
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/phantoms/__init__.py +5 -1
- aprict-0.0.27/src/aprict/scripts/__init__.py +20 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/scripts/cli.py +2 -2
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/scripts/project_cbfp.py +3 -3
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/tests/cuda_kernels/test_project_cb.py +1 -1
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/tests/cuda_kernels/test_project_cb_FORBILD_phantoms.py +1 -1
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/tests/test_FORBILD_lungs_construction.py +1 -1
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/version.py +1 -1
- aprict-0.0.27/src/aprict/volume/__init__.py +24 -0
- {aprict-0.0.24.dev1/src/aprict → aprict-0.0.27/src/aprict/volume}/volume.py +7 -7
- {aprict-0.0.24.dev1 → aprict-0.0.27/src/aprict.egg-info}/PKG-INFO +1 -1
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict.egg-info/SOURCES.txt +5 -2
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict.egg-info/entry_points.txt +1 -0
- aprict-0.0.24.dev1/src/aprict/__init__.py +0 -47
- {aprict-0.0.24.dev1 → aprict-0.0.27}/LICENSE.txt +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/LICENSE_GPLv3.txt +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/MANIFEST.in +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/README.md +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/setup.cfg +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cb/__init__.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cb/_unused_old_fbp.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cb/noop_filter.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cb/ramp_filter.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cb/ramp_filter_cpu.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/__init__.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/_generate_cusrc.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/dtype_cacher.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/header_injection.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/kern_structs.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/ptx_cacher.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/FORBILD_volumes.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/__init__.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/base.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/config_cb_backproject.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/config_cb_project.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/config_cb_project_FORBILD.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/cu/FORBILD_Box.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/cu/FORBILD_ClipAxisSpec.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/cu/FORBILD_Cone.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/cu/FORBILD_Cone_x.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/cu/FORBILD_Cone_y.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/cu/FORBILD_Cone_z.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/cu/FORBILD_Cylinder.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/cu/FORBILD_Cylinder_x.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/cu/FORBILD_Cylinder_y.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/cu/FORBILD_Cylinder_z.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/cu/FORBILD_Ellipsoid.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/cu/FORBILD_Ellipsoid_free.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/cu/FORBILD_Ellipt_Cyl.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/cu/FORBILD_Ellipt_Cyl_x.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/cu/FORBILD_Ellipt_Cyl_y.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/cu/FORBILD_Ellipt_Cyl_z.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/cu/FORBILD_Shape.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/cu/FORBILD_Sphere.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/cu/__init__.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/geometry.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/test_subdir/__init__.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/cuda/structs/test_subdir/test_config.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/.gitignore +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/abdomen/AbdomenPhantom.pha +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/abdomen/AbdomenPhantom_fixed.pha +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/abdomen/TableOfTissues +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/abdomen/Wirbel.pha +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/custom_composite/Ribs.pha +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/custom_composite/Shoulders.pha +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/custom_composite/TableOfTissues +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/custom_composite/Vertebra.pha +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/custom_composite/part_01_hip.pha +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/custom_composite/part_02_abdomen.pha +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/custom_composite/part_03_thorax.pha +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/custom_composite/part_04_head.pha +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/custom_composite/part_05_jaw.pha +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/custom_other/rock_canister_01.pha +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/custom_other/rock_canister_01_cavities_1e5.pha +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/custom_other/unit_Cyl_z.pha +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/head/HeadPhantom.pha +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/head/TableOfTissues +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/hip/HipPhantom.pha +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/jaw/JawPhantom.pha +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/lungs/LungPhantom3Generations.pha +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/thorax/Ribs.pha +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/thorax/Shoulders.pha +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/thorax/TableOfTissues +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/thorax/ThoraxPhantom.pha +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/FORBILD/thorax/Vertebra.pha +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/README.txt +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/cusrc/CB_backproject.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/cusrc/CB_backproject_sharedmem.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/cusrc/CB_project_sharedmem.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/cusrc/CB_project_texture_chunked.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/cusrc/FORBILD_volumes.h +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/cusrc/base.h +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/cusrc/config_cb_backproject.h +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/cusrc/config_cb_project.h +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/cusrc/config_cb_project_FORBILD.h +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/cusrc/geometry.h +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/cusrc/get_bboxes_FORBILD.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/cusrc/ramlak_convolve.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/cusrc/sample_FORBILD_volumes.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/cusrc/test_kernel.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/cusrc/test_subdir/test_config.h +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/data/cusrc/texture_operations.cu +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/examples/lungs_sirt.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/gbc/__init__.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/gbc/filters.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/gbc/weightinteg.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/image_view.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/iterators/__init__.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/iterators/landweber_vram.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/iterators/sirt_vram.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/lib/__init__.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/lib/argparse_tools.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/lib/bboxes_FORBILD.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/lib/click_tools.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/lib/empty_context_manager.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/lib/gpu_tools.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/lib/import_tools.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/lib/lds.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/lib/ne_tools.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/lib/ng_tools.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/lib/np_tools.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/lib/process_pha_file.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/lib/sample_FORBILD.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/lib/texture_tools/__init__.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/lib/texture_tools/operations.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/lib/texture_tools/texture.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/liveplot.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/logtools/__init__.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/logtools/config.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/logtools/pbar.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/logtools/pbar_tqdm.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/logtools/rich_custombar.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/ramp_kernels.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/scripts/make_geometry_cone_cyl.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/scripts/make_geometry_fan_circ.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/scripts/neuroglance.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/scripts/recon_cbfp_cyl_fbp.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/scripts/recon_cbfp_cyl_gbc.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/scripts/recon_cbfp_landweber.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/tests/__init__.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/tests/cuda_kernels/__init__.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/tests/cuda_kernels/test_backproject_cb.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/tests/cuda_kernels/test_cusrc/__init__.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/tests/cuda_kernels/test_kernel_structs.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/tests/cuda_kernels/test_project_cb_FORBILD_shapes.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict/tests/test_volume.py +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict.egg-info/dependency_links.txt +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict.egg-info/requires.txt +0 -0
- {aprict-0.0.24.dev1 → aprict-0.0.27}/src/aprict.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Copyright (C) 2026 Murdock Grewar
|
|
2
|
+
#
|
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
6
|
+
# (at your option) any later version.
|
|
7
|
+
#
|
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11
|
+
# GNU General Public License for more details.
|
|
12
|
+
#
|
|
13
|
+
# You should have received a copy of the GNU General Public License
|
|
14
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
15
|
+
|
|
16
|
+
"""
|
|
17
|
+
[](https://orcid.org/0000-0002-0015-8284)
|
|
18
|
+
[](https://doi.org/10.5281/zenodo.23632625)
|
|
19
|
+

|
|
20
|
+
[](https://www.repostatus.org/#wip)
|
|
21
|
+
|
|
22
|
+
`aprict` is a Python module and commandline program for simulating flat-panel transmission X-ray experiments.
|
|
23
|
+
|
|
24
|
+
Recommended import pattern
|
|
25
|
+
--
|
|
26
|
+
|
|
27
|
+
The recommended import pattern for this module is
|
|
28
|
+
```python
|
|
29
|
+
import aprict
|
|
30
|
+
from aprict.cb import flatpanel as cbfp
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Main components
|
|
34
|
+
--
|
|
35
|
+
|
|
36
|
+
The main components of the end-user Python API are:
|
|
37
|
+
- [`aprict.FBVolume`](aprict/volume.html#FBVolume) - an attenuating volume defined in FORBILD format
|
|
38
|
+
- [`aprict.Volume`](aprict/volume.html#Volume) - an attenuating volume defined in voxelised format
|
|
39
|
+
- `aprict.cb.flatpanel` - a namespace for objects and functions applying to cone-beam imaging geometries
|
|
40
|
+
|
|
41
|
+
Examples
|
|
42
|
+
--
|
|
43
|
+
|
|
44
|
+
For examples of Python API usage, see `aprict.examples`.
|
|
45
|
+
|
|
46
|
+
Commandline interface
|
|
47
|
+
--
|
|
48
|
+
|
|
49
|
+
The entry point for the main commandline interface is the shell command `aprict`. This shell command should be available on `$PATH` if the module is installed in the current environment. All shell commands are self-documented:
|
|
50
|
+
```bash
|
|
51
|
+
$ aprict --help
|
|
52
|
+
```
|
|
53
|
+
""" # ruff: ignore[ambiguous-unicode-character-docstring, blank-lines-between-header-and-content, mismatched-section-underline-length, missing-blank-line-after-summary, missing-trailing-period]
|
|
54
|
+
|
|
55
|
+
# If we are just running the build script, then I don't want to initialise anything,
|
|
56
|
+
# because the imports fail because it hasn't built yet.
|
|
57
|
+
|
|
58
|
+
import os as _os
|
|
59
|
+
|
|
60
|
+
if _os.environ.get("APRICT_BUILDMODE", ""): # ruff: ignore[non-empty-init-module]
|
|
61
|
+
pass
|
|
62
|
+
else:
|
|
63
|
+
# Ensure that numexpr max threads is set to the number of logical cores before importing numexpr either directly or indirectly through other imports.
|
|
64
|
+
_nethreads_max_env = _os.environ.get("NUMEXPR_MAX_THREADS", None)
|
|
65
|
+
if _nethreads_max_env is None:
|
|
66
|
+
_os.environ["NUMEXPR_MAX_THREADS"] = str(_os.process_cpu_count())
|
|
67
|
+
|
|
68
|
+
del _os
|
|
69
|
+
from . import cb as cb
|
|
70
|
+
from . import image_view as imview
|
|
71
|
+
from . import iterators, lib, phantoms, volume
|
|
72
|
+
from .cuda import structs as dtypes
|
|
73
|
+
from .volume import FBVolume as FBVolume
|
|
74
|
+
|
|
75
|
+
FBVolume.__doc__ = "@private\nAn alias to aprict.volume.FBVolume" # Hide from pdoc documentation of this module
|
|
76
|
+
from .volume import Volume as Volume
|
|
77
|
+
|
|
78
|
+
Volume.__doc__ = "@private\nAn alias to aprict.volume.Volume" # Hide from pdoc documentation of this module
|
|
79
|
+
|
|
80
|
+
# Note that __all__ determines what's listed in the documentation page.
|
|
81
|
+
# So, I'm selecting only those parts which I want to be documented on the main doc page here.
|
|
82
|
+
__all__ = [
|
|
83
|
+
"FBVolume", # documented in aprict.volume
|
|
84
|
+
"Volume", # documented in aprict.volume
|
|
85
|
+
"cb",
|
|
86
|
+
"dtypes",
|
|
87
|
+
"imview",
|
|
88
|
+
"iterators",
|
|
89
|
+
"lib",
|
|
90
|
+
"phantoms",
|
|
91
|
+
"volume",
|
|
92
|
+
]
|
|
@@ -15,7 +15,21 @@
|
|
|
15
15
|
|
|
16
16
|
# flatpanel.py
|
|
17
17
|
|
|
18
|
-
"""
|
|
18
|
+
"""
|
|
19
|
+
End-user interfaces to the flat-panel cone-beam projection and backprojection CUDA code.
|
|
20
|
+
|
|
21
|
+
The main provided methods are
|
|
22
|
+
- `project` - used to generate projection data from a `aprict.volume.Volume` or `aprict.volume.FBVolume` object.
|
|
23
|
+
- `backproject` - used to generate backprojection data from a `aprict.volume.Volume` or `aprict.volume.FBVolume` object.
|
|
24
|
+
|
|
25
|
+
The main provided classes are
|
|
26
|
+
- `ProjGeom` - object to encode a flat-panel (back)projection geometry.
|
|
27
|
+
- `ProjectionSet` - object to hold a `ProjGeom` and associated projection data.
|
|
28
|
+
- `ConfigProject` - object to hold a collection of settings applied when computing projections with `project`.
|
|
29
|
+
- `ConfigBackproject` - object to hold a collection of settings applied when computing backprojections with `backproject`.
|
|
30
|
+
|
|
31
|
+
Note that the `ConfigBackproject` object allows for configuring weighted backprojections and the like. The `backproj_weighting_preset` attribute passed to its constructor can significantly influence the behaviour of the backprojection, since this value is passed to the CUDA kernel, which performs some internal logic depending on this value. Currently, the end user has limited control over what kind of weightings are applied, since adding new presets requires editing the CUDA kernel. The available presets will be documented at a later time. The default value of `0` corresponds to the adjoint of the forward projection.
|
|
32
|
+
"""
|
|
19
33
|
|
|
20
34
|
import dataclasses
|
|
21
35
|
import functools
|
|
@@ -42,7 +56,7 @@ _delay_compile: bool = (
|
|
|
42
56
|
|
|
43
57
|
|
|
44
58
|
def force_compile(*, log_stream: object | None = None) -> None:
|
|
45
|
-
"""Force the relevant CUDA kernels to compile."""
|
|
59
|
+
"""Force the relevant CUDA kernels to compile, if they have not already."""
|
|
46
60
|
_projection_module.compile(log_stream=log_stream)
|
|
47
61
|
_backprojection_module.compile(log_stream=log_stream)
|
|
48
62
|
|
|
@@ -250,7 +264,7 @@ class ProjGeom: # ruff: ignore[eq-without-hash]
|
|
|
250
264
|
tuple[float, float, float],
|
|
251
265
|
tuple[float, float, float],
|
|
252
266
|
]:
|
|
253
|
-
"""Return a bounding box."""
|
|
267
|
+
"""Return a bounding box like ((minx,miny,minz),(maxx,maxy,maxz))."""
|
|
254
268
|
# Make a list of points such that the whole projection geometry
|
|
255
269
|
# is contained in the convex hull. Then take the min x,y,z and max x,y,z
|
|
256
270
|
# it = slice(None, None) if index_tuple is None else index_tuple
|
|
@@ -713,7 +727,7 @@ class ProjectionSet:
|
|
|
713
727
|
tuple[float, float, float],
|
|
714
728
|
tuple[float, float, float],
|
|
715
729
|
]:
|
|
716
|
-
"""Return a bounding box."""
|
|
730
|
+
"""Return a bounding box like ((minx,miny,minz),(maxx,maxy,maxz))."""
|
|
717
731
|
return self._proj_geom.get_bbox(index_tuple=index_tuple)
|
|
718
732
|
|
|
719
733
|
@property
|
|
@@ -809,19 +823,19 @@ class ProjectionSet:
|
|
|
809
823
|
|
|
810
824
|
|
|
811
825
|
class ConfigProject:
|
|
812
|
-
"""Configuration object for projections. Some options will have no effect if a Volume
|
|
826
|
+
"""Configuration object for projections. This is to be passed to the `project` method. Some options will have no effect if applied improperly to a `Volume`/`FBVolume`."""
|
|
813
827
|
|
|
814
828
|
_contents: np.dtype[structs.config_cb_project] # ty:ignore[invalid-type-arguments]
|
|
815
829
|
_contents_fb: np.dtype[structs.config_cb_project_FORBILD] # ty:ignore[invalid-type-arguments]
|
|
816
830
|
|
|
817
831
|
@property
|
|
818
832
|
def contents(self) -> np.dtype[structs.config_cb_project]: # ty:ignore[invalid-type-arguments]
|
|
819
|
-
"""The configuration object underlying this object
|
|
833
|
+
"""The configuration object underlying this object, when applied to `Volume`."""
|
|
820
834
|
return self._contents.copy() # ty:ignore[unresolved-attribute]
|
|
821
835
|
|
|
822
836
|
@property
|
|
823
837
|
def contents_fb(self) -> np.dtype[structs.config_cb_project_FORBILD]: # ty:ignore[invalid-type-arguments]
|
|
824
|
-
"""The configuration object underlying this object
|
|
838
|
+
"""The configuration object underlying this object, when applied to `FBVolume`."""
|
|
825
839
|
return self._contents_fb.copy() # ty:ignore[unresolved-attribute]
|
|
826
840
|
|
|
827
841
|
def __init__(
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Copyright (C) 2026 Murdock Grewar
|
|
2
|
+
#
|
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
6
|
+
# (at your option) any later version.
|
|
7
|
+
#
|
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11
|
+
# GNU General Public License for more details.
|
|
12
|
+
#
|
|
13
|
+
# You should have received a copy of the GNU General Public License
|
|
14
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
15
|
+
|
|
16
|
+
"""
|
|
17
|
+
A submodule containing example scripts using the Python API.
|
|
18
|
+
|
|
19
|
+
Browse the `aprict` source code and navigate to this directory to see the examples.
|
|
20
|
+
|
|
21
|
+
Examples can be run with e.g. `python -m aprict.examples.EXAMPLE_NAME`.
|
|
22
|
+
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from . import (
|
|
26
|
+
composite_human_sirt,
|
|
27
|
+
fan_beam_sirt,
|
|
28
|
+
helical_sirt,
|
|
29
|
+
lungs_sirt,
|
|
30
|
+
trajtest_A_sirt,
|
|
31
|
+
triangle_exp_fb,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
__all__ = [
|
|
35
|
+
"composite_human_sirt",
|
|
36
|
+
"fan_beam_sirt",
|
|
37
|
+
"helical_sirt",
|
|
38
|
+
"lungs_sirt",
|
|
39
|
+
"trajtest_A_sirt",
|
|
40
|
+
"triangle_exp_fb",
|
|
41
|
+
]
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# You should have received a copy of the GNU General Public License
|
|
14
14
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
15
15
|
|
|
16
|
-
"""Simulate an example experiment
|
|
16
|
+
"""Simulate an example experiment and SIRT reconstruction using the composite human phantom."""
|
|
17
17
|
|
|
18
18
|
import itertools
|
|
19
19
|
import math
|
|
@@ -174,7 +174,7 @@ def main() -> None: # ruff: ignore[complex-structure, undocumented-public-funct
|
|
|
174
174
|
print("Voxel width (mm): ", voxwid_mm)
|
|
175
175
|
print()
|
|
176
176
|
print("Creating volume... ", end="", flush=True)
|
|
177
|
-
vol: aprict.FBVolume = aprict.phantoms.FORBILD.CustomComposite
|
|
177
|
+
vol: aprict.FBVolume = aprict.phantoms.FORBILD.CustomComposite()
|
|
178
178
|
if plot_volume:
|
|
179
179
|
print("plotting volume... ", end="", flush=True)
|
|
180
180
|
xs = np.linspace(-300, 300, num=601, endpoint=True)
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# You should have received a copy of the GNU General Public License
|
|
14
14
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
15
15
|
|
|
16
|
-
"""Simulate an example experiment
|
|
16
|
+
"""Simulate an example 2D fan-beam experiment and SIRT reconstruction."""
|
|
17
17
|
|
|
18
18
|
import math
|
|
19
19
|
import sys
|
|
@@ -99,7 +99,7 @@ def main() -> None: # ruff: ignore[undocumented-public-function]
|
|
|
99
99
|
|
|
100
100
|
# Create the volume to be projected
|
|
101
101
|
print("Voxel width (mm): ", voxwid_mm)
|
|
102
|
-
vol: aprict.FBVolume = aprict.phantoms.FORBILD.HeadPhantom
|
|
102
|
+
vol: aprict.FBVolume = aprict.phantoms.FORBILD.HeadPhantom()
|
|
103
103
|
xyz_min, xyz_max = vol.minxyz_maxxyz
|
|
104
104
|
volwid_mm = 1.1 * 2 * max(map(abs, (*xyz_min[:2], *xyz_max[:2])))
|
|
105
105
|
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# You should have received a copy of the GNU General Public License
|
|
14
14
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
15
15
|
|
|
16
|
-
"""Simulate an example experiment with a helical scan."""
|
|
16
|
+
"""Simulate an example experiment and SIRT reconstruction with a helical scan."""
|
|
17
17
|
|
|
18
18
|
import math
|
|
19
19
|
import sys
|
|
@@ -106,7 +106,7 @@ def main() -> None: # ruff: ignore[undocumented-public-function]
|
|
|
106
106
|
|
|
107
107
|
# Create the volume to be projected
|
|
108
108
|
print("Voxel width (mm): ", voxwid_mm)
|
|
109
|
-
vol: aprict.FBVolume = aprict.phantoms.FORBILD.HeadPhantom
|
|
109
|
+
vol: aprict.FBVolume = aprict.phantoms.FORBILD.HeadPhantom()
|
|
110
110
|
volwid_mm = 250 # in the future, fetch from the phantom
|
|
111
111
|
# Scale up the volume
|
|
112
112
|
vol.scale_len(scale_phantom_size)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# ruff: ignore[invalid-module-name]
|
|
1
2
|
# Copyright (C) 2026 Murdock Grewar
|
|
2
3
|
#
|
|
3
4
|
# This program is free software: you can redistribute it and/or modify
|
|
@@ -12,8 +13,7 @@
|
|
|
12
13
|
#
|
|
13
14
|
# You should have received a copy of the GNU General Public License
|
|
14
15
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
15
|
-
|
|
16
|
-
"""Simulate an example experiment with a helical scan."""
|
|
16
|
+
"""Simulate an example experiment and SIRT reconstruction with a cylindrical scan."""
|
|
17
17
|
|
|
18
18
|
import math
|
|
19
19
|
import sys
|
|
@@ -106,7 +106,7 @@ def main() -> None: # ruff: ignore[undocumented-public-function]
|
|
|
106
106
|
|
|
107
107
|
# Create the volume to be projected
|
|
108
108
|
print("Voxel width (mm): ", voxwid_mm)
|
|
109
|
-
vol: aprict.FBVolume = aprict.phantoms.FORBILD.HeadPhantom
|
|
109
|
+
vol: aprict.FBVolume = aprict.phantoms.FORBILD.HeadPhantom()
|
|
110
110
|
volwid_mm = 275 # in the future, fetch from the phantom
|
|
111
111
|
# Scale up the volume
|
|
112
112
|
vol.scale_len(scale_phantom_size)
|
|
@@ -246,8 +246,8 @@ def main() -> None: # ruff: ignore[undocumented-public-function]
|
|
|
246
246
|
_lp_process, lp_dispatcher = liveplot.start_live_plot_2d(
|
|
247
247
|
title="Live plot",
|
|
248
248
|
histogram_label="Attenuation coefficient",
|
|
249
|
-
plotmin=0.0184 *
|
|
250
|
-
plotmax=0.0184 *
|
|
249
|
+
plotmin=0.0184 * (1 + default_plot_range_HU[0] / 1000),
|
|
250
|
+
plotmax=0.0184 * (1 + default_plot_range_HU[1] / 1000),
|
|
251
251
|
show=False,
|
|
252
252
|
)
|
|
253
253
|
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# You should have received a copy of the GNU General Public License
|
|
14
14
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
15
15
|
|
|
16
|
-
"""Simulate an example experiment with a triangular scanning apparatus."""
|
|
16
|
+
"""Simulate an example experiment and Landweber reconstruction with a triangular scanning apparatus."""
|
|
17
17
|
|
|
18
18
|
import itertools
|
|
19
19
|
import math
|
|
@@ -243,8 +243,8 @@ def main() -> None: # ruff: ignore[undocumented-public-function]
|
|
|
243
243
|
|
|
244
244
|
# Create the volume to be projected
|
|
245
245
|
print("Voxel width (mm): ", voxwid_mm)
|
|
246
|
-
# vol: aprict.FBVolume = aprict.phantoms.FORBILD.HeadPhantom
|
|
247
|
-
vol: aprict.FBVolume = aprict.phantoms.FORBILD.CustomComposite
|
|
246
|
+
# vol: aprict.FBVolume = aprict.phantoms.FORBILD.HeadPhantom()
|
|
247
|
+
vol: aprict.FBVolume = aprict.phantoms.FORBILD.CustomComposite()
|
|
248
248
|
volwid_mm = 300 # in the future, fetch from the phantom
|
|
249
249
|
# Scale up the volume
|
|
250
250
|
vol.scale_len(scale_phantom_size)
|
|
@@ -14,9 +14,10 @@
|
|
|
14
14
|
# You should have received a copy of the GNU General Public License
|
|
15
15
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
16
16
|
|
|
17
|
-
"""Provides FORBILD phantoms from the files published by the Arbeitsgruppe Phantome."""
|
|
17
|
+
"""Provides FORBILD phantoms from the files published by the Arbeitsgruppe Phantome, as well as others."""
|
|
18
18
|
|
|
19
19
|
import dataclasses
|
|
20
|
+
import functools
|
|
20
21
|
import itertools
|
|
21
22
|
import math
|
|
22
23
|
import pathlib
|
|
@@ -30,19 +31,23 @@ from ..cuda.structs import FORBILD_volumes as fv
|
|
|
30
31
|
from ..lib import process_pha_file as ppf
|
|
31
32
|
from ..volume import FBVolume
|
|
32
33
|
|
|
33
|
-
|
|
34
|
+
_path_to_FORBILD_src = pathlib.Path(str(data.__path__[0])).joinpath("FORBILD") # ruff: ignore[mixed-case-variable-in-global-scope]
|
|
34
35
|
|
|
35
36
|
|
|
36
|
-
# ruff: disable[invalid-function-name
|
|
37
|
+
# ruff: disable[non-imperative-mood,invalid-function-name]
|
|
37
38
|
|
|
38
39
|
|
|
39
|
-
class
|
|
40
|
-
|
|
40
|
+
class PhantomContainer:
|
|
41
|
+
"""A container for the phantom objects."""
|
|
42
|
+
|
|
43
|
+
@classmethod
|
|
44
|
+
@functools.cache
|
|
41
45
|
def CustomComposite(cls) -> FBVolume:
|
|
46
|
+
"""A custom phantom stitching together and slightly modifying the Hip, Abdomen, Thorax, Head and Jaw phantom."""
|
|
42
47
|
hi, ab, th, he, ja = [
|
|
43
48
|
FBVolume(
|
|
44
49
|
ppf.convert_ph_file_to_shapes(
|
|
45
|
-
|
|
50
|
+
_path_to_FORBILD_src.joinpath("custom_composite/" + fn)
|
|
46
51
|
)
|
|
47
52
|
)
|
|
48
53
|
for fn in (
|
|
@@ -105,12 +110,13 @@ class _MetaPhantomContainer(type):
|
|
|
105
110
|
v = v.superimpose_onto(cavity)
|
|
106
111
|
return v # ruff: ignore[unnecessary-assign]
|
|
107
112
|
|
|
108
|
-
@
|
|
113
|
+
@classmethod
|
|
114
|
+
@functools.cache
|
|
109
115
|
def JawPhantom(cls) -> FBVolume:
|
|
110
|
-
"""The
|
|
116
|
+
"""The [Jaw phantom](https://www.dkfz.de/en/x-ray-imaging-and-computed-tomography/jaw-phantom)."""
|
|
111
117
|
fbv = FBVolume(
|
|
112
118
|
ppf.convert_ph_file_to_shapes(
|
|
113
|
-
|
|
119
|
+
_path_to_FORBILD_src.joinpath("jaw/JawPhantom.pha")
|
|
114
120
|
)
|
|
115
121
|
)
|
|
116
122
|
# Phantom is defined with centimeters as the unit of length.
|
|
@@ -118,12 +124,13 @@ class _MetaPhantomContainer(type):
|
|
|
118
124
|
fbv.scale_len(10)
|
|
119
125
|
return fbv
|
|
120
126
|
|
|
121
|
-
@
|
|
127
|
+
@classmethod
|
|
128
|
+
@functools.cache
|
|
122
129
|
def HeadPhantom(cls) -> FBVolume:
|
|
123
|
-
"""
|
|
130
|
+
"""The [Head phantom](https://www.dkfz.de/en/x-ray-imaging-and-computed-tomography/head-phantom)."""
|
|
124
131
|
fbv = FBVolume(
|
|
125
132
|
ppf.convert_ph_file_to_shapes(
|
|
126
|
-
|
|
133
|
+
_path_to_FORBILD_src.joinpath("head/HeadPhantom.pha")
|
|
127
134
|
)
|
|
128
135
|
)
|
|
129
136
|
# Phantom is defined with centimeters as the unit of length.
|
|
@@ -131,12 +138,13 @@ class _MetaPhantomContainer(type):
|
|
|
131
138
|
fbv.scale_len(10)
|
|
132
139
|
return fbv
|
|
133
140
|
|
|
134
|
-
@
|
|
141
|
+
@classmethod
|
|
142
|
+
@functools.cache
|
|
135
143
|
def HipPhantom(cls) -> FBVolume:
|
|
136
|
-
"""
|
|
144
|
+
"""The [Hip phantom](https://www.dkfz.de/en/x-ray-imaging-and-computed-tomography/hip-phantom)."""
|
|
137
145
|
fbv = FBVolume(
|
|
138
146
|
ppf.convert_ph_file_to_shapes(
|
|
139
|
-
|
|
147
|
+
_path_to_FORBILD_src.joinpath("hip/HipPhantom.pha")
|
|
140
148
|
)
|
|
141
149
|
)
|
|
142
150
|
# Phantom is defined with centimeters as the unit of length.
|
|
@@ -144,13 +152,14 @@ class _MetaPhantomContainer(type):
|
|
|
144
152
|
fbv.scale_len(10)
|
|
145
153
|
return fbv
|
|
146
154
|
|
|
147
|
-
@
|
|
155
|
+
@classmethod
|
|
156
|
+
@functools.cache
|
|
148
157
|
def AbdomenPhantom(cls) -> FBVolume:
|
|
149
|
-
"""Fixed
|
|
158
|
+
"""Fixed [Abdomen phantom](https://www.dkfz.de/en/x-ray-imaging-and-computed-tomography/abdominal-phantom)."""
|
|
150
159
|
# The AbdomenPhantom.pha file has a bug in it. Load a manually fixed version.
|
|
151
160
|
fbv = FBVolume(
|
|
152
161
|
ppf.convert_ph_file_to_shapes(
|
|
153
|
-
|
|
162
|
+
_path_to_FORBILD_src.joinpath(
|
|
154
163
|
"abdomen/AbdomenPhantom_fixed.pha"
|
|
155
164
|
)
|
|
156
165
|
)
|
|
@@ -160,13 +169,14 @@ class _MetaPhantomContainer(type):
|
|
|
160
169
|
fbv.scale_len(10)
|
|
161
170
|
return fbv
|
|
162
171
|
|
|
163
|
-
@
|
|
172
|
+
@classmethod
|
|
173
|
+
@functools.cache
|
|
164
174
|
def LungPhantom3Generations(cls) -> FBVolume:
|
|
165
|
-
"""
|
|
175
|
+
"""The [Lung phantom](https://www.dkfz.de/en/x-ray-imaging-and-computed-tomography/lung-phantom) to 3 generations."""
|
|
166
176
|
# DEV NOTE: make sure this phantom loads the reference file published by the Arbeitsgruppe Phantome. This is used in a unittest to ensure that the generation procedure for N generations matches in this case.
|
|
167
177
|
fbv = FBVolume(
|
|
168
178
|
ppf.convert_ph_file_to_shapes(
|
|
169
|
-
|
|
179
|
+
_path_to_FORBILD_src.joinpath(
|
|
170
180
|
"lungs/LungPhantom3Generations.pha"
|
|
171
181
|
)
|
|
172
182
|
)
|
|
@@ -175,12 +185,13 @@ class _MetaPhantomContainer(type):
|
|
|
175
185
|
fbv.flip(axis="z")
|
|
176
186
|
return fbv
|
|
177
187
|
|
|
178
|
-
@
|
|
188
|
+
@classmethod
|
|
189
|
+
@functools.cache
|
|
179
190
|
def ThoraxPhantom(cls) -> FBVolume:
|
|
180
|
-
"""
|
|
191
|
+
"""The [Thorax phantom](https://www.dkfz.de/en/x-ray-imaging-and-computed-tomography/thorax-phantom)."""
|
|
181
192
|
fbv = FBVolume(
|
|
182
193
|
ppf.convert_ph_file_to_shapes(
|
|
183
|
-
|
|
194
|
+
_path_to_FORBILD_src.joinpath("thorax/ThoraxPhantom.pha")
|
|
184
195
|
)
|
|
185
196
|
)
|
|
186
197
|
# Phantom is defined with centimeters as the unit of length.
|
|
@@ -188,11 +199,13 @@ class _MetaPhantomContainer(type):
|
|
|
188
199
|
fbv.scale_len(10)
|
|
189
200
|
return fbv
|
|
190
201
|
|
|
191
|
-
@
|
|
202
|
+
@classmethod
|
|
203
|
+
@functools.cache
|
|
192
204
|
def RockCanisterAl(cls) -> FBVolume:
|
|
205
|
+
"""A phantom resembling a 6-millimeter-wide double-chambered tube of rocks."""
|
|
193
206
|
fbv = FBVolume(
|
|
194
207
|
ppf.convert_ph_file_to_shapes(
|
|
195
|
-
|
|
208
|
+
_path_to_FORBILD_src.joinpath(
|
|
196
209
|
"custom_other/rock_canister_01.pha"
|
|
197
210
|
),
|
|
198
211
|
skip_preprocessing=True, # I know that this file doesn't require preprocessing
|
|
@@ -202,26 +215,30 @@ class _MetaPhantomContainer(type):
|
|
|
202
215
|
fbv.multiply_attenuation(0.55)
|
|
203
216
|
return fbv
|
|
204
217
|
|
|
205
|
-
@
|
|
218
|
+
@classmethod
|
|
219
|
+
@functools.cache
|
|
206
220
|
def RockCanisterCavities1e5(cls) -> FBVolume:
|
|
221
|
+
"""An appendage to the RockCanisterAl phantom which adds small cavities to the aluminium canister."""
|
|
207
222
|
return FBVolume(
|
|
208
223
|
ppf.convert_ph_file_to_shapes(
|
|
209
|
-
|
|
224
|
+
_path_to_FORBILD_src.joinpath(
|
|
210
225
|
"custom_other/rock_canister_01_cavities_1e5.pha"
|
|
211
226
|
),
|
|
212
227
|
skip_preprocessing=True, # I know that this file doesn't require preprocessing
|
|
213
228
|
)
|
|
214
229
|
)
|
|
215
230
|
|
|
216
|
-
@
|
|
231
|
+
@classmethod
|
|
232
|
+
@functools.cache
|
|
217
233
|
def RockCanisterAlWithHoles(cls) -> FBVolume:
|
|
234
|
+
"""A phantom resembling a 6-millimeter-wide double-chambered tube of rocks, with small cavities inthe aluminium cylinder."""
|
|
218
235
|
fbv = FBVolume(
|
|
219
236
|
ppf.convert_ph_file_to_shapes(
|
|
220
|
-
|
|
237
|
+
_path_to_FORBILD_src.joinpath(
|
|
221
238
|
"custom_other/rock_canister_01.pha"
|
|
222
239
|
),
|
|
223
240
|
append_files=(
|
|
224
|
-
|
|
241
|
+
_path_to_FORBILD_src.joinpath(
|
|
225
242
|
"custom_other/rock_canister_01_cavities_1e5.pha"
|
|
226
243
|
),
|
|
227
244
|
),
|
|
@@ -232,18 +249,16 @@ class _MetaPhantomContainer(type):
|
|
|
232
249
|
fbv.multiply_attenuation(0.55)
|
|
233
250
|
return fbv
|
|
234
251
|
|
|
235
|
-
@
|
|
252
|
+
@classmethod
|
|
253
|
+
@functools.cache
|
|
236
254
|
def UnitCyl_z(cls) -> FBVolume:
|
|
255
|
+
"""Unit z cylinder."""
|
|
237
256
|
return FBVolume(
|
|
238
257
|
ppf.convert_ph_file_to_shapes(
|
|
239
|
-
|
|
258
|
+
_path_to_FORBILD_src.joinpath("custom_other/unit_Cyl_z.pha")
|
|
240
259
|
)
|
|
241
260
|
)
|
|
242
261
|
|
|
243
|
-
|
|
244
|
-
class PhantomContainer(metaclass=_MetaPhantomContainer):
|
|
245
|
-
"""A container for the phantom objects."""
|
|
246
|
-
|
|
247
262
|
@classmethod
|
|
248
263
|
def _LungPhantom_phastring( # ruff: ignore[complex-structure]
|
|
249
264
|
cls,
|
|
@@ -254,7 +269,7 @@ class PhantomContainer(metaclass=_MetaPhantomContainer):
|
|
|
254
269
|
fix: bool
|
|
255
270
|
| None = None, # Leave at None for default configuration. Turning this True will fix what appear to be errors in the original phantom. These errors are particularly noticeable with e.g. taper=True.
|
|
256
271
|
) -> str:
|
|
257
|
-
"""Generate the Lung phantom (by Marc Kachelrieß) up to generation n."""
|
|
272
|
+
"""Generate the [Lung phantom](https://www.dkfz.de/en/x-ray-imaging-and-computed-tomography/lung-phantom) (by Markus Blank and Marc Kachelrieß) up to generation n."""
|
|
258
273
|
if type(generation) is not int or generation < 2:
|
|
259
274
|
msg = "'generation' must be an integer >=2"
|
|
260
275
|
raise ValueError(msg)
|
|
@@ -534,7 +549,7 @@ class PhantomContainer(metaclass=_MetaPhantomContainer):
|
|
|
534
549
|
fix: bool
|
|
535
550
|
| None = None, # Leave at None for default configuration. Turning this True will fix what appear to be errors in the original phantom. These errors are particularly noticeable with e.g. taper=True.
|
|
536
551
|
) -> FBVolume:
|
|
537
|
-
"""Generate the Lung phantom (by Marc Kachelrieß) up to generation n."""
|
|
552
|
+
"""Generate the [Lung phantom](https://www.dkfz.de/en/x-ray-imaging-and-computed-tomography/lung-phantom) (by Markus Blank and Marc Kachelrieß) up to generation n."""
|
|
538
553
|
phastr: str = cls._LungPhantom_phastring(
|
|
539
554
|
generation=generation,
|
|
540
555
|
scale_factor=scale_factor,
|
|
@@ -657,7 +672,7 @@ class PhantomContainer(metaclass=_MetaPhantomContainer):
|
|
|
657
672
|
randomise_parity: bool = False,
|
|
658
673
|
seed: int | None = None,
|
|
659
674
|
) -> FBVolume:
|
|
660
|
-
"""Generate a disc-shaped resolution phantom."""
|
|
675
|
+
"""Generate a disc-shaped resolution phantom (use as a 2D phantom with z=0)."""
|
|
661
676
|
if generation < 1:
|
|
662
677
|
msg = "Generation should be a positive integer."
|
|
663
678
|
raise ValueError(msg)
|
|
@@ -996,4 +1011,4 @@ class PhantomContainer(metaclass=_MetaPhantomContainer):
|
|
|
996
1011
|
return FBVolume(np.array(shapes, dtype=fv.Shape))
|
|
997
1012
|
|
|
998
1013
|
|
|
999
|
-
# ruff: enable[invalid-function-name
|
|
1014
|
+
# ruff: enable[non-imperative-mood,invalid-function-name]
|
|
@@ -13,7 +13,11 @@
|
|
|
13
13
|
# You should have received a copy of the GNU General Public License
|
|
14
14
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
15
15
|
|
|
16
|
-
"""
|
|
16
|
+
"""
|
|
17
|
+
Phantom objects useful for simulations and testing.
|
|
18
|
+
|
|
19
|
+
These can be loaded with e.g. `aprict.phantoms.FORBILD.HeadPhantom()`.
|
|
20
|
+
"""
|
|
17
21
|
|
|
18
22
|
from .FORBILD_phantoms import (
|
|
19
23
|
PhantomContainer as FORBILD, # ruff: ignore[camelcase-imported-as-constant]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Copyright (C) 2026 Murdock Grewar
|
|
2
|
+
#
|
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
6
|
+
# (at your option) any later version.
|
|
7
|
+
#
|
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
11
|
+
# GNU General Public License for more details.
|
|
12
|
+
#
|
|
13
|
+
# You should have received a copy of the GNU General Public License
|
|
14
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
15
|
+
|
|
16
|
+
"""
|
|
17
|
+
Scripts to use `aprict` with a commandline interface.
|
|
18
|
+
|
|
19
|
+
The recommended entry point is `aprict.scripts.cli`, which is a wrapper for the other scirpts. When `aprict` is installed in the current environment, this can be called from the shell with `aprict-cli`.
|
|
20
|
+
"""
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# You should have received a copy of the GNU General Public License
|
|
14
14
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
15
15
|
|
|
16
|
-
"""
|
|
16
|
+
"""The main command-line interface to aprict."""
|
|
17
17
|
|
|
18
18
|
import click_extra as ce
|
|
19
19
|
|
|
@@ -36,7 +36,7 @@ _cs = {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
@ce.group(name="aprict
|
|
39
|
+
@ce.group(name="aprict", params=None, help=_progdesc, context_settings=_cs)
|
|
40
40
|
@ce.version_option(version=version) # add --version from click_extra
|
|
41
41
|
@ce.tree_option() # add --tree option from click_extra
|
|
42
42
|
# not including the man_option because it includes incorrect information, like possible exit codes etc.
|