Skip to content

Commit 109eade

Browse files
Georg SchrammGeorg Schramm
authored andcommitted
WIP simulation and recon
1 parent 422857b commit 109eade

File tree

2 files changed

+28
-12
lines changed

2 files changed

+28
-12
lines changed

python/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
*.bin
22
*.npy
33
tmp
4+
my_lm_sim/*

python/simulate_block_scanner_listmode_data.py

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99
import petsird
1010
import matplotlib.pyplot as plt
1111
import math
12+
import json
1213

14+
from pathlib import Path
1315

14-
# %% c
16+
17+
# %%
1518
def circular_distance(i_mod_1: int, i_mod_2: int, num_modules: int) -> int:
1619
clockwise_distance = abs(i_mod_1 - i_mod_2)
1720
counterclockwise_distance = num_modules - clockwise_distance
@@ -36,11 +39,12 @@ def module_pair_eff_from_sgd(i_sgd: int) -> float:
3639
# parse the command line for the input parameters below
3740
parser = argparse.ArgumentParser()
3841

39-
parser.add_argument("--fname", type=str, default="sim_lm.bin")
42+
parser.add_argument("--fname", type=str, default="simulated_lm_file.bin")
43+
parser.add_argument("--output_dir", type=str, default="my_lm_sim")
4044
parser.add_argument("--num_true_counts", type=int, default=int(1e6))
4145
parser.add_argument("--show_plots", default=False, action="store_true")
4246
parser.add_argument("--check_backprojection", default=False, action="store_true")
43-
parser.add_argument("--run_recon", default=False, action="store_true")
47+
parser.add_argument("--run_histogram_mlem", default=False, action="store_true")
4448
parser.add_argument("--num_iter", type=int, default=10)
4549
parser.add_argument("--skip_writing", default=False, action="store_true")
4650
parser.add_argument("--fwhm_mm", type=float, default=1.5)
@@ -58,15 +62,24 @@ def module_pair_eff_from_sgd(i_sgd: int) -> float:
5862
fname = args.fname
5963
show_plots = args.show_plots
6064
check_backprojection = args.check_backprojection
61-
run_recon = args.run_recon
65+
run_histogram_mlem = args.run_histogram_mlem
6266
num_true_counts = args.num_true_counts
6367
skip_writing = args.skip_writing
6468
num_iter = args.num_iter
6569
fwhm_mm = args.fwhm_mm
6670
tof_fwhm_mm = args.tof_fwhm_mm
6771
seed = args.seed
6872
phantom = args.phantom
73+
output_dir = Path(args.output_dir)
74+
75+
if not output_dir.exists():
76+
output_dir.mkdir(parents=True)
6977

78+
# dump args into a json file output_dir / "args.json"
79+
with open(output_dir / "sim_parameters.json", "w") as f:
80+
json.dump(vars(args), f, indent=4)
81+
82+
# %%
7083
dev = "cpu"
7184
xp.random.seed(args.seed)
7285

@@ -262,8 +275,9 @@ def module_pair_eff_from_sgd(i_sgd: int) -> float:
262275
# TOF backproject a "TOF histogram" full of ones ("sensitivity image" when attenuation
263276
# and normalization are ignored)
264277

265-
ones_back_tof = fwd_op.adjoint(xp.ones(fwd_op.out_shape, dtype=xp.float32, device=dev))
266-
print(ones_back_tof.shape)
278+
sens_img = fwd_op.adjoint(xp.ones(fwd_op.out_shape, dtype=xp.float32, device=dev))
279+
xp.save(output_dir / "reference_sensitivity_image.npy", sens_img)
280+
print(sens_img.shape)
267281

268282
# %%
269283
# put poisson noise on the forward projection
@@ -276,18 +290,19 @@ def module_pair_eff_from_sgd(i_sgd: int) -> float:
276290
emission_data = img_fwd_tof
277291

278292
# %%
279-
if run_recon:
293+
if run_histogram_mlem:
280294
recon = xp.ones(img_shape, dtype=xp.float32, device=dev)
281295

282296
for i in range(num_iter):
283297
print(f"{(i+1):03}/{num_iter:03}", end="\r")
284298

285299
exp = xp.clip(fwd_op(recon), 1e-6, None)
286300
grad = fwd_op.adjoint((exp - emission_data) / exp)
287-
step = recon / ones_back_tof
301+
step = recon / sens_img
288302
recon -= step * grad
289303

290304
print("")
305+
xp.save(output_dir / f"reference_histogram_mlem_{num_iter}.npy", recon)
291306

292307
# %%
293308
# convert emission histogram to LM
@@ -382,13 +397,13 @@ def module_pair_eff_from_sgd(i_sgd: int) -> float:
382397

383398
if show_plots:
384399
fig6, ax6 = plt.subplots(1, 4, figsize=(12, 3), tight_layout=True)
385-
vmin = float(xp.min(ones_back_tof))
386-
vmax = float(xp.max(ones_back_tof))
400+
vmin = float(xp.min(sens_img))
401+
vmax = float(xp.max(sens_img))
387402
for i, sl in enumerate(
388403
[img_shape[2] // 4, img_shape[2] // 2, 3 * img_shape[2] // 4]
389404
):
390405
ax6[i].imshow(
391-
parallelproj.to_numpy_array(ones_back_tof[:, :, sl]),
406+
parallelproj.to_numpy_array(sens_img[:, :, sl]),
392407
vmin=vmin,
393408
vmax=vmax,
394409
cmap="Greys",
@@ -610,7 +625,7 @@ def module_pair_eff_from_sgd(i_sgd: int) -> float:
610625

611626
if not skip_writing:
612627
print("Writing LM file")
613-
with petsird.BinaryPETSIRDWriter(fname) as writer:
628+
with petsird.BinaryPETSIRDWriter(str(output_dir / fname)) as writer:
614629
writer.write_header(header)
615630
for i_t in range(1):
616631
start = i_t * header.scanner.event_time_block_duration

0 commit comments

Comments
 (0)