-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
337 changed files
with
69,523 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Sphinx build info version 1 | ||
# This file records the configuration used when building these files. When it is not found, a full rebuild will be done. | ||
config: f890332ff33e9a7902f7376252864dd5 | ||
tags: 645f666f9bcd5a90fca523b33c5a78b7 |
Binary file added
BIN
+39.2 KB
pr-98/.doctrees/auto_examples/01_pet_geometry/01_run_regular_polygon_pet_scanner.doctree
Binary file not shown.
Binary file added
BIN
+50.1 KB
pr-98/.doctrees/auto_examples/01_pet_geometry/02_run_regular_polygon_pet_sino.doctree
Binary file not shown.
Binary file added
BIN
+38.7 KB
pr-98/.doctrees/auto_examples/01_pet_geometry/03_run_block_scanner.doctree
Binary file not shown.
Binary file added
BIN
+11.3 KB
pr-98/.doctrees/auto_examples/01_pet_geometry/sg_execution_times.doctree
Binary file not shown.
Binary file added
BIN
+54.2 KB
...s/auto_examples/02_pet_sinogram_projections/01_run_pet_non_tof_sinogram_projector.doctree
Binary file not shown.
Binary file added
BIN
+46 KB
...trees/auto_examples/02_pet_sinogram_projections/02_run_pet_tof_sinogram_projector.doctree
Binary file not shown.
Binary file added
BIN
+47.7 KB
...8/.doctrees/auto_examples/02_pet_sinogram_projections/03_run_equalblock_projector.doctree
Binary file not shown.
Binary file added
BIN
+11.7 KB
pr-98/.doctrees/auto_examples/02_pet_sinogram_projections/sg_execution_times.doctree
Binary file not shown.
Binary file added
BIN
+41.5 KB
...s/auto_examples/03_pet_listmode_projections/01_run_pet_non_tof_listmode_projector.doctree
Binary file not shown.
Binary file added
BIN
+42.4 KB
...trees/auto_examples/03_pet_listmode_projections/02_run_pet_tof_listmode_projector.doctree
Binary file not shown.
Binary file added
BIN
+10.2 KB
pr-98/.doctrees/auto_examples/03_pet_listmode_projections/sg_execution_times.doctree
Binary file not shown.
Binary file added
BIN
+33.3 KB
pr-98/.doctrees/auto_examples/04_low_level/01_run_nontof_projections.doctree
Binary file not shown.
Binary file added
BIN
+36.4 KB
pr-98/.doctrees/auto_examples/04_low_level/02_run_tof_sinogram_projections.doctree
Binary file not shown.
Binary file added
BIN
+35.5 KB
pr-98/.doctrees/auto_examples/04_low_level/03_run_tof_listmode_projections.doctree
Binary file not shown.
Binary file added
BIN
+11.2 KB
pr-98/.doctrees/auto_examples/04_low_level/sg_execution_times.doctree
Binary file not shown.
Binary file added
BIN
+39.3 KB
pr-98/.doctrees/auto_examples/05_algorithms/01_run_mlem_basic.doctree
Binary file not shown.
Binary file added
BIN
+43.8 KB
pr-98/.doctrees/auto_examples/05_algorithms/02_run_osem_basic.doctree
Binary file not shown.
Binary file added
BIN
+716 KB
pr-98/.doctrees/auto_examples/05_algorithms/03_run_mlem_projection_data.doctree
Binary file not shown.
Binary file added
BIN
+773 KB
pr-98/.doctrees/auto_examples/05_algorithms/04_run_osem_projection_data.doctree
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added
BIN
+164 KB
pr-98/.doctrees/auto_examples/05_algorithms/07_run_mlem_open_geometry.doctree
Binary file not shown.
Binary file added
BIN
+16.5 KB
pr-98/.doctrees/auto_examples/05_algorithms/sg_execution_times.doctree
Binary file not shown.
Binary file added
BIN
+48.1 KB
pr-98/.doctrees/auto_examples/06_listmode_algorithms/01_listmode_mlem.doctree
Binary file not shown.
Binary file added
BIN
+50.1 KB
pr-98/.doctrees/auto_examples/06_listmode_algorithms/02_listmode_osem.doctree
Binary file not shown.
Binary file added
BIN
+92.5 KB
pr-98/.doctrees/auto_examples/06_listmode_algorithms/03_lm_spdhg.doctree
Binary file not shown.
Binary file added
BIN
+11.1 KB
pr-98/.doctrees/auto_examples/06_listmode_algorithms/sg_execution_times.doctree
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added
BIN
+163 KB
pr-98/_downloads/07fcc19ba03226cd3d83d4e40ec44385/auto_examples_python.zip
Binary file not shown.
Binary file added
BIN
+17.8 KB
pr-98/_downloads/0942a5aca804c72fed1e3753c622eda0/03_run_equalblock_projector.zip
Binary file not shown.
177 changes: 177 additions & 0 deletions
177
pr-98/_downloads/110a8e9e8dde6fdb85f465e626976517/01_run_pet_non_tof_listmode_projector.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
""" | ||
PET non-TOF listmode projector | ||
============================== | ||
In this example we will show how to setup and use a non-TOF | ||
PET listmode projector including geometrical forward projection | ||
in listmode, image-based resolution model and a listmode | ||
attenuation model. | ||
.. tip:: | ||
parallelproj is python array API compatible meaning it supports different | ||
array backends (e.g. numpy, cupy, torch, ...) and devices (CPU or GPU). | ||
Choose your preferred array API ``xp`` and device ``dev`` below. | ||
.. image:: https://mybinder.org/badge_logo.svg | ||
:target: https://mybinder.org/v2/gh/gschramm/parallelproj/master?labpath=examples | ||
""" | ||
|
||
# %% | ||
import array_api_compat.numpy as xp | ||
|
||
# import array_api_compat.cupy as xp | ||
# import array_api_compat.torch as xp | ||
|
||
import parallelproj | ||
from array_api_compat import to_device | ||
import array_api_compat.numpy as np | ||
import matplotlib.pyplot as plt | ||
|
||
# choose a device (CPU or CUDA GPU) | ||
if "numpy" in xp.__name__: | ||
# using numpy, device must be cpu | ||
dev = "cpu" | ||
elif "cupy" in xp.__name__: | ||
# using cupy, only cuda devices are possible | ||
dev = xp.cuda.Device(0) | ||
elif "torch" in xp.__name__: | ||
# using torch valid choices are 'cpu' or 'cuda' | ||
dev = "cuda" | ||
|
||
# %% | ||
# Setup a small regular polygon PET scanner with 5 rings (polygons) | ||
# ----------------------------------------------------------------- | ||
|
||
num_rings = 4 | ||
scanner = parallelproj.RegularPolygonPETScannerGeometry( | ||
xp, | ||
dev, | ||
radius=65.0, | ||
num_sides=12, | ||
num_lor_endpoints_per_side=15, | ||
lor_spacing=2.3, | ||
ring_positions=xp.linspace(-10, 10, num_rings), | ||
symmetry_axis=1, | ||
) | ||
|
||
# %% | ||
# Generate 4 arbitrary listmode events | ||
# ------------------------------------ | ||
|
||
start_ring = xp.asarray([2, 1, 0, 3], device=dev) | ||
start_xtal = xp.asarray([0, 59, 143, 75], device=dev) | ||
|
||
end_ring = xp.asarray([2, 0, 1, 3], device=dev) | ||
end_xtal = xp.asarray([79, 140, 33, 147], device=dev) | ||
|
||
event_start_coordinates = scanner.get_lor_endpoints(start_ring, start_xtal) | ||
event_end_coordinates = scanner.get_lor_endpoints(end_ring, end_xtal) | ||
|
||
print(event_start_coordinates) | ||
print(event_end_coordinates) | ||
|
||
# %% | ||
# Show the scanner geometry and the events | ||
# ---------------------------------------- | ||
|
||
fig = plt.figure(figsize=(8, 8)) | ||
ax = fig.add_subplot(111, projection="3d") | ||
scanner.show_lor_endpoints(ax) | ||
for i in range(event_start_coordinates.shape[0]): | ||
ax.plot( | ||
[float(event_start_coordinates[i, 0]), float(event_end_coordinates[i, 0])], | ||
[float(event_start_coordinates[i, 1]), float(event_end_coordinates[i, 1])], | ||
[float(event_start_coordinates[i, 2]), float(event_end_coordinates[i, 2])], | ||
) | ||
fig.tight_layout() | ||
fig.show() | ||
|
||
|
||
# %% | ||
# Setup a listmode projector and a test image | ||
# ------------------------------------------- | ||
|
||
img_shape = (40, 9, 40) | ||
voxel_size = (2.0, 3.0, 2.0) | ||
|
||
lm_proj = parallelproj.ListmodePETProjector( | ||
event_start_coordinates, event_end_coordinates, img_shape, voxel_size | ||
) | ||
|
||
x = xp.ones(img_shape, dtype=xp.float32, device=dev) | ||
|
||
# %% | ||
# Perform listmode forward and back projections | ||
# --------------------------------------------- | ||
|
||
x_fwd = lm_proj(x) | ||
print(x_fwd) | ||
|
||
# back project a list of ones | ||
ones_list = xp.ones(lm_proj.num_events, dtype=xp.float32, device=dev) | ||
y_back = lm_proj.adjoint(ones_list) | ||
|
||
# %% | ||
# Show the backprojected list of ones (events) | ||
# -------------------------------------------- | ||
|
||
fig2, ax2 = plt.subplots(3, 3, figsize=(8, 8)) | ||
vmax = float(xp.max(y_back)) | ||
for i in range(ax2.size): | ||
if i < y_back.shape[1]: | ||
axx = ax2.ravel()[i] | ||
axx.imshow( | ||
parallelproj.to_numpy_array(y_back[:, i, :].T), | ||
cmap="Greys", | ||
vmin=0, | ||
vmax=vmax, | ||
) | ||
axx.set_title(f"img plane {i}", fontsize="medium") | ||
else: | ||
ax2.ravel()[i].set_axis_off() | ||
fig2.tight_layout() | ||
fig2.show() | ||
|
||
# %% | ||
# Combine the listmode projector with a resolution and attenuation model | ||
# ---------------------------------------------------------------------- | ||
|
||
# setup a simple image-based resolution model with an Gaussian FWHM of 4.5mm | ||
res_model = parallelproj.GaussianFilterOperator( | ||
lm_proj.in_shape, sigma=4.5 / (2.35 * lm_proj.voxel_size) | ||
) | ||
|
||
# define arbritrary attenuation factors | ||
att_list = xp.asarray([0.3, 0.4, 0.2, 0.6], device=dev) | ||
att_op = parallelproj.ElementwiseMultiplicationOperator(att_list) | ||
|
||
|
||
lm_proj_with_res_model_and_att = parallelproj.CompositeLinearOperator( | ||
(att_op, lm_proj, res_model) | ||
) | ||
|
||
x_fwd2 = lm_proj_with_res_model_and_att(x) | ||
print(x_fwd2) | ||
|
||
y_back2 = lm_proj_with_res_model_and_att.adjoint(ones_list) | ||
|
||
# %% | ||
# Show the backprojected list of ones (events) | ||
# -------------------------------------------- | ||
|
||
fig3, ax3 = plt.subplots(3, 3, figsize=(8, 8)) | ||
vmax = float(xp.max(y_back2)) | ||
for i in range(ax3.size): | ||
if i < y_back.shape[1]: | ||
axx = ax3.ravel()[i] | ||
axx.imshow( | ||
parallelproj.to_numpy_array(y_back2[:, i, :].T), | ||
cmap="Greys", | ||
vmin=0, | ||
vmax=vmax, | ||
) | ||
axx.set_title(f"img plane {i}", fontsize="medium") | ||
else: | ||
ax3.ravel()[i].set_axis_off() | ||
fig3.tight_layout() | ||
fig3.show() |
187 changes: 187 additions & 0 deletions
187
...8/_downloads/1209efffc3032a2746127056278142b7/01_run_pet_non_tof_listmode_projector.ipynb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"\n# PET non-TOF listmode projector\n\nIn this example we will show how to setup and use a non-TOF \nPET listmode projector including geometrical forward projection\nin listmode, image-based resolution model and a listmode \nattenuation model.\n\n.. tip::\n parallelproj is python array API compatible meaning it supports different \n array backends (e.g. numpy, cupy, torch, ...) and devices (CPU or GPU).\n Choose your preferred array API ``xp`` and device ``dev`` below.\n\n<img src=\"https://mybinder.org/badge_logo.svg\" target=\"https://mybinder.org/v2/gh/gschramm/parallelproj/master?labpath=examples\">\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"import array_api_compat.numpy as xp\n\n# import array_api_compat.cupy as xp\n# import array_api_compat.torch as xp\n\nimport parallelproj\nfrom array_api_compat import to_device\nimport array_api_compat.numpy as np\nimport matplotlib.pyplot as plt\n\n# choose a device (CPU or CUDA GPU)\nif \"numpy\" in xp.__name__:\n # using numpy, device must be cpu\n dev = \"cpu\"\nelif \"cupy\" in xp.__name__:\n # using cupy, only cuda devices are possible\n dev = xp.cuda.Device(0)\nelif \"torch\" in xp.__name__:\n # using torch valid choices are 'cpu' or 'cuda'\n dev = \"cuda\"" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Setup a small regular polygon PET scanner with 5 rings (polygons)\n\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"num_rings = 4\nscanner = parallelproj.RegularPolygonPETScannerGeometry(\n xp,\n dev,\n radius=65.0,\n num_sides=12,\n num_lor_endpoints_per_side=15,\n lor_spacing=2.3,\n ring_positions=xp.linspace(-10, 10, num_rings),\n symmetry_axis=1,\n)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Generate 4 arbitrary listmode events\n\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"start_ring = xp.asarray([2, 1, 0, 3], device=dev)\nstart_xtal = xp.asarray([0, 59, 143, 75], device=dev)\n\nend_ring = xp.asarray([2, 0, 1, 3], device=dev)\nend_xtal = xp.asarray([79, 140, 33, 147], device=dev)\n\nevent_start_coordinates = scanner.get_lor_endpoints(start_ring, start_xtal)\nevent_end_coordinates = scanner.get_lor_endpoints(end_ring, end_xtal)\n\nprint(event_start_coordinates)\nprint(event_end_coordinates)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Show the scanner geometry and the events\n\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"fig = plt.figure(figsize=(8, 8))\nax = fig.add_subplot(111, projection=\"3d\")\nscanner.show_lor_endpoints(ax)\nfor i in range(event_start_coordinates.shape[0]):\n ax.plot(\n [float(event_start_coordinates[i, 0]), float(event_end_coordinates[i, 0])],\n [float(event_start_coordinates[i, 1]), float(event_end_coordinates[i, 1])],\n [float(event_start_coordinates[i, 2]), float(event_end_coordinates[i, 2])],\n )\nfig.tight_layout()\nfig.show()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Setup a listmode projector and a test image\n\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"img_shape = (40, 9, 40)\nvoxel_size = (2.0, 3.0, 2.0)\n\nlm_proj = parallelproj.ListmodePETProjector(\n event_start_coordinates, event_end_coordinates, img_shape, voxel_size\n)\n\nx = xp.ones(img_shape, dtype=xp.float32, device=dev)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Perform listmode forward and back projections\n\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"x_fwd = lm_proj(x)\nprint(x_fwd)\n\n# back project a list of ones\nones_list = xp.ones(lm_proj.num_events, dtype=xp.float32, device=dev)\ny_back = lm_proj.adjoint(ones_list)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Show the backprojected list of ones (events)\n\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"fig2, ax2 = plt.subplots(3, 3, figsize=(8, 8))\nvmax = float(xp.max(y_back))\nfor i in range(ax2.size):\n if i < y_back.shape[1]:\n axx = ax2.ravel()[i]\n axx.imshow(\n parallelproj.to_numpy_array(y_back[:, i, :].T),\n cmap=\"Greys\",\n vmin=0,\n vmax=vmax,\n )\n axx.set_title(f\"img plane {i}\", fontsize=\"medium\")\n else:\n ax2.ravel()[i].set_axis_off()\nfig2.tight_layout()\nfig2.show()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Combine the listmode projector with a resolution and attenuation model\n\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"# setup a simple image-based resolution model with an Gaussian FWHM of 4.5mm\nres_model = parallelproj.GaussianFilterOperator(\n lm_proj.in_shape, sigma=4.5 / (2.35 * lm_proj.voxel_size)\n)\n\n# define arbritrary attenuation factors\natt_list = xp.asarray([0.3, 0.4, 0.2, 0.6], device=dev)\natt_op = parallelproj.ElementwiseMultiplicationOperator(att_list)\n\n\nlm_proj_with_res_model_and_att = parallelproj.CompositeLinearOperator(\n (att_op, lm_proj, res_model)\n)\n\nx_fwd2 = lm_proj_with_res_model_and_att(x)\nprint(x_fwd2)\n\ny_back2 = lm_proj_with_res_model_and_att.adjoint(ones_list)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Show the backprojected list of ones (events)\n\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"fig3, ax3 = plt.subplots(3, 3, figsize=(8, 8))\nvmax = float(xp.max(y_back2))\nfor i in range(ax3.size):\n if i < y_back.shape[1]:\n axx = ax3.ravel()[i]\n axx.imshow(\n parallelproj.to_numpy_array(y_back2[:, i, :].T),\n cmap=\"Greys\",\n vmin=0,\n vmax=vmax,\n )\n axx.set_title(f\"img plane {i}\", fontsize=\"medium\")\n else:\n ax3.ravel()[i].set_axis_off()\nfig3.tight_layout()\nfig3.show()" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.12.7" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 0 | ||
} |
Oops, something went wrong.