aprict 0.0.23__tar.gz → 0.0.24.dev1__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.
Files changed (157) hide show
  1. {aprict-0.0.23/src/aprict.egg-info → aprict-0.0.24.dev1}/PKG-INFO +19 -12
  2. {aprict-0.0.23 → aprict-0.0.24.dev1}/README.md +18 -11
  3. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cb/flatpanel.py +6 -0
  4. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/lib/ne_tools.py +4 -1
  5. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/logtools/pbar.py +5 -0
  6. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/scripts/recon_cbfp_cyl_fbp.py +7 -6
  7. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/scripts/recon_cbfp_cyl_gbc.py +72 -25
  8. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/scripts/recon_cbfp_landweber.py +1 -1
  9. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/version.py +1 -1
  10. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/volume.py +15 -2
  11. {aprict-0.0.23 → aprict-0.0.24.dev1/src/aprict.egg-info}/PKG-INFO +19 -12
  12. {aprict-0.0.23 → aprict-0.0.24.dev1}/LICENSE.txt +0 -0
  13. {aprict-0.0.23 → aprict-0.0.24.dev1}/LICENSE_GPLv3.txt +0 -0
  14. {aprict-0.0.23 → aprict-0.0.24.dev1}/MANIFEST.in +0 -0
  15. {aprict-0.0.23 → aprict-0.0.24.dev1}/pyproject.toml +0 -0
  16. {aprict-0.0.23 → aprict-0.0.24.dev1}/setup.cfg +0 -0
  17. {aprict-0.0.23 → aprict-0.0.24.dev1}/setup.py +0 -0
  18. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/__init__.py +0 -0
  19. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cb/__init__.py +0 -0
  20. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cb/_unused_old_fbp.py +0 -0
  21. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cb/noop_filter.py +0 -0
  22. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cb/ramp_filter.py +0 -0
  23. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cb/ramp_filter_cpu.py +0 -0
  24. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/__init__.py +0 -0
  25. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/_generate_cusrc.py +0 -0
  26. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/dtype_cacher.py +0 -0
  27. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/header_injection.py +0 -0
  28. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/kern_structs.py +0 -0
  29. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/ptx_cacher.py +0 -0
  30. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/FORBILD_volumes.py +0 -0
  31. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/__init__.py +0 -0
  32. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/base.py +0 -0
  33. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/config_cb_backproject.py +0 -0
  34. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/config_cb_project.py +0 -0
  35. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/config_cb_project_FORBILD.py +0 -0
  36. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/cu/FORBILD_Box.cu +0 -0
  37. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/cu/FORBILD_ClipAxisSpec.cu +0 -0
  38. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/cu/FORBILD_Cone.cu +0 -0
  39. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/cu/FORBILD_Cone_x.cu +0 -0
  40. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/cu/FORBILD_Cone_y.cu +0 -0
  41. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/cu/FORBILD_Cone_z.cu +0 -0
  42. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/cu/FORBILD_Cylinder.cu +0 -0
  43. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/cu/FORBILD_Cylinder_x.cu +0 -0
  44. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/cu/FORBILD_Cylinder_y.cu +0 -0
  45. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/cu/FORBILD_Cylinder_z.cu +0 -0
  46. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/cu/FORBILD_Ellipsoid.cu +0 -0
  47. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/cu/FORBILD_Ellipsoid_free.cu +0 -0
  48. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/cu/FORBILD_Ellipt_Cyl.cu +0 -0
  49. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/cu/FORBILD_Ellipt_Cyl_x.cu +0 -0
  50. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/cu/FORBILD_Ellipt_Cyl_y.cu +0 -0
  51. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/cu/FORBILD_Ellipt_Cyl_z.cu +0 -0
  52. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/cu/FORBILD_Shape.cu +0 -0
  53. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/cu/FORBILD_Sphere.cu +0 -0
  54. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/cu/__init__.py +0 -0
  55. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/geometry.py +0 -0
  56. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/test_subdir/__init__.py +0 -0
  57. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/cuda/structs/test_subdir/test_config.py +0 -0
  58. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/.gitignore +0 -0
  59. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/abdomen/AbdomenPhantom.pha +0 -0
  60. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/abdomen/AbdomenPhantom_fixed.pha +0 -0
  61. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/abdomen/TableOfTissues +0 -0
  62. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/abdomen/Wirbel.pha +0 -0
  63. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/custom_composite/Ribs.pha +0 -0
  64. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/custom_composite/Shoulders.pha +0 -0
  65. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/custom_composite/TableOfTissues +0 -0
  66. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/custom_composite/Vertebra.pha +0 -0
  67. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/custom_composite/part_01_hip.pha +0 -0
  68. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/custom_composite/part_02_abdomen.pha +0 -0
  69. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/custom_composite/part_03_thorax.pha +0 -0
  70. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/custom_composite/part_04_head.pha +0 -0
  71. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/custom_composite/part_05_jaw.pha +0 -0
  72. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/custom_other/rock_canister_01.pha +0 -0
  73. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/custom_other/rock_canister_01_cavities_1e5.pha +0 -0
  74. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/custom_other/unit_Cyl_z.pha +0 -0
  75. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/head/HeadPhantom.pha +0 -0
  76. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/head/TableOfTissues +0 -0
  77. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/hip/HipPhantom.pha +0 -0
  78. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/jaw/JawPhantom.pha +0 -0
  79. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/lungs/LungPhantom3Generations.pha +0 -0
  80. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/thorax/Ribs.pha +0 -0
  81. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/thorax/Shoulders.pha +0 -0
  82. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/thorax/TableOfTissues +0 -0
  83. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/thorax/ThoraxPhantom.pha +0 -0
  84. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/FORBILD/thorax/Vertebra.pha +0 -0
  85. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/README.txt +0 -0
  86. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/cusrc/CB_backproject.cu +0 -0
  87. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/cusrc/CB_backproject_sharedmem.cu +0 -0
  88. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/cusrc/CB_project_sharedmem.cu +0 -0
  89. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/cusrc/CB_project_texture_chunked.cu +0 -0
  90. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/cusrc/FORBILD_volumes.h +0 -0
  91. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/cusrc/base.h +0 -0
  92. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/cusrc/config_cb_backproject.h +0 -0
  93. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/cusrc/config_cb_project.h +0 -0
  94. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/cusrc/config_cb_project_FORBILD.h +0 -0
  95. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/cusrc/geometry.h +0 -0
  96. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/cusrc/get_bboxes_FORBILD.cu +0 -0
  97. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/cusrc/ramlak_convolve.cu +0 -0
  98. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/cusrc/sample_FORBILD_volumes.cu +0 -0
  99. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/cusrc/test_kernel.cu +0 -0
  100. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/cusrc/test_subdir/test_config.h +0 -0
  101. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/data/cusrc/texture_operations.cu +0 -0
  102. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/examples/composite_human_sirt.py +0 -0
  103. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/examples/fan_beam_sirt.py +0 -0
  104. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/examples/helical_sirt.py +0 -0
  105. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/examples/lungs_sirt.py +0 -0
  106. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/examples/trajtest_A_sirt.py +0 -0
  107. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/examples/triangle_exp_fb.py +0 -0
  108. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/gbc/__init__.py +0 -0
  109. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/gbc/filters.py +0 -0
  110. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/gbc/weightinteg.py +0 -0
  111. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/image_view.py +0 -0
  112. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/iterators/__init__.py +0 -0
  113. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/iterators/landweber_vram.py +0 -0
  114. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/iterators/sirt_vram.py +0 -0
  115. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/lib/__init__.py +0 -0
  116. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/lib/argparse_tools.py +0 -0
  117. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/lib/bboxes_FORBILD.py +0 -0
  118. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/lib/click_tools.py +0 -0
  119. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/lib/empty_context_manager.py +0 -0
  120. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/lib/gpu_tools.py +0 -0
  121. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/lib/import_tools.py +0 -0
  122. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/lib/lds.py +0 -0
  123. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/lib/ng_tools.py +0 -0
  124. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/lib/np_tools.py +0 -0
  125. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/lib/process_pha_file.py +0 -0
  126. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/lib/sample_FORBILD.py +0 -0
  127. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/lib/texture_tools/__init__.py +0 -0
  128. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/lib/texture_tools/operations.py +0 -0
  129. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/lib/texture_tools/texture.py +0 -0
  130. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/liveplot.py +0 -0
  131. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/logtools/__init__.py +0 -0
  132. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/logtools/config.py +0 -0
  133. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/logtools/pbar_tqdm.py +0 -0
  134. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/logtools/rich_custombar.py +0 -0
  135. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/phantoms/FORBILD_phantoms.py +0 -0
  136. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/phantoms/__init__.py +0 -0
  137. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/ramp_kernels.py +0 -0
  138. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/scripts/cli.py +0 -0
  139. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/scripts/make_geometry_cone_cyl.py +0 -0
  140. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/scripts/make_geometry_fan_circ.py +0 -0
  141. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/scripts/neuroglance.py +0 -0
  142. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/scripts/project_cbfp.py +0 -0
  143. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/tests/__init__.py +0 -0
  144. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/tests/cuda_kernels/__init__.py +0 -0
  145. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/tests/cuda_kernels/test_backproject_cb.py +0 -0
  146. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/tests/cuda_kernels/test_cusrc/__init__.py +0 -0
  147. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/tests/cuda_kernels/test_kernel_structs.py +0 -0
  148. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/tests/cuda_kernels/test_project_cb.py +0 -0
  149. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/tests/cuda_kernels/test_project_cb_FORBILD_phantoms.py +0 -0
  150. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/tests/cuda_kernels/test_project_cb_FORBILD_shapes.py +0 -0
  151. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/tests/test_FORBILD_lungs_construction.py +0 -0
  152. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict/tests/test_volume.py +0 -0
  153. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict.egg-info/SOURCES.txt +0 -0
  154. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict.egg-info/dependency_links.txt +0 -0
  155. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict.egg-info/entry_points.txt +0 -0
  156. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict.egg-info/requires.txt +0 -0
  157. {aprict-0.0.23 → aprict-0.0.24.dev1}/src/aprict.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aprict
