Skip to content

Commit 0a506c3

Browse files
Georg SchrammGeorg Schramm
authored andcommitted
WIP
1 parent 0c2c563 commit 0a506c3

File tree

3 files changed

+32
-30
lines changed

3 files changed

+32
-30
lines changed

README.md

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,35 @@
1-
# PETSIRD v0.2 - parallelproj repository
2-
3-
The purpose of this repo is to provide a starting point for developing software that uses PETSIRD.
4-
Here we will focus on python usecases using parallelproj projection library.
1+
# Analytic simulation of petsird v0.2 data using parallelproj
52

63
## Create your conda / mamba environment
74

85
```
96
conda env create -f environment.yml
10-
```
11-
12-
## Run a first PETSIRD example
13-
14-
```
157
conda activate petsird-v0.2-parallelproj
168
cd python
17-
python petsird_generator.py > test.bin
18-
python petsird_analysis.py < test.bin
199
```
2010

21-
## Projects to work on
22-
23-
### Read scanner geometry from a PETSIRD file and visualize it
11+
## Simulate petsird LM data
2412

25-
**TODO**:
26-
- start from this [parallel example here](https://parallelproj.readthedocs.io/en/stable/auto_examples/01_pet_geometry/03_run_block_scanner.html#sphx-glr-auto-examples-01-pet-geometry-03-run-block-scanner-py) and this [petsird example here](python/petsird_plot_scanner_and_events.py)
27-
- map PETSIRD scanner detector elements to LOR endpoints
28-
- How to map BoxShape to a single LOR point? (center of the Box is not want we want. We need most likely interaction point.)
29-
- use LOR endpoints to setup [BlockScannerModules](https://parallelproj.readthedocs.io/en/stable/python_api.html#parallelproj.pet_scanners.BlockPETScannerModule) tha can be used in [ModularizedPETScannerGeometry](https://parallelproj.readthedocs.io/en/stable/python_api.html#parallelproj.pet_scanners.ModularizedPETScannerGeometry) or a [RegularPolygonPETScannerGeometry](https://parallelproj.readthedocs.io/en/stable/python_api.html#parallelproj.pet_scanners.RegularPolygonPETScannerGeometry) - depending of the system geometry and module definition. Using the latter is more convient for the definition of sinograms, the former is better for systems with less symmetries where it is less straight forward to define "sinograms".
30-
31-
### Simulation of PETSIRD LM data using parallelproj
13+
```
14+
python 01_analytic_petsird_lm_simulator.py
15+
```
3216

33-
Start from this [parallelproj example](https://parallelproj.readthedocs.io/en/stable/auto_examples/06_listmode_algorithms/01_listmode_mlem.html#sphx-glr-auto-examples-06-listmode-algorithms-01-listmode-mlem-py).
17+
The simulation can be customized in many ways (number of counts to simulate,
18+
uniform or non-uniform efficiencies ...) via command line options.
3419

35-
**TODO**:
36-
- rewrite (simplify) util function that converts sinogram to listmode including event detectors IDs instead of coordinates. Write an updated noisy emission sinogram to LM converter similar to [this](https://parallelproj.readthedocs.io/en/stable/_modules/parallelproj/projectors.html#RegularPolygonPETProjector.convert_sinogram_to_listmode) but skipping the detector ID to world coordinate lookup.
37-
- write scanner geometry to file
20+
These option can be listed via
21+
```
22+
python 01_analytic_petsird_lm_simulator.py
23+
```
3824

25+
## Run a listmode OSEM recon on the simulated
3926

27+
```
28+
python 02_recon_block_scanner_listmode_data.py
29+
```
4030

31+
Thes command line optione for the LM OSEM recon script can be listed via
32+
```
33+
python 02_recon_block_scanner_listmode_data.py -h
34+
```
4135

python/01_analytic_petsird_lm_simulator.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ def module_pair_eff_from_sgd(i_sgd: int, uniform: bool = False) -> float:
4444
return res
4545

4646

47-
# parse the command line
4847
def parse_int_tuple(arg):
4948
return tuple(map(int, arg.split(",")))
5049

@@ -63,7 +62,7 @@ def parse_float_tuple(arg):
6362

6463
parser.add_argument("--fname", type=str, default="simulated_lm_file.bin")
6564
parser.add_argument("--output_dir", type=str, default="my_lm_sim")
66-
parser.add_argument("--num_true_counts", type=int, default=int(1e6))
65+
parser.add_argument("--num_true_counts", type=int, default=int(4e6))
6766
parser.add_argument("--skip_plots", action="store_true")
6867
parser.add_argument("--check_backprojection", default=False, action="store_true")
6968
parser.add_argument("--num_epochs_mlem", type=int, default=0)
@@ -78,7 +77,7 @@ def parse_float_tuple(arg):
7877
parser.add_argument(
7978
"--phantom",
8079
type=str,
81-
default="uniform_cylinder",
80+
default="squares",
8281
choices=["uniform_cylinder", "squares"],
8382
)
8483

python/recon_block_scanner_listmode_data.py renamed to python/02_recon_block_scanner_listmode_data.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,18 @@ def transform_BoxShape(
7676
)
7777

7878

79+
def parse_int_tuple(arg):
80+
return tuple(map(int, arg.split(",")))
81+
82+
83+
def parse_float_tuple(arg):
84+
return tuple(map(float, arg.split(",")))
85+
86+
7987
# %%
8088

8189
parser = argparse.ArgumentParser()
82-
parser.add_argument("--fname", type=str, default="sim_lm.bin")
90+
parser.add_argument("--fname", type=str, default="my_lm_sim/simulated_lm_file.bin")
8391
parser.add_argument("--num_epochs", type=int, default=5)
8492
parser.add_argument("--num_subsets", type=int, default=20)
8593
parser.add_argument("--img_shape", type=parse_int_tuple, default=(100, 100, 11))
@@ -223,13 +231,13 @@ def transform_BoxShape(
223231
proj.event_tofbins = xp.full(
224232
start_coords.shape[0], tofbin, dtype="int32"
225233
)
234+
proj.tof = True
226235
sens_img += proj.adjoint(start_el_eff * end_el_eff * module_pair_eff)
227236

228237
print("")
229238

230239
# for some reason we have to divide the sens image by the number of TOF bins
231240
# right now unclear why that is
232-
sens_img /= num_tofbins
233241
sens_img = res_model.adjoint(sens_img)
234242

235243
# %%
@@ -294,6 +302,7 @@ def transform_BoxShape(
294302
)
295303
lm_subset_projs[i_subset].tof_parameters = tof_params
296304
lm_subset_projs[i_subset].event_tofbins = tof_bin[sl]
305+
lm_subset_projs[i_subset].tof = True
297306

298307
for i_epoch in range(num_epochs):
299308
for i_subset, sl in enumerate(subset_slices):

0 commit comments

Comments
 (0)