From d3a0f2d77eb599f73233f7baf33407dc715ab54f Mon Sep 17 00:00:00 2001
From: Tamino Huxohl <thuxohl@techfak.uni-bielefeld.de>
Date: Thu, 20 Oct 2022 11:04:40 +0200
Subject: [PATCH] add reconstruction function to util

---
 mu_map/util.py | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/mu_map/util.py b/mu_map/util.py
index 914793b..63d72ff 100644
--- a/mu_map/util.py
+++ b/mu_map/util.py
@@ -1,6 +1,8 @@
+import math
 from typing import Optional
 
 import numpy as np
+from tomolab.Reconstruction.SPECT import SPECT_Static_Scan
 
 COLOR_BLACK = (0, 0, 0)
 COLOR_WHITE = (255, 255, 255)
@@ -40,3 +42,65 @@ def grayscale_to_rgb(img: np.ndarray):
     """
     assert img.ndim == 2, f"grascale image has more than 2 dimensions {img.shape}"
     return img.repeat(3).reshape((*img.shape, 3))
+
+
+def reconstruct(recon, mu_map=None, use_gpu=True):
+    recon = np.transpose(recon, (2, 1, 0)).astype(np.float32)
+    print(f"Transpose recon to {recon.shape}")
+    if mu_map is not None:
+        mu_map = np.transpose(mu_map, (2, 1, 0)).astype(np.float32)
+
+        s = recon.shape[0]
+        padding_lower = math.ceil(s - mu_map.shape[2])
+        padding_upper = math.floor(s - mu_map.shape[2])
+        _shape = mu_map.shape
+        mu_map = np.pad(mu_map, [(0, 0), (0, 0), (padding_lower, padding_upper)])
+        print(f"Change mu_map shape from {_shape} to {mu_map.shape}")
+
+
+    spect = SPECT_Static_Scan()
+    spect.set_use_gpu(use_gpu)
+
+    spect.set_n_pixels(128, 128)
+    spect.set_gantry_angular_positions(0.0, 360.0, 59)
+
+    print("Forward projection .....", end="\r")
+    if mu_map is not None:
+        measurement = spect.project(recon, attenuation=mu_map)
+        spect.set_measurement(measurement.data)
+        spect.set_attenuation(mu_map)
+    else:
+        measurement = spect.project(recon)
+        spect.set_measurement(measurement.data)
+    print("Forward projection DONE!")
+
+    spect.set_pixel_size(4.8, 4.8)
+    spect.set_radius(200.0)
+    spect.set_psf(fwhm0_mm=5.0, depth_dependence=0.0001)
+
+    print("Reconstruction .....", end="\r")
+    activity = spect.estimate_activity(
+        iterations=10, subset_size=16, subset_mode="random", method="EM"
+    )
+    activity = activity.data
+    print("Reconstruction DONE!")
+
+    s = recon.shape[2] / 2
+    c = activity.shape[2] // 2
+    activity = activity[:, :, c-math.ceil(s):c+math.floor(s)]
+    print(f"Reshape activity to {activity.shape}")
+
+    return np.transpose(activity, (2, 1, 0))
+
+if __name__ == "__main__":
+    import pydicom
+    
+    from mu_map.dataset.default import DCM_TAG_PIXEL_SCALE_FACTOR
+
+    img = pydicom.dcmread("./data/second/images/0001-stress-recon_nac_nsc.dcm")
+    img = img.pixel_array / img[DCM_TAG_PIXEL_SCALE_FACTOR].value
+
+    mu_map = pydicom.dcmread("./data/second/images/0001-stress-mu_map.dcm")
+    mu_map = mu_map.pixel_array / mu_map[DCM_TAG_PIXEL_SCALE_FACTOR].value
+
+    reconstruct(img, mu_map)
-- 
GitLab