3
- Version: 0.0.23
3
+ Version: 0.0.24.dev1
4
4
  Summary: Tools to simulate and reconstruct XCT transmission data.
5
5
  Author: Murdock Grewar
6
6
  Author-email: Murdock Grewar <murdock.grewar@anu.edu.au>
@@ -36,6 +36,10 @@ Requires-Dist: neuroglancer>=2.41.0; extra == "gui"
36
36
  Dynamic: author
37
37
  Dynamic: license-file
38
38
 
39
+ [![Static Badge](https://img.shields.io/badge/ORCiD-0000--0002--0015--8284-green?logo=orcid)](https://orcid.org/0000-0002-0015-8284)
40
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.23632625.svg)](https://doi.org/10.5281/zenodo.23632625)
41
+ ![PyPI Version](https://img.shields.io/pypi/v/aprict)
42
+ [![Project Status: WIP – Initial development is in progress, but there has not yet been a stable, usable release suitable for the public.](https://www.repostatus.org/badges/latest/wip.svg)](https://www.repostatus.org/#wip)
39
43
  <details open><summary><h1>About</h1></summary>
40
44
 
41
45
  Description
@@ -71,8 +75,7 @@ Known limitations
71
75
  * Volume size is limited by CUDA texture limit. For example, a `(2400,2400,4800)` volume can be reconstructed, but not a `(30000,30000,1)` volume, due to a volume of this size not fitting within a single CUDA texture
72
76
  * The FORBILD shape `Tetrahedron` is not yet implemented, and no primitive shape is permitted to have more than 3 clipping planes applied, due to internal limitations. All other FORBILD phantoms should be supported.
73
77
  * Only one GPU is utilised by this module, at the present time. There is no defined behaviour for which GPU will be chosen.
74
- * Not fully optimised: among other issues,
75
- * the GBC reconstruction script assumes that the whole volume (or more) can fit in RAM. This limitation may be lifted in the future. (Note: a present workaround is to create a large swapfile on disk, since swap space is treated as RAM when the physical RAM is exhausted.)
78
+ * Not fully optimised
76
79
  * CPU and GPU work not completely asynchronous: due to unresolved bugs, various asynchronous GPU operations have been disabled. This may not have much impact on large reconstructions, but could result in poor GPU utilisation for smaller reconstructions.
77
80
  * No smart batching of (back)projections: smarter code would analyse the geometry of projections, and batch together (back)projections that involve similar regions of the volume. Currently, the code does not do any kind of clever batching like this, and so the (back)projection code is not as performant as it could be.
78
81
 
@@ -99,7 +102,7 @@ You can install `aprict` like you would any python package, using `pip install`.
99
102
  Example installation using `uv`:
100
103
  ```bash
101
104
  $ uv venv -p 3.14
102
- $ uv pip install aprict[gui]==0.0.19
105
+ $ uv pip install aprict[gui]==0.0.24
103
106
  $ source .venv/bin/activate
104
107
  ```
105
108
  You should now have several executables available on `$PATH`. Try `aprict-cli --help` to see the polished commandline interface.
@@ -118,11 +121,11 @@ Activate the environment:
118
121
  ```bash
119
122
  source .venv/bin/activate
120
123
  ```
121
- Now, try the shell command `aprict-cli --help`. Here is the output as at `v0.0.19`:
124
+ Now, try the shell command `aprict-cli --help`. Here is the output as at `v0.0.24`:
122
125
  ```
123
126
  Usage: aprict-cli [OPTIONS] COMMAND [ARGS]...
124
127
 
125
- Entry point for aprict CLI.
128
+ Entry point for CLI interface to aprict version 0.0.24
126
129
 
127
130
  Options:
128
131
  --version Show the version and exit.
@@ -170,8 +173,8 @@ aprict-cli project cbfp \
170
173
  --output projs \
171
174
  --plot-mode PYQTGRAPH
172
175
  ````
173
- (Time on my machine: ~2 minutes, 55 seconds)
174
- The option `--plot-mode PYQTGRAPH` will display a plot window of the projection data after it is created. (This will not be available if the module was not installed with the `[gui]` option.)
176
+ (Time on my machine: ~2 minutes, 56 seconds)
177
+ The options `--ssu 3 --ssv 3` indicate that the line attenuation for each detector pixel is to be calculated as the average of a 3-by-3 grid of exact line integrals. This kind of improved accuracy is necessary for some phantoms, including this one, if using a large detector pixel size. The option `--plot-mode PYQTGRAPH` will display a plot window of the projection data after it is created. (This will not be available if the module was not installed with the `[gui]` option.)
175
178
 
176
179
  Now, let's reconstruct with three different algorithms:
177
180
  1. Global Backprojection-Convolution (GBC)
@@ -186,10 +189,14 @@ aprict-cli recon gbc-cone-cyl \
186
189
  --voxwid 0.5 \
187
190
  --volshape '(525,525,525)' \
188
191
  --alg GREWAR \
192
+ --f1 1.2 \
193
+ --f2 6 \
194
+ --n 9 \
195
+ --eps 1e-9 \
189
196
  --output recon_gbc \
190
197
  --plot-mode PYQTGRAPH
191
198
  ```
192
- (Time on my machine: ~37 seconds)
199
+ (Time on my machine: ~39 seconds)
193
200
 
194
201
  To perform an FBP reconstruction, we do:
195
202
  ```bash
@@ -202,7 +209,7 @@ aprict-cli recon fbp-cone-cyl \
202
209
  --output recon_fbp \
203
210
  --plot-mode PYQTGRAPH
204
211
  ```
205
- (Time on my machine: ~12 seconds)
212
+ (Time on my machine: ~19 seconds)
206
213
 
207
214
  To perform an FBP-VM reconstruction, we change `--alg` to `NOOGREWAR`:
208
215
  ```bash
@@ -215,7 +222,7 @@ aprict-cli recon fbp-cone-cyl \
215
222
  --output recon_fbp-vw \
216
223
  --plot-mode PYQTGRAPH
217
224
  ```
218
- (Time on my machine: ~22 seconds)
225
+ (Time on my machine: ~26 seconds)
219
226
 
220
227
 
221
228
  </details>
@@ -253,7 +260,7 @@ aprict-cli project cbfp \
253
260
  --output projs \
254
261
  --plot-mode PYQTGRAPH
255
262
  ````
256
- (Time on my machine: ~1 minute, 46 seconds)
263
+ (Time on my machine: ~1 minute, 48 seconds)
257
264
  The option `--plot-mode PYQTGRAPH` will display a plot window of the projection data (a sinogram) after it is created. (This will not be available if the module was not installed with the `[gui]` option.)
258
265
 
259
266
  You will find a copy of the `ROCK_CAN` phantom in the output directory `projs`, beside the projection data. The phantom is always copied to the output directory, to ensure a good record of the inputs to the simulation.
@@ -1,3 +1,7 @@
1
+ [![Static Badge](https://img.shields.io/badge/ORCiD-0000--0002--0015--8284-green?logo=orcid)](https://orcid.org/0000-0002-0015-8284)
2
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.23632625.svg)](https://doi.org/10.5281/zenodo.23632625)
3
+ ![PyPI Version](https://img.shields.io/pypi/v/aprict)
4
+ [![Project Status: WIP – Initial development is in progress, but there has not yet been a stable, usable release suitable for the public.](https://www.repostatus.org/badges/latest/wip.svg)](https://www.repostatus.org/#wip)
1
5
  <details open><summary><h1>About</h1></summary>
2
6
 
3
7
  Description
@@ -33,8 +37,7 @@ Known limitations
33
37
  * Volume size is limited by CUDA texture limit. For example, a `(2400,2400,4800)` volume can be reconstructed, but not a `(30000,30000,1)` volume, due to a volume of this size not fitting within a single CUDA texture
34
38
  * The FORBILD shape `Tetrahedron` is not yet implemented, and no primitive shape is permitted to have more than 3 clipping planes applied, due to internal limitations. All other FORBILD phantoms should be supported.
35
39
  * Only one GPU is utilised by this module, at the present time. There is no defined behaviour for which GPU will be chosen.
36
- * Not fully optimised: among other issues,
37
- * the GBC reconstruction script assumes that the whole volume (or more) can fit in RAM. This limitation may be lifted in the future. (Note: a present workaround is to create a large swapfile on disk, since swap space is treated as RAM when the physical RAM is exhausted.)
40
+ * Not fully optimised
38
41
  * CPU and GPU work not completely asynchronous: due to unresolved bugs, various asynchronous GPU operations have been disabled. This may not have much impact on large reconstructions, but could result in poor GPU utilisation for smaller reconstructions.
39
42
  * No smart batching of (back)projections: smarter code would analyse the geometry of projections, and batch together (back)projections that involve similar regions of the volume. Currently, the code does not do any kind of clever batching like this, and so the (back)projection code is not as performant as it could be.
40
43
 
@@ -61,7 +64,7 @@ You can install `aprict` like you would any python package, using `pip install`.
61
64
  Example installation using `uv`:
62
65
  ```bash
63
66
  $ uv venv -p 3.14
64
- $ uv pip install aprict[gui]==0.0.19
67
+ $ uv pip install aprict[gui]==0.0.24
65
68
  $ source .venv/bin/activate
66
69
  ```
67
70
  You should now have several executables available on `$PATH`. Try `aprict-cli --help` to see the polished commandline interface.
@@ -80,11 +83,11 @@ Activate the environment:
80
83
  ```bash
81
84
  source .venv/bin/activate
82
85
  ```
83
- Now, try the shell command `aprict-cli --help`. Here is the output as at `v0.0.19`:
86
+ Now, try the shell command `aprict-cli --help`. Here is the output as at `v0.0.24`:
84
87
  ```
85
88
  Usage: aprict-cli [OPTIONS] COMMAND [ARGS]...
86
89
 
87
- Entry point for aprict CLI.
90
+ Entry point for CLI interface to aprict version 0.0.24
88
91
 
89
92
  Options:
90
93
  --version Show the version and exit.
@@ -132,8 +135,8 @@ aprict-cli project cbfp \
132
135
  --output projs \
133
136
  --plot-mode PYQTGRAPH
134
137
  ````
135
- (Time on my machine: ~2 minutes, 55 seconds)
136
- The option `--plot-mode PYQTGRAPH` will display a plot window of the projection data after it is created. (This will not be available if the module was not installed with the `[gui]` option.)
138
+ (Time on my machine: ~2 minutes, 56 seconds)
139
+ The options `--ssu 3 --ssv 3` indicate that the line attenuation for each detector pixel is to be calculated as the average of a 3-by-3 grid of exact line integrals. This kind of improved accuracy is necessary for some phantoms, including this one, if using a large detector pixel size. The option `--plot-mode PYQTGRAPH` will display a plot window of the projection data after it is created. (This will not be available if the module was not installed with the `[gui]` option.)
137
140
 
138
141
  Now, let's reconstruct with three different algorithms:
139
142
  1. Global Backprojection-Convolution (GBC)
@@ -148,10 +151,14 @@ aprict-cli recon gbc-cone-cyl \
148
151
  --voxwid 0.5 \
149
152
  --volshape '(525,525,525)' \
150
153
  --alg GREWAR \
154
+ --f1 1.2 \
155
+ --f2 6 \
156
+ --n 9 \
157
+ --eps 1e-9 \
151
158
  --output recon_gbc \
152
159
  --plot-mode PYQTGRAPH
153
160
  ```
154
- (Time on my machine: ~37 seconds)
161
+ (Time on my machine: ~39 seconds)
155
162
 
156
163
  To perform an FBP reconstruction, we do:
157
164
  ```bash
@@ -164,7 +171,7 @@ aprict-cli recon fbp-cone-cyl \
164
171
  --output recon_fbp \
165
172
  --plot-mode PYQTGRAPH
166
173
  ```
167
- (Time on my machine: ~12 seconds)
174
+ (Time on my machine: ~19 seconds)
168
175
 
169
176
  To perform an FBP-VM reconstruction, we change `--alg` to `NOOGREWAR`:
170
177
  ```bash
@@ -177,7 +184,7 @@ aprict-cli recon fbp-cone-cyl \
177
184
  --output recon_fbp-vw \
178
185
  --plot-mode PYQTGRAPH
179
186
  ```
180
- (Time on my machine: ~22 seconds)
187
+ (Time on my machine: ~26 seconds)
181
188
 
182
189
 
183
190
  </details>
@@ -215,7 +222,7 @@ aprict-cli project cbfp \
215
222
  --output projs \
216
223
  --plot-mode PYQTGRAPH
217
224
  ````
218
- (Time on my machine: ~1 minute, 46 seconds)
225
+ (Time on my machine: ~1 minute, 48 seconds)
219
226
  The option `--plot-mode PYQTGRAPH` will display a plot window of the projection data (a sinogram) after it is created. (This will not be available if the module was not installed with the `[gui]` option.)
220
227
 
221
228
  You will find a copy of the `ROCK_CAN` phantom in the output directory `projs`, beside the projection data. The phantom is always copied to the output directory, to ensure a good record of the inputs to the simulation.
@@ -33,6 +33,7 @@ import numpy.typing as npt # ruff: ignore[unused-import]
33
33
  from .. import logtools
34
34
  from ..cuda import header_injection, structs
35
35
  from ..cuda.kern_structs import _np_dtype_to_c_type
36
+ from ..lib import gpu_tools
36
37
  from ..volume import FBVolume, Volume
37
38
 
38
39
  _delay_compile: bool = (
@@ -801,6 +802,11 @@ class ProjectionSet:
801
802
  )
802
803
  return ProjectionSet(self._proj_geom, data=cp.zeros_like(self._data))
803
804
 
805
+ def __del__(self) -> None: # ruff: ignore[undocumented-magic-method]
806
+ # HOTFIX to work around a pinned-memory leak in CuPy
807
+ # Unfortunately, this reduces GPU utilisation.
808
+ gpu_tools.clear_pinned_cache()
809
+
804
810
 
805
811
  class ConfigProject:
806
812
  """Configuration object for projections. Some options will have no effect if a Volume or FBVolume."""
@@ -162,12 +162,15 @@ def downbin( # ruff: ignore[complex-structure]
162
162
  return xnew
163
163
 
164
164
 
165
- def save(path: pathlib.Path, arr: np.ndarray) -> None:
165
+ def save(path: pathlib.Path, arr: np.ndarray, flush: bool = True) -> None:
166
166
  """Save an array to a path in a faster manner than np.save."""
167
167
  mm: np.memmap = np.lib.format.open_memmap(
168
168
  path, shape=arr.shape, dtype=arr.dtype, mode="w+"
169
169
  )
170
170
  ne.evaluate("x", out=mm, local_dict={"x": arr})
171
+ if flush:
172
+ # Write changes to disk now.
173
+ mm.flush()
171
174
 
172
175
 
173
176
  class NETHREADS(enum.Enum):
@@ -140,6 +140,11 @@ class ProgressBar:
140
140
  speed_estimate_period=86400, # period in seconds
141
141
  )
142
142
 
143
+ @property
144
+ def maxval(self) -> int | float:
145
+ """Maximum value of the progress bar."""
146
+ return self._maxval
147
+
143
148
  def __enter__(self) -> ProgressBar: # ruff: ignore[undocumented-magic-method]
144
149
  if self._enable:
145
150
  self._cm.__enter__()
@@ -872,7 +872,7 @@ def main_from_args(args: types.SimpleNamespace) -> None: # ruff: ignore[complex
872
872
  if logger is not None:
873
873
  msg = f"Saving full volume to '{savepath}'..."
874
874
  logger.debug(msg)
875
- lib.ne_tools.save(savepath, x)
875
+ lib.ne_tools.save(savepath, x, flush=True)
876
876
  if logger is not None:
877
877
  msg = "Full volume now saved to disk."
878
878
  logger.debug(msg)
@@ -1139,16 +1139,17 @@ def main_from_args(args: types.SimpleNamespace) -> None: # ruff: ignore[complex
1139
1139
  logger.debug(msg)
1140
1140
  if vol is not None:
1141
1141
  # Not efficient. Can't copy from CUDAArray directly to the chunk because it's not C-contiguous.
1142
- ans = vol.as_numpy()
1143
- lib.ne_tools.fastcopy(src=ans, dst=vol_np[..., sl_vol])
1144
- del ans # allow the memory to be freed
1145
- lib.gpu_tools.clear_pinned_cache()
1142
+ vol.as_numpy(
1143
+ out=vol_np[..., sl_vol], allow_indirect_copy=True
1144
+ )
1145
+ del vol
1146
+ lib.gpu_tools.clear_cache()
1146
1147
  else:
1147
1148
  msg = "No need to transfer volume chunk from GPU. No work performed."
1148
1149
  logger.debug(msg)
1150
+ del vol
1149
1151
 
1150
1152
  # Free some memory
1151
- del vol
1152
1153
  lib.gpu_tools.clear_cache()
1153
1154
  lib.gpu_tools.clear_pinned_cache()
1154
1155
 
@@ -294,6 +294,12 @@ _progdesc = "Perform an FBP reconstruction from cylindrical flat-panel cone-beam
294
294
  default=8080,
295
295
  help="Port to use for serving things via a web interface, if applicable.",
296
296
  ),
297
+ ce.option(
298
+ "--memmap-vols",
299
+ type=lib.click_tools.BoolArgType(),
300
+ default=True,
301
+ help="Memory-map volumes, rather than keeping them in RAM.",
302
+ ),
297
303
  )
298
304
  @ce.option_group(
299
305
  "resource options",
@@ -317,6 +323,10 @@ def validate_args(args: types.SimpleNamespace) -> None:
317
323
  msg = f"Output path '{args.output!s}' already exists."
318
324
  raise ce.UsageError(msg)
319
325
 
326
+ if args.output is None and args.memmap_vols:
327
+ msg = "Cannot use --memmap-vols True while --output is not specified."
328
+ raise ce.UsageError(msg)
329
+
320
330
  # If outputting intermediates, then the user must also specify the --output directory
321
331
  if args.output_intermediates and not args.output:
322
332
  msg = "Cannot output intermediate tomograms when no output directory was specified. Specify an output directory with --output path/to/new/dir"
@@ -903,9 +913,20 @@ def main_from_args(args: types.SimpleNamespace) -> None: # ruff: ignore[complex
903
913
 
904
914
  msg = "Allocating and zeroing the backprojection arrays..."
905
915
  logger.info(msg)
906
- # Put the z axis first, so that we can slice it in Z and have a C-contiguous array. This is necessary to copy directly from a cupy array to a numpy array.
907
- vol_np = np.empty(padded_volshape, dtype=vol_dtype)
908
- volmini_np = np.empty(padded_volshape_mini, dtype=vol_dtype)
916
+ if args.memmap_vols:
917
+ assert path_output is not None # ensured by validate_args(...)
918
+ # These are temporary arrays which may be overwritten during filtration.
919
+ savepath = path_output.joinpath("tmp_backproj" + ".npy")
920
+ vol_np = np.lib.format.open_memmap(
921
+ savepath, shape=padded_volshape, dtype=vol_dtype, mode="w+"
922
+ )
923
+ savepath = path_output.joinpath("tmp_backproj" + "_mini" + ".npy")
924
+ volmini_np = np.lib.format.open_memmap(
925
+ savepath, shape=padded_volshape_mini, dtype=vol_dtype, mode="w+"
926
+ )
927
+ else:
928
+ vol_np = np.empty(padded_volshape, dtype=vol_dtype)
929
+ volmini_np = np.empty(padded_volshape_mini, dtype=vol_dtype)
909
930
  lib.ne_tools.set_array_to_constant_pbar(
910
931
  vol_np,
911
932
  const=0,
@@ -923,11 +944,18 @@ def main_from_args(args: types.SimpleNamespace) -> None: # ruff: ignore[complex
923
944
  pbar_persist=False,
924
945
  )
925
946
 
947
+ # Convert the progress display ta more intuitive set of units using the progratio.
948
+ # The displayed progress will correspond to bytes in the padded backprojection.
949
+ progratio: float = (
950
+ math.prod(padded_volshape)
951
+ * np.dtype(vol_dtype).itemsize
952
+ / bytes_cumsum[-1]
953
+ )
926
954
  curr_slice: slice | None = None
927
955
  logger.info("Beginning reconstruction...")
928
956
  with logtools.ProgressBar(
929
957
  desc="Backproj.:",
930
- maxval=int(bytes_cumsum[-1]),
958
+ maxval=math.ceil(bytes_cumsum[-1] * progratio),
931
959
  logger=logger,
932
960
  persist=True,
933
961
  unit_is_bytes=True,
@@ -1042,7 +1070,8 @@ def main_from_args(args: types.SimpleNamespace) -> None: # ruff: ignore[complex
1042
1070
  prog_evs_bytes.append(
1043
1071
  (
1044
1072
  ev,
1045
- (
1073
+ progratio
1074
+ * (
1046
1075
  (
1047
1076
  (sl.stop - sl.start)
1048
1077
  / tot_num_nonskipped_projs
@@ -1075,8 +1104,6 @@ def main_from_args(args: types.SimpleNamespace) -> None: # ruff: ignore[complex
1075
1104
  if tot_num_nonskipped_projs == 0:
1076
1105
  msg = "No need to transfer volume chunk from GPU. No work performed."
1077
1106
  logger.debug(msg)
1078
- del vol_weightsum
1079
- del minivol_weightsum
1080
1107
  else:
1081
1108
  # Normalise to the correct weighting.
1082
1109
  # This will multiply both a numerator and a divisor by the same amount.
@@ -1120,33 +1147,36 @@ def main_from_args(args: types.SimpleNamespace) -> None: # ruff: ignore[complex
1120
1147
  minivol.divide_softzero(minivol_weightsum, eps=args.eps)
1121
1148
  del vol_weightsum
1122
1149
  del minivol_weightsum
1150
+ lib.gpu_tools.clear_cache()
1151
+ lib.gpu_tools.clear_pinned_cache()
1123
1152
 
1124
1153
  # Save the backprojections into the arrays
1125
1154
  msg = "Transferring backprojected volume chunk from GPU..."
1126
1155
  logger.debug(msg)
1156
+ # Copy minivol.
1157
+ # Not efficient. Can't copy from CUDAArray directly to the chunk because it's not C-contiguous.
1158
+ minivol.as_numpy(
1159
+ out=volmini_np[..., sl_minivol], allow_indirect_copy=True
1160
+ )
1161
+ del minivol
1162
+ lib.gpu_tools.clear_cache()
1163
+ # Copy vol.
1127
1164
  if vol is not None:
1128
1165
  # Not efficient. Can't copy from CUDAArray directly to the chunk because it's not C-contiguous.
1129
- ans = vol.as_numpy()
1130
- lib.ne_tools.fastcopy(src=ans, dst=vol_np[..., sl_vol])
1131
- del ans # allow the memory to be freed
1132
- lib.gpu_tools.clear_pinned_cache()
1133
- # Not efficient. Can't copy from CUDAArray directly to the chunk because it's not C-contiguous.
1134
- ans = minivol.as_numpy()
1135
- lib.ne_tools.fastcopy(src=ans, dst=volmini_np[..., sl_minivol])
1136
- del ans # allow the memory to be freed
1137
- lib.gpu_tools.clear_pinned_cache()
1138
-
1139
- # Free some memory
1140
- del vol, minivol
1141
- lib.gpu_tools.clear_pinned_cache()
1142
- lib.gpu_tools.clear_cache()
1166
+ vol.as_numpy(
1167
+ out=vol_np[..., sl_vol], allow_indirect_copy=True
1168
+ )
1169
+ del vol
1170
+ lib.gpu_tools.clear_cache()
1143
1171
 
1144
- pbar.update_to(int(bytes_cumsum[-1]))
1172
+ pbar.update_to(pbar.maxval)
1145
1173
 
1146
1174
  msg = "Filtering volumes..."
1147
1175
  logger.info(msg)
1148
1176
  with rich_console.status(msg, spinner="dots"):
1149
1177
  # Filter the mini recon first.
1178
+ msg = "Filtering padded minivol..."
1179
+ logger.debug(msg)
1150
1180
  minivol_voxwid = args.voxwid * args.n
1151
1181
  ndarray_container = lib.np_tools.NDArrayContainer(array=volmini_np)
1152
1182
  minivol_padded_filtered_np = gbc.filters.ramp_filter_conebeam(
@@ -1167,16 +1197,20 @@ def main_from_args(args: types.SimpleNamespace) -> None: # ruff: ignore[complex
1167
1197
  ]
1168
1198
  )
1169
1199
  del volmini_np # not going to reuse this, so delete this reference so the filtration can free some memory.
1200
+ msg = "Filtering unpadded minivol..."
1201
+ logger.debug(msg)
1170
1202
  minivol_unpadded_filtered_np = gbc.filters.ramp_filter_conebeam(
1171
1203
  ndarray_container,
1172
1204
  minivol_voxwid,
1173
1205
  2 * vartheta_v,
1174
1206
  theta_soft=args.softspan_v,
1175
1207
  auto_dc_adjust=False,
1176
- allow_overwrite_arr=True, # we're not going to reuse the 'minivol_cp' object after this.
1208
+ allow_overwrite_arr=True, # we're not going to reuse the 'volmini_np' object after this.
1177
1209
  logger=logger,
1178
1210
  copy_to_array=None,
1179
1211
  )
1212
+ msg = "Producing minivol correction array..."
1213
+ logger.debug(msg)
1180
1214
  minivol_correction_np = (
1181
1215
  minivol_padded_filtered_np[
1182
1216
  mvc_padx : (-mvc_padx) or None,
@@ -1192,6 +1226,8 @@ def main_from_args(args: types.SimpleNamespace) -> None: # ruff: ignore[complex
1192
1226
  ndarray_container,
1193
1227
  )
1194
1228
  # Filter the full recon now
1229
+ msg = "Filtering padded vol and adding upscaled minivol correction..."
1230
+ logger.debug(msg)
1195
1231
  ndarray_container = lib.np_tools.NDArrayContainer(array=vol_np)
1196
1232
  vol_voxwid = args.voxwid
1197
1233
  del vol_np # allows memory to be freed, because the gbc.filters.ramp_filter_conebeam is free to overwrite the ndarray_container.array
@@ -1201,7 +1237,7 @@ def main_from_args(args: types.SimpleNamespace) -> None: # ruff: ignore[complex
1201
1237
  2 * vartheta_v,
1202
1238
  theta_soft=args.softspan_v,
1203
1239
  auto_dc_adjust=False,
1204
- allow_overwrite_arr=True,
1240
+ allow_overwrite_arr=True, # not going to need the 'vol_np' object after this.
1205
1241
  logger=logger,
1206
1242
  copy_to_array=None, # Should be a contiguous array. E.g., not an arbitrary view.
1207
1243
  lowres_correction_array=minivol_correction_np,
@@ -1231,6 +1267,8 @@ def main_from_args(args: types.SimpleNamespace) -> None: # ruff: ignore[complex
1231
1267
  f"Estimated DC component to be subtracted: {dc_component:.5g}"
1232
1268
  )
1233
1269
  # Correct the DC component
1270
+ msg = "Adding DC correction..."
1271
+ logger.debug(msg)
1234
1272
  ne.evaluate(
1235
1273
  "v - dcc",
1236
1274
  out=vol_filtered_np,
@@ -1250,6 +1288,7 @@ def main_from_args(args: types.SimpleNamespace) -> None: # ruff: ignore[complex
1250
1288
 
1251
1289
  # Clean up
1252
1290
  lib.gpu_tools.clear_cache()
1291
+ lib.gpu_tools.clear_pinned_cache()
1253
1292
 
1254
1293
  if path_output is not None:
1255
1294
  msg = "Saving volume to disk..."
@@ -1258,9 +1297,17 @@ def main_from_args(args: types.SimpleNamespace) -> None: # ruff: ignore[complex
1258
1297
  x = vol_filtered
1259
1298
  # Save the volume as a .npy file
1260
1299
  tomo_path = path_output.joinpath("recon.npy")
1261
- lib.ne_tools.save(tomo_path, x)
1300
+ lib.ne_tools.save(tomo_path, x, flush=True)
1262
1301
  msg = "Full volume now saved to disk."
1263
1302
  logger.debug(msg)
1303
+ # Now get rid of the temporary files, if applicable
1304
+ if args.memmap_vols:
1305
+ savepath = path_output.joinpath("tmp_backproj" + ".npy")
1306
+ savepath.unlink() # delete file
1307
+ savepath = path_output.joinpath(
1308
+ "tmp_backproj" + "_mini" + ".npy"
1309
+ )
1310
+ savepath.unlink() # delete file
1264
1311
  # Save slices
1265
1312
  for axis, axis_str in enumerate("xyz"):
1266
1313
  msg = f"Saving '{axis_str}' slice..."
@@ -521,7 +521,7 @@ def main() -> None:
521
521
  save_path.joinpath("tomograms") if is_intermediate else save_path
522
522
  )
523
523
  tomo_path.mkdir(exist_ok=True)
524
- lib.ne_tools.save(tomo_path.joinpath(id_str + ".npy"), x)
524
+ lib.ne_tools.save(tomo_path.joinpath(id_str + ".npy"), x, flush=True)
525
525
 
526
526
  # Save midslices from volume as .png files
527
527
  # The method used here can be a bit slow, because I get a full numpy array and process that.
@@ -16,4 +16,4 @@
16
16
  # This file is read from by 'setup.py', from '__init__.py', and also by a git hook which increments the dev number each time a commit is made on the 'dev' branch. There should only be one line in the file which begins with "version".
17
17
  """File which stores the current version number of this module."""
18
18
 
19
- version = "0.0.23"
19
+ version = "0.0.24.dev1"
@@ -193,8 +193,21 @@ class Volume[
193
193
  self._texture, vol._texture, tout=self._texture, eps=eps
194
194
  )
195
195
 
196
- def as_numpy(self, out: np.ndarray | None = None) -> np.ndarray:
196
+ def as_numpy(
197
+ self, out: np.ndarray | None = None, allow_indirect_copy: bool = False
198
+ ) -> np.ndarray:
197
199
  """Copy this volume's data into a numpy array."""
200
+ # Note: the option 'allow_indirect_copy' allows a fast-but-not-fastest copy when the output array is not C-contiguous.
201
+ if out is not None and not out.flags["C_CONTIGUOUS"]:
202
+ # The output volume is not C contiguous. A copy cannot be performed unless
203
+ # allow_indirect_copy=True is supplied.
204
+ if not allow_indirect_copy:
205
+ msg = "The array supplied to the out=... keyword is not C contiguous. The data cannot be copied directly, and indirect copying must be explicitly allowed via allow_indirect_copy=True."
206
+ raise ValueError(msg)
207
+ out_ = self.as_numpy(out=None)
208
+ ne_tools.fastcopy(src=out_, dst=out)
209
+ gpu_tools.clear_pinned_cache()
210
+ return out
198
211
  x = (
199
212
  out
200
213
  if out is not None
@@ -209,7 +222,7 @@ class Volume[
209
222
  def save(self, path: pathlib.Path) -> None:
210
223
  """Save this volume into a numpy array on disk."""
211
224
  x = self.as_numpy()
212
- ne_tools.save(path, x)
225
+ ne_tools.save(path, x, flush=True)
213
226
 
214
227
  def as_cupy(self, out: cp.ndarray | None = None) -> cp.ndarray:
215
228
  """Copy this volume's data into a cupy array."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aprict
3
- Version: 0.0.23
3
+ Version: 0.0.24.dev1
4
4
  Summary: Tools to simulate and reconstruct XCT transmission data.
5
5
  Author: Murdock Grewar
6
6
  Author-email: Murdock Grewar <murdock.grewar@anu.edu.au>
@@ -36,6 +36,10 @@ Requires-Dist: neuroglancer>=2.41.0; extra == "gui"
36
36
  Dynamic: author
37
37
  Dynamic: license-file
38
38
 
39
+ [![Static Badge](https://img.shields.io/badge/ORCiD-0000--0002--0015--8284-green?logo=orcid)](https://orcid.org/0000-0002-0015-8284)
40
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.23632625.svg)](https://doi.org/10.5281/zenodo.23632625)
41
+ ![PyPI Version](https://img.shields.io/pypi/v/aprict)
42
+ [![Project Status: WIP – Initial development is in progress, but there has not yet been a stable, usable release suitable for the public.](https://www.repostatus.org/badges/latest/wip.svg)](https://www.repostatus.org/#wip)
39
43
  <details open><summary><h1>About</h1></summary>
40
44
 
41
45
  Description
@@ -71,8 +75,7 @@ Known limitations
71
75
  * Volume size is limited by CUDA texture limit. For example, a `(2400,2400,4800)` volume can be reconstructed, but not a `(30000,30000,1)` volume, due to a volume of this size not fitting within a single CUDA texture
72
76
  * The FORBILD shape `Tetrahedron` is not yet implemented, and no primitive shape is permitted to have more than 3 clipping planes applied, due to internal limitations. All other FORBILD phantoms should be supported.
73
77
  * Only one GPU is utilised by this module, at the present time. There is no defined behaviour for which GPU will be chosen.
74
- * Not fully optimised: among other issues,
75
- * the GBC reconstruction script assumes that the whole volume (or more) can fit in RAM. This limitation may be lifted in the future. (Note: a present workaround is to create a large swapfile on disk, since swap space is treated as RAM when the physical RAM is exhausted.)
78
+ * Not fully optimised
76
79
  * CPU and GPU work not completely asynchronous: due to unresolved bugs, various asynchronous GPU operations have been disabled. This may not have much impact on large reconstructions, but could result in poor GPU utilisation for smaller reconstructions.
77
80
  * No smart batching of (back)projections: smarter code would analyse the geometry of projections, and batch together (back)projections that involve similar regions of the volume. Currently, the code does not do any kind of clever batching like this, and so the (back)projection code is not as performant as it could be.
78
81
 
@@ -99,7 +102,7 @@ You can install `aprict` like you would any python package, using `pip install`.
99
102
  Example installation using `uv`:
100
103
  ```bash
101
104
  $ uv venv -p 3.14
102
- $ uv pip install aprict[gui]==0.0.19
105
+ $ uv pip install aprict[gui]==0.0.24
103
106
  $ source .venv/bin/activate
104
107
  ```
105
108
  You should now have several executables available on `$PATH`. Try `aprict-cli --help` to see the polished commandline interface.
@@ -118,11 +121,11 @@ Activate the environment:
118
121
  ```bash
119
122
  source .venv/bin/activate
120
123
  ```
121
- Now, try the shell command `aprict-cli --help`. Here is the output as at `v0.0.19`:
124
+ Now, try the shell command `aprict-cli --help`. Here is the output as at `v0.0.24`:
122
125
  ```
123
126
  Usage: aprict-cli [OPTIONS] COMMAND [ARGS]...
124
127
 
125
- Entry point for aprict CLI.
128
+ Entry point for CLI interface to aprict version 0.0.24
126
129
 
127
130
  Options:
128
131
  --version Show the version and exit.
@@ -170,8 +173,8 @@ aprict-cli project cbfp \
170
173
  --output projs \
171
174
  --plot-mode PYQTGRAPH
172
175
  ````
173
- (Time on my machine: ~2 minutes, 55 seconds)
174
- The option `--plot-mode PYQTGRAPH` will display a plot window of the projection data after it is created. (This will not be available if the module was not installed with the `[gui]` option.)
176
+ (Time on my machine: ~2 minutes, 56 seconds)
177
+ The options `--ssu 3 --ssv 3` indicate that the line attenuation for each detector pixel is to be calculated as the average of a 3-by-3 grid of exact line integrals. This kind of improved accuracy is necessary for some phantoms, including this one, if using a large detector pixel size. The option `--plot-mode PYQTGRAPH` will display a plot window of the projection data after it is created. (This will not be available if the module was not installed with the `[gui]` option.)
175
178
 
176
179
  Now, let's reconstruct with three different algorithms:
177
180
  1. Global Backprojection-Convolution (GBC)
@@ -186,10 +189,14 @@ aprict-cli recon gbc-cone-cyl \
186
189
  --voxwid 0.5 \
187
190
  --volshape '(525,525,525)' \
188
191
  --alg GREWAR \
192
+ --f1 1.2 \
193
+ --f2 6 \
194
+ --n 9 \
195
+ --eps 1e-9 \
189
196
  --output recon_gbc \
190
197
  --plot-mode PYQTGRAPH
191
198
  ```
192
- (Time on my machine: ~37 seconds)
199
+ (Time on my machine: ~39 seconds)
193
200
 
194
201
  To perform an FBP reconstruction, we do:
195
202
  ```bash
@@ -202,7 +209,7 @@ aprict-cli recon fbp-cone-cyl \
202
209
  --output recon_fbp \
203
210
  --plot-mode PYQTGRAPH
204
211
  ```
205
- (Time on my machine: ~12 seconds)
212
+ (Time on my machine: ~19 seconds)
206
213
 
207
214
  To perform an FBP-VM reconstruction, we change `--alg` to `NOOGREWAR`:
208
215
  ```bash
@@ -215,7 +222,7 @@ aprict-cli recon fbp-cone-cyl \
215
222
  --output recon_fbp-vw \
216
223
  --plot-mode PYQTGRAPH
217
224
  ```
218
- (Time on my machine: ~22 seconds)
225
+ (Time on my machine: ~26 seconds)
219
226
 
220
227
 
221
228
  </details>
@@ -253,7 +260,7 @@ aprict-cli project cbfp \
253
260
  --output projs \
254
261
  --plot-mode PYQTGRAPH
255
262
  ````
256
- (Time on my machine: ~1 minute, 46 seconds)
263
+ (Time on my machine: ~1 minute, 48 seconds)
257
264
  The option `--plot-mode PYQTGRAPH` will display a plot window of the projection data (a sinogram) after it is created. (This will not be available if the module was not installed with the `[gui]` option.)
258
265
 
259
266
  You will find a copy of the `ROCK_CAN` phantom in the output directory `projs`, beside the projection data. The phantom is always copied to the output directory, to ensure a good record of the inputs to the simulation.
File without changes
File without changes
File without changes
File without changes
File without changes