aprict 0.0.14__py3-none-any.whl

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.
Files changed (150) hide show
  1. aprict/__init__.py +47 -0
  2. aprict/cb/__init__.py +21 -0
  3. aprict/cb/_unused_old_fbp.py +113 -0
  4. aprict/cb/flatpanel.py +1169 -0
  5. aprict/cb/noop_filter.py +131 -0
  6. aprict/cb/ramp_filter.py +897 -0
  7. aprict/cb/ramp_filter_cpu.py +550 -0
  8. aprict/cuda/__init__.py +15 -0
  9. aprict/cuda/_generate_cusrc.py +152 -0
  10. aprict/cuda/dtype_cacher.py +79 -0
  11. aprict/cuda/header_injection.py +71 -0
  12. aprict/cuda/kern_structs.py +427 -0
  13. aprict/cuda/ptx_cacher.py +98 -0
  14. aprict/cuda/structs/FORBILD_volumes.py +610 -0
  15. aprict/cuda/structs/__init__.py +37 -0
  16. aprict/cuda/structs/base.py +291 -0
  17. aprict/cuda/structs/config_cb_backproject.py +76 -0
  18. aprict/cuda/structs/config_cb_project.py +42 -0
  19. aprict/cuda/structs/config_cb_project_FORBILD.py +43 -0
  20. aprict/cuda/structs/cu/FORBILD_Box.cu +78 -0
  21. aprict/cuda/structs/cu/FORBILD_ClipAxisSpec.cu +63 -0
  22. aprict/cuda/structs/cu/FORBILD_Cone.cu +71 -0
  23. aprict/cuda/structs/cu/FORBILD_Cone_x.cu +51 -0
  24. aprict/cuda/structs/cu/FORBILD_Cone_y.cu +51 -0
  25. aprict/cuda/structs/cu/FORBILD_Cone_z.cu +230 -0
  26. aprict/cuda/structs/cu/FORBILD_Cylinder.cu +122 -0
  27. aprict/cuda/structs/cu/FORBILD_Cylinder_x.cu +42 -0
  28. aprict/cuda/structs/cu/FORBILD_Cylinder_y.cu +42 -0
  29. aprict/cuda/structs/cu/FORBILD_Cylinder_z.cu +42 -0
  30. aprict/cuda/structs/cu/FORBILD_Ellipsoid.cu +50 -0
  31. aprict/cuda/structs/cu/FORBILD_Ellipsoid_free.cu +71 -0
  32. aprict/cuda/structs/cu/FORBILD_Ellipt_Cyl.cu +73 -0
  33. aprict/cuda/structs/cu/FORBILD_Ellipt_Cyl_x.cu +53 -0
  34. aprict/cuda/structs/cu/FORBILD_Ellipt_Cyl_y.cu +53 -0
  35. aprict/cuda/structs/cu/FORBILD_Ellipt_Cyl_z.cu +53 -0
  36. aprict/cuda/structs/cu/FORBILD_Shape.cu +665 -0
  37. aprict/cuda/structs/cu/FORBILD_Sphere.cu +81 -0
  38. aprict/cuda/structs/cu/__init__.py +15 -0
  39. aprict/cuda/structs/geometry.py +189 -0
  40. aprict/cuda/structs/test_subdir/__init__.py +17 -0
  41. aprict/cuda/structs/test_subdir/test_config.py +36 -0
  42. aprict/data/.gitignore +4 -0
  43. aprict/data/FORBILD/abdomen/AbdomenPhantom.pha +168 -0
  44. aprict/data/FORBILD/abdomen/AbdomenPhantom_fixed.pha +175 -0
  45. aprict/data/FORBILD/abdomen/TableOfTissues +34 -0
  46. aprict/data/FORBILD/abdomen/Wirbel.pha +28 -0
  47. aprict/data/FORBILD/custom_composite/Ribs.pha +223 -0
  48. aprict/data/FORBILD/custom_composite/Shoulders.pha +28 -0
  49. aprict/data/FORBILD/custom_composite/TableOfTissues +34 -0
  50. aprict/data/FORBILD/custom_composite/Vertebra.pha +26 -0
  51. aprict/data/FORBILD/custom_composite/part_01_hip.pha +248 -0
  52. aprict/data/FORBILD/custom_composite/part_02_abdomen.pha +168 -0
  53. aprict/data/FORBILD/custom_composite/part_03_thorax.pha +53 -0
  54. aprict/data/FORBILD/custom_composite/part_04_head.pha +776 -0
  55. aprict/data/FORBILD/custom_composite/part_05_jaw.pha +507 -0
  56. aprict/data/FORBILD/custom_other/rock_canister_01.pha +101500 -0
  57. aprict/data/FORBILD/custom_other/rock_canister_01_cavities_1e5.pha +10000 -0
  58. aprict/data/FORBILD/custom_other/unit_Cyl_z.pha +1 -0
  59. aprict/data/FORBILD/head/HeadPhantom.pha +776 -0
  60. aprict/data/FORBILD/head/TableOfTissues +34 -0
  61. aprict/data/FORBILD/hip/HipPhantom.pha +248 -0
  62. aprict/data/FORBILD/jaw/JawPhantom.pha +502 -0
  63. aprict/data/FORBILD/lungs/LungPhantom3Generations.pha +590 -0
  64. aprict/data/FORBILD/thorax/Ribs.pha +223 -0
  65. aprict/data/FORBILD/thorax/Shoulders.pha +28 -0
  66. aprict/data/FORBILD/thorax/TableOfTissues +34 -0
  67. aprict/data/FORBILD/thorax/ThoraxPhantom.pha +53 -0
  68. aprict/data/FORBILD/thorax/Vertebra.pha +26 -0
  69. aprict/data/README.txt +5 -0
  70. aprict/data/cusrc/CB_backproject.cu +833 -0
  71. aprict/data/cusrc/CB_backproject_sharedmem.cu +383 -0
  72. aprict/data/cusrc/CB_project_sharedmem.cu +324 -0
  73. aprict/data/cusrc/CB_project_texture_chunked.cu +616 -0
  74. aprict/data/cusrc/FORBILD_volumes.h +2081 -0
  75. aprict/data/cusrc/base.h +227 -0
  76. aprict/data/cusrc/config_cb_backproject.h +22 -0
  77. aprict/data/cusrc/config_cb_project.h +7 -0
  78. aprict/data/cusrc/config_cb_project_FORBILD.h +7 -0
  79. aprict/data/cusrc/geometry.h +93 -0
  80. aprict/data/cusrc/get_bboxes_FORBILD.cu +21 -0
  81. aprict/data/cusrc/ramlak_convolve.cu +102 -0
  82. aprict/data/cusrc/sample_FORBILD_volumes.cu +123 -0
  83. aprict/data/cusrc/test_kernel.cu +59 -0
  84. aprict/data/cusrc/test_subdir/test_config.h +5 -0
  85. aprict/data/cusrc/texture_operations.cu +344 -0
  86. aprict/examples/composite_human_sirt.py +418 -0
  87. aprict/examples/fan_beam_sirt.py +263 -0
  88. aprict/examples/helical_sirt.py +268 -0
  89. aprict/examples/lungs_sirt.py +315 -0
  90. aprict/examples/trajtest_A_sirt.py +270 -0
  91. aprict/examples/triangle_exp_fb.py +468 -0
  92. aprict/gbc/__init__.py +19 -0
  93. aprict/gbc/filters.py +558 -0
  94. aprict/gbc/weightinteg.py +174 -0
  95. aprict/image_view.py +165 -0
  96. aprict/iterators/__init__.py +19 -0
  97. aprict/iterators/landweber_vram.py +265 -0
  98. aprict/iterators/sirt_vram.py +157 -0
  99. aprict/lib/__init__.py +27 -0
  100. aprict/lib/argparse_tools.py +221 -0
  101. aprict/lib/bboxes_FORBILD.py +97 -0
  102. aprict/lib/click_tools.py +214 -0
  103. aprict/lib/empty_context_manager.py +26 -0
  104. aprict/lib/gpu_tools.py +248 -0
  105. aprict/lib/import_tools.py +32 -0
  106. aprict/lib/lds.py +495 -0
  107. aprict/lib/ne_tools.py +234 -0
  108. aprict/lib/ng_tools.py +162 -0
  109. aprict/lib/np_tools.py +29 -0
  110. aprict/lib/process_pha_file.py +388 -0
  111. aprict/lib/sample_FORBILD.py +170 -0
  112. aprict/lib/texture_tools/__init__.py +19 -0
  113. aprict/lib/texture_tools/operations.py +500 -0
  114. aprict/lib/texture_tools/texture.py +331 -0
  115. aprict/liveplot.py +221 -0
  116. aprict/logtools/__init__.py +20 -0
  117. aprict/logtools/config.py +173 -0
  118. aprict/logtools/pbar.py +182 -0
  119. aprict/logtools/pbar_tqdm.py +100 -0
  120. aprict/logtools/rich_custombar.py +183 -0
  121. aprict/phantoms/FORBILD_phantoms.py +999 -0
  122. aprict/phantoms/__init__.py +24 -0
  123. aprict/ramp_kernels.py +98 -0
  124. aprict/scripts/cli.py +121 -0
  125. aprict/scripts/make_geometry_cone_cyl.py +305 -0
  126. aprict/scripts/make_geometry_fan_circ.py +270 -0
  127. aprict/scripts/neuroglance.py +77 -0
  128. aprict/scripts/project_cbfp.py +493 -0
  129. aprict/scripts/recon_cbfp_cyl_fbp.py +894 -0
  130. aprict/scripts/recon_cbfp_cyl_gbc.py +954 -0
  131. aprict/scripts/recon_cbfp_landweber.py +577 -0
  132. aprict/tests/__init__.py +16 -0
  133. aprict/tests/cuda_kernels/__init__.py +16 -0
  134. aprict/tests/cuda_kernels/test_backproject_cb.py +552 -0
  135. aprict/tests/cuda_kernels/test_cusrc/__init__.py +16 -0
  136. aprict/tests/cuda_kernels/test_kernel_structs.py +163 -0
  137. aprict/tests/cuda_kernels/test_project_cb.py +662 -0
  138. aprict/tests/cuda_kernels/test_project_cb_FORBILD_phantoms.py +205 -0
  139. aprict/tests/cuda_kernels/test_project_cb_FORBILD_shapes.py +877 -0
  140. aprict/tests/test_FORBILD_lungs_construction.py +64 -0
  141. aprict/tests/test_volume.py +70 -0
  142. aprict/version.py +19 -0
  143. aprict/volume.py +811 -0
  144. aprict-0.0.14.dist-info/METADATA +323 -0
  145. aprict-0.0.14.dist-info/RECORD +150 -0
  146. aprict-0.0.14.dist-info/WHEEL +5 -0
  147. aprict-0.0.14.dist-info/entry_points.txt +9 -0
  148. aprict-0.0.14.dist-info/licenses/LICENSE.txt +14 -0
  149. aprict-0.0.14.dist-info/licenses/LICENSE_GPLv3.txt +674 -0
  150. aprict-0.0.14.dist-info/top_level.txt +1 -0
