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.
- aprict/__init__.py +47 -0
- aprict/cb/__init__.py +21 -0
- aprict/cb/_unused_old_fbp.py +113 -0
- aprict/cb/flatpanel.py +1169 -0
- aprict/cb/noop_filter.py +131 -0
- aprict/cb/ramp_filter.py +897 -0
- aprict/cb/ramp_filter_cpu.py +550 -0
- aprict/cuda/__init__.py +15 -0
- aprict/cuda/_generate_cusrc.py +152 -0
- aprict/cuda/dtype_cacher.py +79 -0
- aprict/cuda/header_injection.py +71 -0
- aprict/cuda/kern_structs.py +427 -0
- aprict/cuda/ptx_cacher.py +98 -0
- aprict/cuda/structs/FORBILD_volumes.py +610 -0
- aprict/cuda/structs/__init__.py +37 -0
- aprict/cuda/structs/base.py +291 -0
- aprict/cuda/structs/config_cb_backproject.py +76 -0
- aprict/cuda/structs/config_cb_project.py +42 -0
- aprict/cuda/structs/config_cb_project_FORBILD.py +43 -0
- aprict/cuda/structs/cu/FORBILD_Box.cu +78 -0
- aprict/cuda/structs/cu/FORBILD_ClipAxisSpec.cu +63 -0
- aprict/cuda/structs/cu/FORBILD_Cone.cu +71 -0
- aprict/cuda/structs/cu/FORBILD_Cone_x.cu +51 -0
- aprict/cuda/structs/cu/FORBILD_Cone_y.cu +51 -0
- aprict/cuda/structs/cu/FORBILD_Cone_z.cu +230 -0
- aprict/cuda/structs/cu/FORBILD_Cylinder.cu +122 -0
- aprict/cuda/structs/cu/FORBILD_Cylinder_x.cu +42 -0
- aprict/cuda/structs/cu/FORBILD_Cylinder_y.cu +42 -0
- aprict/cuda/structs/cu/FORBILD_Cylinder_z.cu +42 -0
- aprict/cuda/structs/cu/FORBILD_Ellipsoid.cu +50 -0
- aprict/cuda/structs/cu/FORBILD_Ellipsoid_free.cu +71 -0
- aprict/cuda/structs/cu/FORBILD_Ellipt_Cyl.cu +73 -0
- aprict/cuda/structs/cu/FORBILD_Ellipt_Cyl_x.cu +53 -0
- aprict/cuda/structs/cu/FORBILD_Ellipt_Cyl_y.cu +53 -0
- aprict/cuda/structs/cu/FORBILD_Ellipt_Cyl_z.cu +53 -0
- aprict/cuda/structs/cu/FORBILD_Shape.cu +665 -0
- aprict/cuda/structs/cu/FORBILD_Sphere.cu +81 -0
- aprict/cuda/structs/cu/__init__.py +15 -0
- aprict/cuda/structs/geometry.py +189 -0
- aprict/cuda/structs/test_subdir/__init__.py +17 -0
- aprict/cuda/structs/test_subdir/test_config.py +36 -0
- aprict/data/.gitignore +4 -0
- aprict/data/FORBILD/abdomen/AbdomenPhantom.pha +168 -0
- aprict/data/FORBILD/abdomen/AbdomenPhantom_fixed.pha +175 -0
- aprict/data/FORBILD/abdomen/TableOfTissues +34 -0
- aprict/data/FORBILD/abdomen/Wirbel.pha +28 -0
- aprict/data/FORBILD/custom_composite/Ribs.pha +223 -0
- aprict/data/FORBILD/custom_composite/Shoulders.pha +28 -0
- aprict/data/FORBILD/custom_composite/TableOfTissues +34 -0
- aprict/data/FORBILD/custom_composite/Vertebra.pha +26 -0
- aprict/data/FORBILD/custom_composite/part_01_hip.pha +248 -0
- aprict/data/FORBILD/custom_composite/part_02_abdomen.pha +168 -0
- aprict/data/FORBILD/custom_composite/part_03_thorax.pha +53 -0
- aprict/data/FORBILD/custom_composite/part_04_head.pha +776 -0
- aprict/data/FORBILD/custom_composite/part_05_jaw.pha +507 -0
- aprict/data/FORBILD/custom_other/rock_canister_01.pha +101500 -0
- aprict/data/FORBILD/custom_other/rock_canister_01_cavities_1e5.pha +10000 -0
- aprict/data/FORBILD/custom_other/unit_Cyl_z.pha +1 -0
- aprict/data/FORBILD/head/HeadPhantom.pha +776 -0
- aprict/data/FORBILD/head/TableOfTissues +34 -0
- aprict/data/FORBILD/hip/HipPhantom.pha +248 -0
- aprict/data/FORBILD/jaw/JawPhantom.pha +502 -0
- aprict/data/FORBILD/lungs/LungPhantom3Generations.pha +590 -0
- aprict/data/FORBILD/thorax/Ribs.pha +223 -0
- aprict/data/FORBILD/thorax/Shoulders.pha +28 -0
- aprict/data/FORBILD/thorax/TableOfTissues +34 -0
- aprict/data/FORBILD/thorax/ThoraxPhantom.pha +53 -0
- aprict/data/FORBILD/thorax/Vertebra.pha +26 -0
- aprict/data/README.txt +5 -0
- aprict/data/cusrc/CB_backproject.cu +833 -0
- aprict/data/cusrc/CB_backproject_sharedmem.cu +383 -0
- aprict/data/cusrc/CB_project_sharedmem.cu +324 -0
- aprict/data/cusrc/CB_project_texture_chunked.cu +616 -0
- aprict/data/cusrc/FORBILD_volumes.h +2081 -0
- aprict/data/cusrc/base.h +227 -0
- aprict/data/cusrc/config_cb_backproject.h +22 -0
- aprict/data/cusrc/config_cb_project.h +7 -0
- aprict/data/cusrc/config_cb_project_FORBILD.h +7 -0
- aprict/data/cusrc/geometry.h +93 -0
- aprict/data/cusrc/get_bboxes_FORBILD.cu +21 -0
- aprict/data/cusrc/ramlak_convolve.cu +102 -0
- aprict/data/cusrc/sample_FORBILD_volumes.cu +123 -0
- aprict/data/cusrc/test_kernel.cu +59 -0
- aprict/data/cusrc/test_subdir/test_config.h +5 -0
- aprict/data/cusrc/texture_operations.cu +344 -0
- aprict/examples/composite_human_sirt.py +418 -0
- aprict/examples/fan_beam_sirt.py +263 -0
- aprict/examples/helical_sirt.py +268 -0
- aprict/examples/lungs_sirt.py +315 -0
- aprict/examples/trajtest_A_sirt.py +270 -0
- aprict/examples/triangle_exp_fb.py +468 -0
- aprict/gbc/__init__.py +19 -0
- aprict/gbc/filters.py +558 -0
- aprict/gbc/weightinteg.py +174 -0
- aprict/image_view.py +165 -0
- aprict/iterators/__init__.py +19 -0
- aprict/iterators/landweber_vram.py +265 -0
- aprict/iterators/sirt_vram.py +157 -0
- aprict/lib/__init__.py +27 -0
- aprict/lib/argparse_tools.py +221 -0
- aprict/lib/bboxes_FORBILD.py +97 -0
- aprict/lib/click_tools.py +214 -0
- aprict/lib/empty_context_manager.py +26 -0
- aprict/lib/gpu_tools.py +248 -0
- aprict/lib/import_tools.py +32 -0
- aprict/lib/lds.py +495 -0
- aprict/lib/ne_tools.py +234 -0
- aprict/lib/ng_tools.py +162 -0
- aprict/lib/np_tools.py +29 -0
- aprict/lib/process_pha_file.py +388 -0
- aprict/lib/sample_FORBILD.py +170 -0
- aprict/lib/texture_tools/__init__.py +19 -0
- aprict/lib/texture_tools/operations.py +500 -0
- aprict/lib/texture_tools/texture.py +331 -0
- aprict/liveplot.py +221 -0
- aprict/logtools/__init__.py +20 -0
- aprict/logtools/config.py +173 -0
- aprict/logtools/pbar.py +182 -0
- aprict/logtools/pbar_tqdm.py +100 -0
- aprict/logtools/rich_custombar.py +183 -0
- aprict/phantoms/FORBILD_phantoms.py +999 -0
- aprict/phantoms/__init__.py +24 -0
- aprict/ramp_kernels.py +98 -0
- aprict/scripts/cli.py +121 -0
- aprict/scripts/make_geometry_cone_cyl.py +305 -0
- aprict/scripts/make_geometry_fan_circ.py +270 -0
- aprict/scripts/neuroglance.py +77 -0
- aprict/scripts/project_cbfp.py +493 -0
- aprict/scripts/recon_cbfp_cyl_fbp.py +894 -0
- aprict/scripts/recon_cbfp_cyl_gbc.py +954 -0
- aprict/scripts/recon_cbfp_landweber.py +577 -0
- aprict/tests/__init__.py +16 -0
- aprict/tests/cuda_kernels/__init__.py +16 -0
- aprict/tests/cuda_kernels/test_backproject_cb.py +552 -0
- aprict/tests/cuda_kernels/test_cusrc/__init__.py +16 -0
- aprict/tests/cuda_kernels/test_kernel_structs.py +163 -0
- aprict/tests/cuda_kernels/test_project_cb.py +662 -0
- aprict/tests/cuda_kernels/test_project_cb_FORBILD_phantoms.py +205 -0
- aprict/tests/cuda_kernels/test_project_cb_FORBILD_shapes.py +877 -0
- aprict/tests/test_FORBILD_lungs_construction.py +64 -0
- aprict/tests/test_volume.py +70 -0
- aprict/version.py +19 -0
- aprict/volume.py +811 -0
- aprict-0.0.14.dist-info/METADATA +323 -0
- aprict-0.0.14.dist-info/RECORD +150 -0
- aprict-0.0.14.dist-info/WHEEL +5 -0
- aprict-0.0.14.dist-info/entry_points.txt +9 -0
- aprict-0.0.14.dist-info/licenses/LICENSE.txt +14 -0
- aprict-0.0.14.dist-info/licenses/LICENSE_GPLv3.txt +674 -0
- 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)
|