AOT-biomaps 2.9.212__py3-none-any.whl → 2.9.233__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of AOT-biomaps might be problematic. Click here for more details.
- AOT_biomaps/AOT_Experiment/Tomography.py +70 -0
- AOT_biomaps/AOT_Experiment/_mainExperiment.py +41 -22
- AOT_biomaps/AOT_Recon/AOT_Optimizers/DEPIERRO.py +48 -11
- AOT_biomaps/AOT_Recon/AOT_Optimizers/LS.py +9 -6
- AOT_biomaps/AOT_Recon/AOT_Optimizers/MAPEM.py +118 -38
- AOT_biomaps/AOT_Recon/AOT_Optimizers/MLEM.py +157 -86
- AOT_biomaps/AOT_Recon/AOT_PotentialFunctions/RelativeDifferences.py +10 -14
- AOT_biomaps/AOT_Recon/AlgebraicRecon.py +337 -185
- AOT_biomaps/AOT_Recon/BayesianRecon.py +33 -96
- AOT_biomaps/AOT_Recon/PrimalDualRecon.py +14 -18
- AOT_biomaps/AOT_Recon/ReconEnums.py +14 -0
- AOT_biomaps/AOT_Recon/ReconTools.py +4 -3
- AOT_biomaps/AOT_Recon/_mainRecon.py +3 -2
- AOT_biomaps/__init__.py +22 -1
- {aot_biomaps-2.9.212.dist-info → aot_biomaps-2.9.233.dist-info}/METADATA +1 -1
- {aot_biomaps-2.9.212.dist-info → aot_biomaps-2.9.233.dist-info}/RECORD +18 -18
- {aot_biomaps-2.9.212.dist-info → aot_biomaps-2.9.233.dist-info}/WHEEL +0 -0
- {aot_biomaps-2.9.212.dist-info → aot_biomaps-2.9.233.dist-info}/top_level.txt +0 -0
|
@@ -7,6 +7,8 @@ import psutil
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
import matplotlib.pyplot as plt
|
|
9
9
|
from tqdm import trange
|
|
10
|
+
import h5py
|
|
11
|
+
from scipy.io import loadmat
|
|
10
12
|
|
|
11
13
|
class Tomography(Experiment):
|
|
12
14
|
def __init__(self, **kwargs):
|
|
@@ -433,3 +435,71 @@ class Tomography(Experiment):
|
|
|
433
435
|
listAcousticFields.append(AcousticField)
|
|
434
436
|
progress_bar.set_postfix_str("")
|
|
435
437
|
return listAcousticFields
|
|
438
|
+
|
|
439
|
+
def load_experimentalAO(self, pathAO, withTumor = True, h5name='AOsignal'):
|
|
440
|
+
"""
|
|
441
|
+
Load experimental AO signals from specified file paths.
|
|
442
|
+
Args:
|
|
443
|
+
path_withTumor: Path to the AO signal with tumor.
|
|
444
|
+
path_withoutTumor: Path to the AO signal without tumor.
|
|
445
|
+
"""
|
|
446
|
+
if not os.path.exists(pathAO):
|
|
447
|
+
raise FileNotFoundError(f"File {pathAO} not found.")
|
|
448
|
+
|
|
449
|
+
if pathAO.endswith('.npy'):
|
|
450
|
+
ao_signal = np.load(pathAO)
|
|
451
|
+
elif pathAO.endswith('.h5'):
|
|
452
|
+
with h5py.File(pathAO, 'r') as f:
|
|
453
|
+
if h5name not in f:
|
|
454
|
+
raise KeyError(f"Dataset '{h5name}' not found in the HDF5 file.")
|
|
455
|
+
ao_signal = f[h5name][:]
|
|
456
|
+
elif pathAO.endswith('.mat'):
|
|
457
|
+
mat_data = loadmat(pathAO)
|
|
458
|
+
if h5name not in mat_data:
|
|
459
|
+
raise KeyError(f"Dataset '{h5name}' not found in the .mat file.")
|
|
460
|
+
ao_signal = mat_data[h5name]
|
|
461
|
+
elif pathAO.endswith('.hdr'):
|
|
462
|
+
ao_signal = self._loadAOSignal(pathAO)
|
|
463
|
+
else:
|
|
464
|
+
raise ValueError("Unsupported file format. Supported formats are: .npy, .h5, .mat, .hdr")
|
|
465
|
+
|
|
466
|
+
if withTumor:
|
|
467
|
+
self.AOsignal_withTumor = ao_signal
|
|
468
|
+
else:
|
|
469
|
+
self.AOsignal_withoutTumor = ao_signal
|
|
470
|
+
|
|
471
|
+
def check_experimentalAO(self, activeListPath, withTumor=True):
|
|
472
|
+
"""
|
|
473
|
+
Check if the experimental AO signals are correctly initialized.
|
|
474
|
+
"""
|
|
475
|
+
if withTumor:
|
|
476
|
+
if self.AOsignal_withTumor is None:
|
|
477
|
+
raise ValueError("Experimental AOsignal with tumor is not initialized. Please load the experimental AO signal with tumor first.")
|
|
478
|
+
else:
|
|
479
|
+
if self.AOsignal_withoutTumor is None:
|
|
480
|
+
raise ValueError("Experimental AOsignal without tumor is not initialized. Please load the experimental AO signal without tumor first.")
|
|
481
|
+
if self.AcousticFields is not None:
|
|
482
|
+
# get min time shape between all AO signals
|
|
483
|
+
print()
|
|
484
|
+
|
|
485
|
+
if self.AcousticFields[0].field.shape[0] > self.AOsignal_withTumor.shape[0]:
|
|
486
|
+
self.cutAcousticFields(max_t=self.AOsignal_withTumor.shape[0]/float(self.params.acoustic['f_saving']))
|
|
487
|
+
else:
|
|
488
|
+
for i in range(len(self.AcousticFields)):
|
|
489
|
+
min_time_shape = min(self.AcousticFields[i].field.shape[0])
|
|
490
|
+
if withTumor:
|
|
491
|
+
self.AOsignal_withTumor = self.AOsignal_withTumor[:min_time_shape, :]
|
|
492
|
+
else:
|
|
493
|
+
self.AOsignal_withoutTumor = self.AOsignal_withoutTumor[:min_time_shape, :]
|
|
494
|
+
|
|
495
|
+
for field in self.AcousticFields:
|
|
496
|
+
if activeListPath is not None:
|
|
497
|
+
with open(activeListPath, 'r') as file:
|
|
498
|
+
lines = file.readlines()
|
|
499
|
+
expected_name = lines[self.AcousticFields.index(field)].strip()
|
|
500
|
+
nameField = field.getName_field()
|
|
501
|
+
if nameField.startswith("field_"):
|
|
502
|
+
nameField = nameField[len("field_"):]
|
|
503
|
+
if nameField != expected_name:
|
|
504
|
+
raise ValueError(f"Field name {nameField} does not match the expected name {expected_name} from the active list.")
|
|
505
|
+
print("Experimental AO signals are correctly initialized.")
|
|
@@ -77,7 +77,6 @@ class Experiment(ABC):
|
|
|
77
77
|
raise ValueError(f"Field {field.getName_field()} has an invalid shape: {field.field.shape}. Expected shape to be at least ({max_sample},).")
|
|
78
78
|
self.AcousticFields[i].field = field.field[min_sample:max_sample, :, :]
|
|
79
79
|
|
|
80
|
-
|
|
81
80
|
def addNoise(self, noiseType='gaussian', noiseLvl=0.1, withTumor=True):
|
|
82
81
|
"""
|
|
83
82
|
Ajoute du bruit (gaussien ou poisson) au signal AO sélectionné.
|
|
@@ -290,28 +289,48 @@ class Experiment(ABC):
|
|
|
290
289
|
|
|
291
290
|
@staticmethod
|
|
292
291
|
def _loadAOSignal(AOsignalPath):
|
|
293
|
-
# if extension is .cdh load .cdf file
|
|
294
292
|
if AOsignalPath.endswith(".cdh"):
|
|
295
293
|
with open(AOsignalPath, "r") as file:
|
|
296
294
|
cdh_content = file.readlines()
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
295
|
+
|
|
296
|
+
cdf_path = AOsignalPath.replace(".cdh", ".cdf")
|
|
297
|
+
|
|
298
|
+
# Extraire les paramètres depuis le fichier .cdh
|
|
299
|
+
n_scans = int([line.split(":")[1].strip() for line in cdh_content if "Number of events" in line][0])
|
|
300
|
+
n_acquisitions_per_event = int([line.split(":")[1].strip() for line in cdh_content if "Number of acquisitions per event" in line][0])
|
|
301
|
+
num_elements = int([line.split(":")[1].strip() for line in cdh_content if "Number of US transducers" in line][0])
|
|
302
|
+
|
|
303
|
+
# Initialisation des structures
|
|
304
|
+
AO_signal = np.zeros((n_acquisitions_per_event, n_scans), dtype=np.float32)
|
|
305
|
+
active_lists = []
|
|
306
|
+
angles = []
|
|
307
|
+
|
|
308
|
+
# Lecture du fichier binaire
|
|
309
|
+
with open(cdf_path, "rb") as file:
|
|
310
|
+
for j in trange(n_scans, desc="Lecture des événements"):
|
|
311
|
+
# Lire l'activeList : 48 caractères hex = 24 bytes
|
|
312
|
+
active_list_bytes = file.read(24)
|
|
313
|
+
active_list_hex = active_list_bytes.hex()
|
|
314
|
+
active_lists.append(active_list_hex)
|
|
315
|
+
|
|
316
|
+
# Lire l'angle (1 byte signé)
|
|
317
|
+
angle_byte = file.read(1)
|
|
318
|
+
angle = np.frombuffer(angle_byte, dtype=np.int8)[0]
|
|
319
|
+
angles.append(angle)
|
|
320
|
+
|
|
321
|
+
# Lire le signal AO (float32)
|
|
322
|
+
data = np.frombuffer(file.read(n_acquisitions_per_event * 4), dtype=np.float32)
|
|
323
|
+
if len(data) != n_acquisitions_per_event:
|
|
324
|
+
raise ValueError(f"Erreur à l'événement {j} : attendu {n_acquisitions_per_event}, obtenu {len(data)}")
|
|
325
|
+
AO_signal[:, j] = data
|
|
326
|
+
|
|
327
|
+
return AO_signal
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
elif AOsignalPath.endswith(".npy"):
|
|
331
|
+
return np.load(AOsignalPath) # Supposé déjà au bon format
|
|
332
|
+
else:
|
|
333
|
+
raise ValueError("Format de fichier non supporté. Utilisez .cdh/.cdf ou .npy.")
|
|
315
334
|
|
|
316
335
|
def saveAOsignals_Castor(self, save_directory, withTumor=True):
|
|
317
336
|
if withTumor:
|
|
@@ -339,10 +358,10 @@ class Experiment(ABC):
|
|
|
339
358
|
header_content = (
|
|
340
359
|
f"Data filename: {'AOSignals_withTumor.cdf' if withTumor else 'AOSignals_withoutTumor.cdf'}\n"
|
|
341
360
|
f"Number of events: {nScan}\n"
|
|
342
|
-
f"Number of acquisitions per event: {AO_signal.shape[
|
|
361
|
+
f"Number of acquisitions per event: {AO_signal.shape[0]}\n"
|
|
343
362
|
f"Start time (s): 0\n"
|
|
344
363
|
f"Duration (s): 1\n"
|
|
345
|
-
f"Acquisition frequency (Hz): {
|
|
364
|
+
f"Acquisition frequency (Hz): {self.params.acoustic['f_saving']}\n"
|
|
346
365
|
f"Data mode: histogram\n"
|
|
347
366
|
f"Data type: AOT\n"
|
|
348
367
|
f"Number of US transducers: {self.params.acoustic['num_elements']}"
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from AOT_biomaps.AOT_Recon.ReconEnums import PotentialType
|
|
2
|
-
from AOT_biomaps.AOT_Recon.ReconTools import _build_adjacency_sparse
|
|
2
|
+
from AOT_biomaps.AOT_Recon.ReconTools import _build_adjacency_sparse, calculate_memory_requirement, check_gpu_memory
|
|
3
3
|
from AOT_biomaps.Config import config
|
|
4
|
+
|
|
5
|
+
import warnings
|
|
4
6
|
import numpy as np
|
|
5
7
|
import torch
|
|
6
8
|
from tqdm import trange
|
|
@@ -11,9 +13,42 @@ if config.get_process() == 'gpu':
|
|
|
11
13
|
except ImportError:
|
|
12
14
|
raise ImportError("torch_scatter and torch_sparse are required for GPU processing. Please install them using 'pip install torch-scatter torch-sparse' with correct link (follow instructions https://github.com/LucasDuclos/AcoustoOpticTomography/edit/main/README.md).")
|
|
13
15
|
|
|
14
|
-
def
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
def DEPIERRO(
|
|
17
|
+
SMatrix,
|
|
18
|
+
y,
|
|
19
|
+
numIterations,
|
|
20
|
+
beta,
|
|
21
|
+
sigma,
|
|
22
|
+
isSavingEachIteration,
|
|
23
|
+
withTumor,
|
|
24
|
+
max_saves,
|
|
25
|
+
show_logs):
|
|
26
|
+
"""
|
|
27
|
+
This method implements the DEPIERRO algorithm using either CPU or single-GPU PyTorch acceleration.
|
|
28
|
+
Multi-GPU and Multi-CPU modes are not implemented for this algorithm.
|
|
29
|
+
"""
|
|
30
|
+
try:
|
|
31
|
+
tumor_str = "WITH" if withTumor else "WITHOUT"
|
|
32
|
+
# Auto-select device and method
|
|
33
|
+
if device is None:
|
|
34
|
+
if torch.cuda.is_available() and check_gpu_memory(config.select_best_gpu(), calculate_memory_requirement(SMatrix, y), show_logs=show_logs):
|
|
35
|
+
device = torch.device(f"cuda:{config.select_best_gpu()}")
|
|
36
|
+
use_gpu = True
|
|
37
|
+
else:
|
|
38
|
+
device = torch.device("cpu")
|
|
39
|
+
use_gpu = False
|
|
40
|
+
else:
|
|
41
|
+
use_gpu = device.type == "cuda"
|
|
42
|
+
# Dispatch to the appropriate implementation
|
|
43
|
+
if use_gpu:
|
|
44
|
+
return _DEPIERRO_GPU(SMatrix, y, numIterations, beta, sigma, isSavingEachIteration, tumor_str, device, max_saves, show_logs)
|
|
45
|
+
else:
|
|
46
|
+
return _DEPIERRO_CPU(SMatrix, y, numIterations, beta, sigma, isSavingEachIteration, tumor_str, device, max_saves, show_logs)
|
|
47
|
+
except Exception as e:
|
|
48
|
+
print(f"Error in MLEM: {type(e).__name__}: {e}")
|
|
49
|
+
return None, None
|
|
50
|
+
|
|
51
|
+
def _DEPIERRO_GPU(SMatrix, y, numIterations, beta, sigma, isSavingEachIteration, tumor_str, device, max_saves, show_logs=True):
|
|
17
52
|
# Conversion des données en tenseurs PyTorch (float64)
|
|
18
53
|
A_matrix_torch = torch.tensor(SMatrix, dtype=torch.float64, device=device)
|
|
19
54
|
y_torch = torch.tensor(y, dtype=torch.float64, device=device)
|
|
@@ -33,7 +68,7 @@ def _DEPIERRO_GPU(SMatrix, y, numIterations, beta, sigma, isSavingEachIteration,
|
|
|
33
68
|
# Construction de la matrice d'adjacence
|
|
34
69
|
adj_index, adj_values = _build_adjacency_sparse(Z, X, device=device, dtype=torch.float64)
|
|
35
70
|
# Description pour la barre de progression
|
|
36
|
-
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: DE PIERRO (Sparse QUADRATIC β:{beta:.4f}, σ:{sigma:.4f}) ---- {
|
|
71
|
+
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: DE PIERRO (Sparse QUADRATIC β:{beta:.4f}, σ:{sigma:.4f}) ---- {tumor_str} TUMOR ---- processing on single GPU no.{torch.cuda.current_device()}"
|
|
37
72
|
# Configuration pour la sauvegarde des itérations
|
|
38
73
|
saved_indices = [0]
|
|
39
74
|
|
|
@@ -47,7 +82,8 @@ def _DEPIERRO_GPU(SMatrix, y, numIterations, beta, sigma, isSavingEachIteration,
|
|
|
47
82
|
save_indices.append(numIterations - 1)
|
|
48
83
|
|
|
49
84
|
# Boucle principale MAP-EM
|
|
50
|
-
|
|
85
|
+
iterator = trange(numIterations, desc=description) if show_logs else range(numIterations)
|
|
86
|
+
for it in iterator:
|
|
51
87
|
theta_p = matrix_theta_torch[-1]
|
|
52
88
|
theta_p_flat = theta_p.reshape(-1)
|
|
53
89
|
# Étape 1 : Projection avant
|
|
@@ -92,7 +128,7 @@ def _DEPIERRO_GPU(SMatrix, y, numIterations, beta, sigma, isSavingEachIteration,
|
|
|
92
128
|
else:
|
|
93
129
|
return matrix_theta_torch[-1].cpu().numpy(), None
|
|
94
130
|
|
|
95
|
-
def _DEPIERRO_CPU(SMatrix, y, numIterations, beta, sigma, isSavingEachIteration,
|
|
131
|
+
def _DEPIERRO_CPU(SMatrix, y, numIterations, beta, sigma, isSavingEachIteration, tumor_str, device, max_saves, show_logs=True):
|
|
96
132
|
try:
|
|
97
133
|
if beta is None or sigma is None:
|
|
98
134
|
raise ValueError("Depierro95 optimizer requires beta and sigma parameters.")
|
|
@@ -120,9 +156,10 @@ def _DEPIERRO_CPU(SMatrix, y, numIterations, beta, sigma, isSavingEachIteration,
|
|
|
120
156
|
if save_indices[-1] != numIterations - 1:
|
|
121
157
|
save_indices.append(numIterations - 1)
|
|
122
158
|
|
|
123
|
-
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: DE PIERRO (Sparse QUADRATIC β:{beta:.4f}, σ:{sigma:.4f}) ---- {
|
|
159
|
+
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: DE PIERRO (Sparse QUADRATIC β:{beta:.4f}, σ:{sigma:.4f}) ---- {tumor_str} TUMOR ---- processing on single CPU ----"
|
|
124
160
|
|
|
125
|
-
|
|
161
|
+
iterator = trange(numIterations, desc=description) if show_logs else range(numIterations)
|
|
162
|
+
for it in iterator:
|
|
126
163
|
theta_p = matrix_theta[-1]
|
|
127
164
|
theta_p_flat = theta_p.reshape(-1)
|
|
128
165
|
q_flat = np.dot(A_flat, theta_p_flat)
|
|
@@ -141,9 +178,9 @@ def _DEPIERRO_CPU(SMatrix, y, numIterations, beta, sigma, isSavingEachIteration,
|
|
|
141
178
|
theta_p_plus_1_flat = np.clip(theta_p_plus_1_flat, a_min=0, a_max=None)
|
|
142
179
|
theta_next = theta_p_plus_1_flat.reshape(Z, X)
|
|
143
180
|
matrix_theta[-1] = theta_next
|
|
144
|
-
if isSavingEachIteration and
|
|
181
|
+
if isSavingEachIteration and it in save_indices:
|
|
145
182
|
I_reconMatrix.append(theta_next.copy())
|
|
146
|
-
saved_indices.append(
|
|
183
|
+
saved_indices.append(it)
|
|
147
184
|
|
|
148
185
|
if isSavingEachIteration:
|
|
149
186
|
return I_reconMatrix, saved_indices
|
|
@@ -2,6 +2,7 @@ from AOT_biomaps.Config import config
|
|
|
2
2
|
import torch
|
|
3
3
|
import numpy as np
|
|
4
4
|
from tqdm import trange
|
|
5
|
+
from AOT_biomaps.AOT_Recon.ReconTools import calculate_memory_requirement, check_gpu_memory
|
|
5
6
|
|
|
6
7
|
def LS(
|
|
7
8
|
SMatrix,
|
|
@@ -12,6 +13,7 @@ def LS(
|
|
|
12
13
|
withTumor=True,
|
|
13
14
|
device=None,
|
|
14
15
|
max_saves=5000,
|
|
16
|
+
show_logs=True
|
|
15
17
|
):
|
|
16
18
|
"""
|
|
17
19
|
Least Squares reconstruction using Projected Gradient Descent (PGD) with non-negativity constraint.
|
|
@@ -20,15 +22,15 @@ def LS(
|
|
|
20
22
|
tumor_str = "WITH" if withTumor else "WITHOUT"
|
|
21
23
|
# Force GPU usage for now
|
|
22
24
|
if device is None:
|
|
23
|
-
if
|
|
25
|
+
if torch.cuda.is_available() and check_gpu_memory(config.select_best_gpu(), calculate_memory_requirement(SMatrix, y), show_logs=show_logs):
|
|
24
26
|
raise RuntimeError("CUDA is required for this implementation.")
|
|
25
27
|
device = torch.device(f"cuda:{config.select_best_gpu()}")
|
|
26
28
|
else:
|
|
27
29
|
if device.type != "cuda":
|
|
28
30
|
raise RuntimeError("Only GPU implementation is available for now.")
|
|
29
|
-
return _LS_GPU_stable(SMatrix, y, numIterations, alpha, isSavingEachIteration, tumor_str, max_saves)
|
|
31
|
+
return _LS_GPU_stable(SMatrix, y, numIterations, alpha, isSavingEachIteration, tumor_str, max_saves, show_logs=show_logs)
|
|
30
32
|
|
|
31
|
-
def _LS_GPU_stable(SMatrix, y, numIterations, alpha, isSavingEachIteration, tumor_str, max_saves=5000):
|
|
33
|
+
def _LS_GPU_stable(SMatrix, y, numIterations, alpha, isSavingEachIteration, tumor_str, max_saves=5000, show_logs=True):
|
|
32
34
|
"""
|
|
33
35
|
Stable GPU implementation of LS using projected gradient descent with diagonal preconditioner.
|
|
34
36
|
"""
|
|
@@ -65,13 +67,14 @@ def _LS_GPU_stable(SMatrix, y, numIterations, alpha, isSavingEachIteration, tumo
|
|
|
65
67
|
AT_r = torch.empty(ZX, device=device)
|
|
66
68
|
description = f"AOT-BioMaps -- Stable LS Reconstruction ---- {tumor_str} TUMOR ---- GPU {torch.cuda.current_device()}"
|
|
67
69
|
|
|
68
|
-
|
|
70
|
+
iterator = trange(numIterations, desc=description) if show_logs else range(numIterations)
|
|
71
|
+
for it in iterator:
|
|
69
72
|
# Calcul du résidu (inplace)
|
|
70
73
|
torch.matmul(A_flat, lambda_k, out=r_k)
|
|
71
74
|
r_k = y_flat - r_k
|
|
72
|
-
if isSavingEachIteration and
|
|
75
|
+
if isSavingEachIteration and it in save_indices:
|
|
73
76
|
lambda_history.append(lambda_k.clone().reshape(Z, X) * (norm_y / norm_A))
|
|
74
|
-
saved_indices.append(
|
|
77
|
+
saved_indices.append(it)
|
|
75
78
|
|
|
76
79
|
# Gradient préconditionné (inplace)
|
|
77
80
|
torch.matmul(A_flat.T, r_k, out=AT_r)
|
|
@@ -2,13 +2,94 @@ from AOT_biomaps.AOT_Recon.ReconEnums import PotentialType
|
|
|
2
2
|
from AOT_biomaps.AOT_Recon.AOT_PotentialFunctions.Quadratic import _Omega_QUADRATIC_CPU, _Omega_QUADRATIC_GPU
|
|
3
3
|
from AOT_biomaps.AOT_Recon.AOT_PotentialFunctions.RelativeDifferences import _Omega_RELATIVE_DIFFERENCE_CPU, _Omega_RELATIVE_DIFFERENCE_GPU
|
|
4
4
|
from AOT_biomaps.AOT_Recon.AOT_PotentialFunctions.Huber import _Omega_HUBER_PIECEWISE_CPU, _Omega_HUBER_PIECEWISE_GPU
|
|
5
|
-
from AOT_biomaps.AOT_Recon.ReconTools import _build_adjacency_sparse
|
|
5
|
+
from AOT_biomaps.AOT_Recon.ReconTools import _build_adjacency_sparse, check_gpu_memory, calculate_memory_requirement
|
|
6
6
|
from AOT_biomaps.Config import config
|
|
7
|
+
|
|
8
|
+
import warnings
|
|
7
9
|
import numpy as np
|
|
8
10
|
import torch
|
|
9
11
|
from tqdm import trange
|
|
10
12
|
|
|
11
|
-
def
|
|
13
|
+
def MAPEM(
|
|
14
|
+
SMatrix,
|
|
15
|
+
y,
|
|
16
|
+
Omega,
|
|
17
|
+
beta,
|
|
18
|
+
delta=None,
|
|
19
|
+
gamma=None,
|
|
20
|
+
sigma=None,
|
|
21
|
+
numIterations=100,
|
|
22
|
+
isSavingEachIteration=True,
|
|
23
|
+
withTumor=True,
|
|
24
|
+
device=None,
|
|
25
|
+
max_saves=5000,
|
|
26
|
+
show_logs=True):
|
|
27
|
+
"""
|
|
28
|
+
This method implements the MAPEM algorithm using either CPU or single-GPU PyTorch acceleration.
|
|
29
|
+
Multi-GPU and Multi-CPU modes are not implemented for this algorithm.
|
|
30
|
+
"""
|
|
31
|
+
try:
|
|
32
|
+
tumor_str = "WITH" if withTumor else "WITHOUT"
|
|
33
|
+
# Auto-select device and method
|
|
34
|
+
if device is None:
|
|
35
|
+
if torch.cuda.is_available() and check_gpu_memory(config.select_best_gpu(), calculate_memory_requirement(SMatrix, y), show_logs=show_logs):
|
|
36
|
+
device = torch.device(f"cuda:{config.select_best_gpu()}")
|
|
37
|
+
use_gpu = True
|
|
38
|
+
else:
|
|
39
|
+
device = torch.device("cpu")
|
|
40
|
+
use_gpu = False
|
|
41
|
+
else:
|
|
42
|
+
use_gpu = device.type == "cuda"
|
|
43
|
+
# Dispatch to the appropriate implementation
|
|
44
|
+
if use_gpu:
|
|
45
|
+
return _MAPEM_GPU(SMatrix, y, Omega, beta, delta, gamma, sigma, numIterations, isSavingEachIteration, tumor_str, device, max_saves, show_logs=True)
|
|
46
|
+
else:
|
|
47
|
+
return _MAPEM_CPU(SMatrix, y, Omega, beta, delta, gamma, sigma, numIterations, isSavingEachIteration, tumor_str, max_saves, show_logs=True)
|
|
48
|
+
except Exception as e:
|
|
49
|
+
print(f"Error in MLEM: {type(e).__name__}: {e}")
|
|
50
|
+
return None, None
|
|
51
|
+
|
|
52
|
+
def MAPEM_STOP(
|
|
53
|
+
SMatrix,
|
|
54
|
+
y,
|
|
55
|
+
Omega,
|
|
56
|
+
beta,
|
|
57
|
+
delta=None,
|
|
58
|
+
gamma=None,
|
|
59
|
+
sigma=None,
|
|
60
|
+
numIterations=100,
|
|
61
|
+
isSavingEachIteration=True,
|
|
62
|
+
withTumor=True,
|
|
63
|
+
device=None,
|
|
64
|
+
max_saves=5000,
|
|
65
|
+
show_logs=True):
|
|
66
|
+
"""
|
|
67
|
+
This method implements the MAPEM_STOP algorithm using either CPU or single-GPU PyTorch acceleration.
|
|
68
|
+
Multi-GPU and Multi-CPU modes are not implemented for this algorithm.
|
|
69
|
+
"""
|
|
70
|
+
try:
|
|
71
|
+
tumor_str = "WITH" if withTumor else "WITHOUT"
|
|
72
|
+
# Auto-select device and method
|
|
73
|
+
if device is None:
|
|
74
|
+
if torch.cuda.is_available() and check_gpu_memory(config.select_best_gpu(), calculate_memory_requirement(SMatrix, y), show_logs=show_logs):
|
|
75
|
+
device = torch.device(f"cuda:{config.select_best_gpu()}")
|
|
76
|
+
use_gpu = True
|
|
77
|
+
else:
|
|
78
|
+
device = torch.device("cpu")
|
|
79
|
+
use_gpu = False
|
|
80
|
+
else:
|
|
81
|
+
use_gpu = device.type == "cuda"
|
|
82
|
+
# Dispatch to the appropriate implementation
|
|
83
|
+
if use_gpu:
|
|
84
|
+
return _MAPEM_GPU_STOP(SMatrix, y, Omega, beta, delta, gamma, sigma, numIterations, isSavingEachIteration, tumor_str, device, max_saves, show_logs=True)
|
|
85
|
+
else:
|
|
86
|
+
return _MAPEM_CPU_STOP(SMatrix, y, Omega, beta, delta, gamma, sigma, numIterations, isSavingEachIteration, tumor_str, max_saves, show_logs=True)
|
|
87
|
+
except Exception as e:
|
|
88
|
+
print(f"Error in MLEM: {type(e).__name__}: {e}")
|
|
89
|
+
return None, None
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _MAPEM_CPU_STOP(SMatrix, y, Omega, beta, delta, gamma, sigma, numIterations, isSavingEachIteration, tumor_str, max_saves, show_logs=True):
|
|
12
93
|
"""
|
|
13
94
|
MAPEM version CPU simple - sans GPU - torch uniquement
|
|
14
95
|
"""
|
|
@@ -42,7 +123,6 @@ def _MAPEM_CPU_STOP(SMatrix, y, Omega, numIterations, beta, delta, gamma, sigma,
|
|
|
42
123
|
theta_list = [I_0]
|
|
43
124
|
results = [I_0.numpy()]
|
|
44
125
|
saved_indices = [0]
|
|
45
|
-
previous = -np.inf
|
|
46
126
|
normalization_factor = SMatrix.sum(dim=(0, 3)).reshape(-1)
|
|
47
127
|
adj_index, adj_values = _build_adjacency_sparse(Z, X)
|
|
48
128
|
|
|
@@ -56,13 +136,14 @@ def _MAPEM_CPU_STOP(SMatrix, y, Omega, numIterations, beta, delta, gamma, sigma,
|
|
|
56
136
|
save_indices.append(numIterations - 1)
|
|
57
137
|
|
|
58
138
|
if Omega == PotentialType.HUBER_PIECEWISE:
|
|
59
|
-
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: MAP-EM (Sparse HUBER β:{beta:.4f}, δ:{delta:.4f}) + STOP condition (penalized log-likelihood) ---- {
|
|
139
|
+
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: MAP-EM (Sparse HUBER β:{beta:.4f}, δ:{delta:.4f}) + STOP condition (penalized log-likelihood) ---- {tumor_str} TUMOR ---- processing on single CPU ----"
|
|
60
140
|
elif Omega == PotentialType.RELATIVE_DIFFERENCE:
|
|
61
|
-
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: MAP-EM (Sparse RD β:{beta:.4f}, γ:{gamma:.4f}) + STOP condition (penalized log-likelihood) ---- {
|
|
141
|
+
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: MAP-EM (Sparse RD β:{beta:.4f}, γ:{gamma:.4f}) + STOP condition (penalized log-likelihood) ---- {tumor_str} TUMOR ---- processing on single CPU ----"
|
|
62
142
|
elif Omega == PotentialType.QUADRATIC:
|
|
63
|
-
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: MAP-EM (Sparse QUADRATIC β:{beta:.4f}, σ:{sigma:.4f}) + STOP condition (penalized log-likelihood) ---- {
|
|
143
|
+
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: MAP-EM (Sparse QUADRATIC β:{beta:.4f}, σ:{sigma:.4f}) + STOP condition (penalized log-likelihood) ---- {tumor_str} TUMOR ---- processing on single CPU ----"
|
|
64
144
|
|
|
65
|
-
|
|
145
|
+
iterator = trange(numIterations, desc=description) if show_logs else range(numIterations)
|
|
146
|
+
for it in iterator:
|
|
66
147
|
theta_p = theta_list[-1]
|
|
67
148
|
theta_p_flat = theta_p.reshape(-1)
|
|
68
149
|
q_flat = A_flat @ theta_p_flat
|
|
@@ -80,14 +161,13 @@ def _MAPEM_CPU_STOP(SMatrix, y, Omega, numIterations, beta, delta, gamma, sigma,
|
|
|
80
161
|
theta_next_flat = torch.clamp(theta_next_flat, min=0)
|
|
81
162
|
theta_next = theta_next_flat.reshape(Z, X)
|
|
82
163
|
theta_list[-1] = theta_next
|
|
83
|
-
if isSavingEachIteration and
|
|
164
|
+
if isSavingEachIteration and it in save_indices:
|
|
84
165
|
results.append(theta_next.numpy())
|
|
85
|
-
saved_indices.append(
|
|
166
|
+
saved_indices.append(it+1)
|
|
86
167
|
log_likelihood = (y_flat * torch.log(q_flat + 1e-8) - (q_flat + 1e-8)).sum()
|
|
87
168
|
penalized_log_likelihood = log_likelihood - beta * U_value
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
print(f"Iter {p+1}: logL={log_likelihood:.3e}, U={U_value:.3e}, penalized logL={penalized_log_likelihood:.3e}")
|
|
169
|
+
if (it + 1) % 100 == 0:
|
|
170
|
+
print(f"Iter {it+1}: logL={log_likelihood:.3e}, U={U_value:.3e}, penalized logL={penalized_log_likelihood:.3e}")
|
|
91
171
|
|
|
92
172
|
if isSavingEachIteration:
|
|
93
173
|
return results, saved_indices
|
|
@@ -97,7 +177,7 @@ def _MAPEM_CPU_STOP(SMatrix, y, Omega, numIterations, beta, delta, gamma, sigma,
|
|
|
97
177
|
print(f"An error occurred in _MAPEM_CPU_STOP: {e}")
|
|
98
178
|
return None, None
|
|
99
179
|
|
|
100
|
-
def _MAPEM_GPU_STOP(SMatrix, y, Omega,
|
|
180
|
+
def _MAPEM_GPU_STOP(SMatrix, y, Omega, beta, delta, gamma, sigma, numIterations, isSavingEachIteration, tumor_str, device, max_saves, show_logs=True):
|
|
101
181
|
"""
|
|
102
182
|
Maximum A Posteriori (MAP) estimation for Bayesian reconstruction.
|
|
103
183
|
This method computes the MAP estimate of the parameters given the data.
|
|
@@ -123,7 +203,6 @@ def _MAPEM_GPU_STOP(SMatrix, y, Omega, numIterations, beta, delta, gamma, sigma,
|
|
|
123
203
|
else:
|
|
124
204
|
raise ValueError(f"Unknown potential type: {Omega}")
|
|
125
205
|
|
|
126
|
-
device = torch.device(f"cuda:{config.select_best_gpu()}")
|
|
127
206
|
A_matrix_torch = torch.tensor(SMatrix, dtype=torch.float32).to(device)
|
|
128
207
|
y_torch = torch.tensor(y, dtype=torch.float32).to(device)
|
|
129
208
|
T, Z, X, N = SMatrix.shape
|
|
@@ -150,13 +229,14 @@ def _MAPEM_GPU_STOP(SMatrix, y, Omega, numIterations, beta, delta, gamma, sigma,
|
|
|
150
229
|
save_indices.append(numIterations - 1)
|
|
151
230
|
|
|
152
231
|
if Omega == PotentialType.HUBER_PIECEWISE:
|
|
153
|
-
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: MAP-EM (Sparse HUBER β:{beta:.4f}, δ:{delta:.4f}) + STOP condition (penalized log-likelihood) ---- {
|
|
232
|
+
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: MAP-EM (Sparse HUBER β:{beta:.4f}, δ:{delta:.4f}) + STOP condition (penalized log-likelihood) ---- {tumor_str} TUMOR ---- processing on single GPU no.{torch.cuda.current_device()} ----"
|
|
154
233
|
elif Omega == PotentialType.RELATIVE_DIFFERENCE:
|
|
155
|
-
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: MAP-EM (Sparse RD β:{beta:.4f}, γ:{gamma:.4f}) + STOP condition (penalized log-likelihood) ---- {
|
|
234
|
+
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: MAP-EM (Sparse RD β:{beta:.4f}, γ:{gamma:.4f}) + STOP condition (penalized log-likelihood) ---- {tumor_str} TUMOR ---- processing on single GPU no.{torch.cuda.current_device()} ----"
|
|
156
235
|
elif Omega == PotentialType.QUADRATIC:
|
|
157
|
-
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: MAP-EM (Sparse QUADRATIC β:{beta:.4f}, σ:{sigma:.4f}) + STOP condition (penalized log-likelihood) ---- {
|
|
236
|
+
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: MAP-EM (Sparse QUADRATIC β:{beta:.4f}, σ:{sigma:.4f}) + STOP condition (penalized log-likelihood) ---- {tumor_str} TUMOR ---- processing on single GPU no.{torch.cuda.current_device()} ----"
|
|
158
237
|
|
|
159
|
-
|
|
238
|
+
iterator = trange(numIterations, desc=description) if show_logs else range(numIterations)
|
|
239
|
+
for it in iterator:
|
|
160
240
|
theta_p = matrix_theta_torch[-1]
|
|
161
241
|
theta_p_flat = theta_p.reshape(-1)
|
|
162
242
|
q_flat = A_flat @ theta_p_flat
|
|
@@ -176,18 +256,18 @@ def _MAPEM_GPU_STOP(SMatrix, y, Omega, numIterations, beta, delta, gamma, sigma,
|
|
|
176
256
|
theta_p_plus_1_flat = torch.clamp(theta_p_plus_1_flat, min=0)
|
|
177
257
|
theta_next = theta_p_plus_1_flat.reshape(Z, X)
|
|
178
258
|
matrix_theta_torch[-1] = theta_next
|
|
179
|
-
if isSavingEachIteration and
|
|
259
|
+
if isSavingEachIteration and it in save_indices:
|
|
180
260
|
matrix_theta_from_gpu_MAPEM.append(theta_next.cpu().numpy())
|
|
181
|
-
saved_indices.append(
|
|
261
|
+
saved_indices.append(it+1)
|
|
182
262
|
log_likelihood = (y_flat * (torch.log(q_flat + torch.finfo(torch.float32).tiny)) - (q_flat + torch.finfo(torch.float32).tiny)).sum()
|
|
183
263
|
penalized_log_likelihood = log_likelihood - beta * U_value
|
|
184
|
-
if
|
|
264
|
+
if it == 0 or (it + 1) % 100 == 0:
|
|
185
265
|
current = penalized_log_likelihood.item()
|
|
186
266
|
if current <= previous:
|
|
187
267
|
nb_false_successive += 1
|
|
188
268
|
else:
|
|
189
269
|
nb_false_successive = 0
|
|
190
|
-
print(f"Iter {
|
|
270
|
+
print(f"Iter {it + 1}: lnL without term ln(m_i !) inside={log_likelihood.item():.8e}, Gibbs energy function U={U_value.item():.4e}, penalized lnL without term ln(m_i !) inside={penalized_log_likelihood.item():.8e}, p lnL (current {current:.8e} - previous {previous:.8e} > 0)={(current - previous > 0)}, nb_false_successive={nb_false_successive}")
|
|
191
271
|
previous = current
|
|
192
272
|
|
|
193
273
|
del A_matrix_torch, y_torch, A_flat, y_flat, I_0, normalization_factor, normalization_factor_flat
|
|
@@ -202,7 +282,7 @@ def _MAPEM_GPU_STOP(SMatrix, y, Omega, numIterations, beta, delta, gamma, sigma,
|
|
|
202
282
|
torch.cuda.empty_cache()
|
|
203
283
|
return None, None
|
|
204
284
|
|
|
205
|
-
def _MAPEM_CPU(SMatrix, y, Omega,
|
|
285
|
+
def _MAPEM_CPU(SMatrix, y, Omega, beta, delta, gamma, sigma, numIterations, isSavingEachIteration, tumor_str, max_saves, show_logs=True):
|
|
206
286
|
try:
|
|
207
287
|
if not isinstance(Omega, PotentialType):
|
|
208
288
|
raise TypeError(f"Omega must be of type PotentialType, got {type(Omega)}")
|
|
@@ -225,7 +305,6 @@ def _MAPEM_CPU(SMatrix, y, Omega, numIterations, beta, delta, gamma, sigma, isSa
|
|
|
225
305
|
raise ValueError(f"Unknown potential type: {Omega}")
|
|
226
306
|
|
|
227
307
|
T, Z, X, N = SMatrix.shape
|
|
228
|
-
J = Z * X
|
|
229
308
|
A_flat = np.transpose(SMatrix, (0, 3, 1, 2)).reshape(T * N, Z * X)
|
|
230
309
|
y_flat = y.reshape(-1)
|
|
231
310
|
theta_0 = np.ones((Z, X), dtype=np.float32)
|
|
@@ -246,13 +325,14 @@ def _MAPEM_CPU(SMatrix, y, Omega, numIterations, beta, delta, gamma, sigma, isSa
|
|
|
246
325
|
save_indices.append(numIterations - 1)
|
|
247
326
|
|
|
248
327
|
if Omega == PotentialType.HUBER_PIECEWISE:
|
|
249
|
-
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: MAP-EM (Sparse HUBER β:{beta:.4f}, δ:{delta:.4f}) ---- {
|
|
328
|
+
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: MAP-EM (Sparse HUBER β:{beta:.4f}, δ:{delta:.4f}) ---- {tumor_str} TUMOR ---- processing on single CPU ----"
|
|
250
329
|
elif Omega == PotentialType.RELATIVE_DIFFERENCE:
|
|
251
|
-
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: MAP-EM (Sparse RD β:{beta:.4f}, γ:{gamma:.4f}) ---- {
|
|
330
|
+
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: MAP-EM (Sparse RD β:{beta:.4f}, γ:{gamma:.4f}) ---- {tumor_str} TUMOR ---- processing on single CPU ----"
|
|
252
331
|
elif Omega == PotentialType.QUADRATIC:
|
|
253
|
-
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: MAP-EM (Sparse QUADRATIC β:{beta:.4f}, σ:{sigma:.4f}) ---- {
|
|
332
|
+
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: MAP-EM (Sparse QUADRATIC β:{beta:.4f}, σ:{sigma:.4f}) ---- {tumor_str} TUMOR ---- processing on single CPU ----"
|
|
254
333
|
|
|
255
|
-
|
|
334
|
+
iterator = trange(numIterations, desc=description) if show_logs else range(numIterations)
|
|
335
|
+
for it in iterator:
|
|
256
336
|
theta_p = matrix_theta_np[-1]
|
|
257
337
|
theta_p_flat = theta_p.reshape(-1)
|
|
258
338
|
q_flat = A_flat @ theta_p_flat
|
|
@@ -270,9 +350,9 @@ def _MAPEM_CPU(SMatrix, y, Omega, numIterations, beta, delta, gamma, sigma, isSa
|
|
|
270
350
|
theta_p_plus_1_flat = np.clip(theta_p_plus_1_flat, 0, None)
|
|
271
351
|
theta_next = theta_p_plus_1_flat.reshape(Z, X)
|
|
272
352
|
matrix_theta_np.append(theta_next)
|
|
273
|
-
if isSavingEachIteration and
|
|
353
|
+
if isSavingEachIteration and it in save_indices:
|
|
274
354
|
I_reconMatrix.append(theta_next.copy())
|
|
275
|
-
saved_indices.append(
|
|
355
|
+
saved_indices.append(it+1)
|
|
276
356
|
|
|
277
357
|
if isSavingEachIteration:
|
|
278
358
|
return I_reconMatrix, saved_indices
|
|
@@ -282,7 +362,7 @@ def _MAPEM_CPU(SMatrix, y, Omega, numIterations, beta, delta, gamma, sigma, isSa
|
|
|
282
362
|
print(f"An error occurred in _MAPEM_CPU: {e}")
|
|
283
363
|
return None, None
|
|
284
364
|
|
|
285
|
-
def _MAPEM_GPU(SMatrix, y, Omega,
|
|
365
|
+
def _MAPEM_GPU(SMatrix, y, Omega, beta, delta, gamma, sigma, numIterations, isSavingEachIteration, tumor_str, device, max_saves, show_logs=True):
|
|
286
366
|
"""
|
|
287
367
|
Maximum A Posteriori (MAP) estimation for Bayesian reconstruction using GPU.
|
|
288
368
|
This method computes the MAP estimate of the parameters given the data.
|
|
@@ -308,7 +388,6 @@ def _MAPEM_GPU(SMatrix, y, Omega, numIterations, beta, delta, gamma, sigma, isSa
|
|
|
308
388
|
else:
|
|
309
389
|
raise ValueError(f"Unknown potential type: {Omega}")
|
|
310
390
|
|
|
311
|
-
device = torch.device(f"cuda:{config.select_best_gpu()}")
|
|
312
391
|
A_matrix_torch = torch.tensor(SMatrix, dtype=torch.float32).to(device)
|
|
313
392
|
y_torch = torch.tensor(y, dtype=torch.float32).to(device)
|
|
314
393
|
T, Z, X, N = SMatrix.shape
|
|
@@ -333,13 +412,14 @@ def _MAPEM_GPU(SMatrix, y, Omega, numIterations, beta, delta, gamma, sigma, isSa
|
|
|
333
412
|
save_indices.append(numIterations - 1)
|
|
334
413
|
|
|
335
414
|
if Omega == PotentialType.HUBER_PIECEWISE:
|
|
336
|
-
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: MAP-EM (Sparse HUBER β:{beta:.4f}, δ:{delta:.4f}) ---- {
|
|
415
|
+
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: MAP-EM (Sparse HUBER β:{beta:.4f}, δ:{delta:.4f}) ---- {tumor_str} TUMOR ---- processing on single GPU no.{torch.cuda.current_device()} ----"
|
|
337
416
|
elif Omega == PotentialType.RELATIVE_DIFFERENCE:
|
|
338
|
-
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: MAP-EM (Sparse RD β:{beta:.4f}, γ:{gamma:.4f}) ---- {
|
|
417
|
+
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: MAP-EM (Sparse RD β:{beta:.4f}, γ:{gamma:.4f}) ---- {tumor_str} TUMOR ---- processing on single GPU no.{torch.cuda.current_device()} ----"
|
|
339
418
|
elif Omega == PotentialType.QUADRATIC:
|
|
340
|
-
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: MAP-EM (Sparse QUADRATIC σ:{sigma:.4f}) ---- {
|
|
419
|
+
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: MAP-EM (Sparse QUADRATIC σ:{sigma:.4f}) ---- {tumor_str} TUMOR ---- processing on single GPU no.{torch.cuda.current_device()} ----"
|
|
341
420
|
|
|
342
|
-
|
|
421
|
+
iterator = trange(numIterations, desc=description) if show_logs else range(numIterations)
|
|
422
|
+
for it in iterator:
|
|
343
423
|
theta_p = matrix_theta_torch[-1]
|
|
344
424
|
theta_p_flat = theta_p.reshape(-1)
|
|
345
425
|
q_flat = A_flat @ theta_p_flat
|
|
@@ -359,9 +439,9 @@ def _MAPEM_GPU(SMatrix, y, Omega, numIterations, beta, delta, gamma, sigma, isSa
|
|
|
359
439
|
theta_p_plus_1_flat = torch.clamp(theta_p_plus_1_flat, min=0)
|
|
360
440
|
theta_next = theta_p_plus_1_flat.reshape(Z, X)
|
|
361
441
|
matrix_theta_torch.append(theta_next)
|
|
362
|
-
if isSavingEachIteration and
|
|
442
|
+
if isSavingEachIteration and it in save_indices:
|
|
363
443
|
I_reconMatrix.append(theta_next.cpu().numpy())
|
|
364
|
-
saved_indices.append(
|
|
444
|
+
saved_indices.append(it+1)
|
|
365
445
|
|
|
366
446
|
del A_matrix_torch, y_torch, A_flat, y_flat, theta_0, normalization_factor, normalization_factor_flat
|
|
367
447
|
torch.cuda.empty_cache()
|