.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/01_tof_sinogram_projection.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_01_tof_sinogram_projection.py: Sinogram (histogram) TOF Joseph Forward and Back Projection =========================================================== This minimal example demonstrates how to call python API for the sinogram (histogram) TOF Joseph forward and back projection functions, which are implemented in :func:`parallelproj_core.joseph3d_tof_sino_fwd` and :func:`parallelproj_core.joseph3d_tof_sino_back`. .. note:: In this educational example, the TOF resolution is much smaller compared to the voxel size, which is not typical for real PET scanners, but better for visualization. .. GENERATED FROM PYTHON SOURCE LINES 13-19 .. code-block:: Python import importlib import parallelproj_core import matplotlib.pyplot as plt from utils import show_voxel_cube, show_lors, to_numpy .. GENERATED FROM PYTHON SOURCE LINES 20-21 import array API compatible library (CuPy if CUDA is available, otherwise NumPy). .. GENERATED FROM PYTHON SOURCE LINES 21-31 .. code-block:: Python if parallelproj_core.cuda_enabled == 1 and importlib.util.find_spec("cupy") is not None: import array_api_compat.cupy as xp dev = xp.cuda.Device(0) else: import array_api_compat.numpy as xp dev = "cpu" .. GENERATED FROM PYTHON SOURCE LINES 32-33 Print backend and device info. .. GENERATED FROM PYTHON SOURCE LINES 33-37 .. code-block:: Python print(f"parallelproj_core version: {parallelproj_core.__version__}") print(f"parallelproj_core cuda enabled: {parallelproj_core.cuda_enabled}") print(f"using array API compatible library: {xp.__name__} on device {dev}") .. rst-class:: sphx-glr-script-out .. code-block:: none parallelproj_core version: v2.0.2 parallelproj_core cuda enabled: 0 using array API compatible library: array_api_compat.numpy on device cpu .. GENERATED FROM PYTHON SOURCE LINES 38-39 Define a mini sparse demo image. .. GENERATED FROM PYTHON SOURCE LINES 39-48 .. code-block:: Python image = xp.zeros((5, 5, 5), dtype=xp.float32, device=dev) image[0, 2, 4] = 0.25 image[4, 2, 4] = 0.25 image[0, 0, 0] = 0.5 image[4, 4, 4] = 0.5 voxel_size = xp.asarray([2.0, 2.0, 2.0], device=dev, dtype=xp.float32) img_origin = xp.asarray([-1.0, -1.0, -1.0], device=dev, dtype=xp.float32) .. GENERATED FROM PYTHON SOURCE LINES 49-50 Define LOR start and end points. .. GENERATED FROM PYTHON SOURCE LINES 50-61 .. code-block:: Python lor_start = xp.asarray( [[14.0, 3.5, 7.0], [-1, -1, -8], [7, -6, -6]], device=dev, dtype=xp.float32, ) lor_end = xp.asarray( [[-8.0, 3.5, 7.0], [-1, -1, 14], [7, 12, 12]], device=dev, dtype=xp.float32, ) .. GENERATED FROM PYTHON SOURCE LINES 62-63 TOF parameter setup .. GENERATED FROM PYTHON SOURCE LINES 63-75 .. code-block:: Python # standard deviation of the TOF kernel in spatial units (mm) sigma_tof = xp.asarray([2.0], device=dev, dtype=xp.float32) # width of the TOF sinogram bins in mm tofbin_width = float(sigma_tof[0]) / 2.0 # offset of the TOF center in mm tof_center_offset = xp.asarray([0.0], device=dev, dtype=xp.float32) # number of sigmas for truncation of Gaussian TOF kernel num_sigmas = 3.0 # number of TOF bins needed to cover an LOR of 20mm length num_tofbins = int(20 / tofbin_width) + 1 .. GENERATED FROM PYTHON SOURCE LINES 76-77 Forward projection of the demo image. .. GENERATED FROM PYTHON SOURCE LINES 77-93 .. code-block:: Python img_fwd = xp.zeros((lor_start.shape[0], num_tofbins), dtype=xp.float32, device=dev) parallelproj_core.joseph3d_tof_sino_fwd( lor_start, lor_end, image, img_origin, voxel_size, img_fwd, tofbin_width, sigma_tof, tof_center_offset, num_tofbins, num_sigmas, ) print(img_fwd) .. rst-class:: sphx-glr-script-out .. code-block:: none [[0.00090206 0.00347077 0.01045007 0.0246249 0.04541901 0.06557555 0.07411528 0.06557555 0.04632107 0.02809567 0.02090013 0.02809567 0.04632107 0.06557555 0.07411528 0.06557555 0.04541901 0.0246249 0.01045007 0.00347077 0.00090206] [0.0024055 0.00925539 0.02786685 0.06566641 0.12111737 0.17486815 0.19764075 0.17486815 0.12111737 0.06566641 0.02786685 0.00925539 0.0024055 0. 0. 0. 0. 0. 0. 0. 0. ] [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.00122766 0.00554934 0.0196281 0.05433032 0.11770228 0.19959447 0.26494858 0.2753215 0.22396815 0.14262262 0.07109211 0.02773627]] .. GENERATED FROM PYTHON SOURCE LINES 94-131 .. code-block:: Python fig = plt.figure(figsize=(12, 6), layout="constrained") ax = fig.add_subplot(121, projection="3d") show_voxel_cube(ax, image, voxel_size, img_origin) show_lors( ax, lor_start, lor_end, labels=[f"LOR-{i}" for i in range(lor_start.shape[0])], num_tofbins=num_tofbins, tofbin_width=tofbin_width, tof_center_offset=tof_center_offset, ) ax.set_xlim(-10, 15) ax.set_ylim(-10, 15) ax.set_zlim(-10, 15) ax.set_xlabel("x [mm]") ax.set_ylabel("y [mm]") ax.set_zlabel("z [mm]") ax.set_box_aspect([1, 1, 1]) fig.suptitle( "TOF sinogram forward projection of a 3D image using Joseph's method", fontsize="medium", ) ax_b = fig.add_subplot(122) for i in range(img_fwd.shape[0]): ax_b.plot(to_numpy(img_fwd[i, ...]), ".-", label=f"LOR {i}") ax_b.set_xlabel("TOF bin") ax_b.set_ylabel("TOF projection profile") ax_b.grid(ls=":") ax_b.legend() fig.show() .. image-sg:: /auto_examples/images/sphx_glr_01_tof_sinogram_projection_001.png :alt: TOF sinogram forward projection of a 3D image using Joseph's method :srcset: /auto_examples/images/sphx_glr_01_tof_sinogram_projection_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 132-133 TOF back projection of a TOF sinogram full of ones. .. GENERATED FROM PYTHON SOURCE LINES 133-148 .. code-block:: Python back_ones = xp.zeros(image.shape, dtype=xp.float32, device=dev) parallelproj_core.joseph3d_tof_sino_back( lor_start, lor_end, back_ones, img_origin, voxel_size, xp.ones(img_fwd.shape, dtype=xp.float32, device=dev), tofbin_width, sigma_tof, tof_center_offset, num_tofbins, num_sigmas, ) .. GENERATED FROM PYTHON SOURCE LINES 149-176 .. code-block:: Python fig2 = plt.figure(figsize=(6, 6), layout="constrained") ax2 = fig2.add_subplot(111, projection="3d") show_voxel_cube(ax2, back_ones, voxel_size, img_origin) show_lors( ax2, lor_start, lor_end, labels=[f"LOR-{i}" for i in range(lor_start.shape[0])], num_tofbins=num_tofbins, tofbin_width=tofbin_width, tof_center_offset=tof_center_offset, ) ax2.set_xlim(-10, 15) ax2.set_ylim(-10, 15) ax2.set_zlim(-10, 15) ax2.set_xlabel("x [mm]") ax2.set_ylabel("y [mm]") ax2.set_zlabel("z [mm]") ax2.set_box_aspect([1, 1, 1]) ax2.set_title( "TOF back projection of a TOF sinogram full of ones using Joseph's method", fontsize="medium", ) fig2.show() .. image-sg:: /auto_examples/images/sphx_glr_01_tof_sinogram_projection_002.png :alt: TOF back projection of a TOF sinogram full of ones using Joseph's method :srcset: /auto_examples/images/sphx_glr_01_tof_sinogram_projection_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 177-178 TOF back projection of a TOF sinogram containing a 1 in the "central" TOF bin. .. GENERATED FROM PYTHON SOURCE LINES 178-198 .. code-block:: Python center_tofbin = num_tofbins // 2 tof_sino = xp.zeros(img_fwd.shape, dtype=xp.float32, device=dev) tof_sino[:, center_tofbin] = 1.0 img_back = xp.zeros(image.shape, dtype=xp.float32, device=dev) parallelproj_core.joseph3d_tof_sino_back( lor_start, lor_end, img_back, img_origin, voxel_size, tof_sino, tofbin_width, sigma_tof, tof_center_offset, num_tofbins, num_sigmas, ) .. GENERATED FROM PYTHON SOURCE LINES 199-225 .. code-block:: Python fig3 = plt.figure(figsize=(6, 6), layout="constrained") ax3 = fig3.add_subplot(111, projection="3d") show_voxel_cube(ax3, img_back, voxel_size, img_origin) show_lors( ax3, lor_start, lor_end, labels=[f"LOR-{i}" for i in range(lor_start.shape[0])], num_tofbins=num_tofbins, tofbin_width=tofbin_width, tof_center_offset=tof_center_offset, ) ax3.set_xlim(-10, 15) ax3.set_ylim(-10, 15) ax3.set_zlim(-10, 15) ax3.set_xlabel("x [mm]") ax3.set_ylabel("y [mm]") ax3.set_zlabel("z [mm]") ax3.set_box_aspect([1, 1, 1]) ax3.set_title( f"TOF back projection of a TOF profiles containg a 1 in TOF bin {center_tofbin}", fontsize="medium", ) fig3.show() .. image-sg:: /auto_examples/images/sphx_glr_01_tof_sinogram_projection_003.png :alt: TOF back projection of a TOF profiles containg a 1 in TOF bin 10 :srcset: /auto_examples/images/sphx_glr_01_tof_sinogram_projection_003.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 3.687 seconds) .. _sphx_glr_download_auto_examples_01_tof_sinogram_projection.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: 01_tof_sinogram_projection.ipynb <01_tof_sinogram_projection.ipynb>` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: 01_tof_sinogram_projection.py <01_tof_sinogram_projection.py>` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: 01_tof_sinogram_projection.zip <01_tof_sinogram_projection.zip>` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_