aprict/__init__.py ADDED
@@ -0,0 +1,47 @@
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
+ """Main module."""
17
+
18
+ # If we are just running the build script, then I don't want to initialise anything,
19
+ # because the imports fail because it hasn't built yet.
20
+
21
+ import os as _os
22
+
23
+ if _os.environ.get("SNOOKERR_BUILDMODE", ""): # ruff: ignore[non-empty-init-module]
24
+ pass
25
+ else:
26
+ # Ensure that numexpr max threads is set to the number of logical cores before importing numexpr either directly or indirectly through other imports.
27
+ _nethreads_max_env = _os.environ.get("NUMEXPR_MAX_THREADS", None)
28
+ if _nethreads_max_env is None:
29
+ _os.environ["NUMEXPR_MAX_THREADS"] = str(_os.process_cpu_count())
30
+
31
+ del _os
32
+ from . import cb as cb
33
+ from . import image_view as imview
34
+ from . import iterators, lib, phantoms
35
+ from .cuda import structs as dtypes
36
+ from .volume import FBVolume, Volume
37
+
38
+ __all__ = [
39
+ "FBVolume",
40
+ "Volume",
41
+ "cb",
42
+ "dtypes",
43
+ "imview",
44
+ "iterators",
45
+ "lib",
46
+ "phantoms",
47
+ ]
aprict/cb/__init__.py ADDED
@@ -0,0 +1,21 @@
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
+ """End-user interfaces to the cone-beam projection and backprojection CUDA code."""
17
+
18
+ from . import flatpanel as flatpanel
19
+ from .noop_filter import NoOpFilterer as NoOpFilterer
20
+ from .ramp_filter import FBPFilterer as FBPFilterer
21
+ from .ramp_filter_cpu import FBPFiltererCPU as FBPFiltererCPU
@@ -0,0 +1,113 @@
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
+ # fbp.py
17
+
18
+ """Methods to compute filtered backprojecitons for the cylindrical CBCT geometry."""
19
+
20
+ import functools
21
+ import itertools
22
+ import math
23
+
24
+ import cupy as cp
25
+ import numpy as np
26
+
27
+ from ..cuda import header_injection, structs
28
+ from ..cuda.kern_structs import _np_dtype_to_c_type
29
+
30
+
31
+ @functools.lru_cache(maxsize=10)
32
+ def _get_kernel(dtype: np.dtype, axis_len: int) -> cp.RawKernel:
33
+ dtype_str = _np_dtype_to_c_type[dtype]
34
+ module: cp.RawModule = header_injection.load_injected_module(
35
+ "./ramlak_convolve.cu",
36
+ name_expressions=[
37
+ f"convolve_with_ramlak_x<{t1:s},{t2:d}>"
38
+ for (t1, t2) in itertools.product(
39
+ [dtype_str],
40
+ [axis_len],
41
+ )
42
+ ],
43
+ )
44
+ # module.compile()
45
+ function: cp.RawKernel = module.get_function(
46
+ "convolve_with_ramlak_x<{t1:s},{t2:d}>".format(
47
+ t1=dtype_str, t2=axis_len
48
+ )
49
+ )
50
+ return function
51
+
52
+
53
+ def ramp_filter_1d_smallest_stride_axis(
54
+ cparr: cp.ndarray, physpixwid: float = 1
55
+ ) -> cp.ndarray:
56
+ """Apply a 1D ramp filter to the array, along the axis of lowest stride in memory."""
57
+ axes = [0, 1, 2]
58
+ axis: int = min(axes, key=lambda a: cparr.strides[a])
59
+ del axes[axis] # leave the remaining two axes in the list
60
+ axes_ordered = [axis, axes[0], axes[1]]
61
+
62
+ # Figure out how many blocks of max size 1024 are required
63
+ numxblocks = (cparr.shape[axis] + (1024 - 1)) // 1024
64
+ xblocksize = math.ceil(
65
+ cparr.shape[axis] / numxblocks
66
+ ) # make blocks evenly sized
67
+ block_dims = (xblocksize, 1, 1)
68
+ grid_dims = (
69
+ numxblocks,
70
+ cparr.shape[axes_ordered[1]],
71
+ cparr.shape[axes_ordered[2]],
72
+ )
73
+ bytes_per_block = cparr.itemsize * math.prod(block_dims)
74
+ if bytes_per_block > 48 * 1024:
75
+ msg = "Convolution axis too long for this method to handle! This is based on a shared memory size of 48kB."
76
+ raise NotImplementedError(msg)
77
+ args = (
78
+ cparr,
79
+ np.array(
80
+ tuple(np.array(cparr.shape)[axes_ordered].tolist()),
81
+ dtype=structs.uivec3,
82
+ ), # unsigned int
83
+ np.array(
84
+ tuple(np.array(cparr.strides)[axes_ordered].tolist()),
85
+ dtype=structs.ulvec3,
86
+ ), # unsigned long
87
+ np.float32(physpixwid),
88
+ )
89
+ kern = _get_kernel(cparr.dtype, cparr.shape[axis])
90
+ kern(grid_dims, block_dims, args)
91
+
92
+
93
+ if __name__ == "__main__":
94
+ ncycles: int = 100
95
+ cparr = cp.zeros((10, 4000, 3001), dtype=cp.float32).transpose((0, 2, 1))
96
+ cparr[:, cparr.shape[1] // 2, :] = 1
97
+ # image_view.plot_projections(cparr)
98
+ import time
99
+
100
+ from .. import image_view
101
+
102
+ t1 = time.time()
103
+ for _ in range(ncycles):
104
+ cparr.fill(0)
105
+ cparr[:, cparr.shape[1] // 2, :] = 1
106
+ ramp_filter_1d_smallest_stride_axis(cparr, physpixwid=1)
107
+ cp.cuda.get_current_stream().synchronize()
108
+ t2 = time.time()
109
+ print(
110
+ f"Milliseconds elapsed per trial per projection: {1000 * (t2 - t1) / ncycles / cparr.shape[0]:.0f}."
111
+ )
112
+
113
+ image_view.plot_projections(cparr)