AOT-biomaps 2.9.138__py3-none-any.whl → 2.9.279__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_Acoustic/AcousticTools.py +35 -115
- AOT_biomaps/AOT_Acoustic/StructuredWave.py +2 -2
- AOT_biomaps/AOT_Acoustic/_mainAcoustic.py +22 -18
- AOT_biomaps/AOT_Experiment/Tomography.py +74 -4
- AOT_biomaps/AOT_Experiment/_mainExperiment.py +102 -68
- AOT_biomaps/AOT_Optic/_mainOptic.py +124 -58
- AOT_biomaps/AOT_Recon/AOT_Optimizers/DEPIERRO.py +72 -108
- AOT_biomaps/AOT_Recon/AOT_Optimizers/LS.py +474 -289
- AOT_biomaps/AOT_Recon/AOT_Optimizers/MAPEM.py +173 -68
- AOT_biomaps/AOT_Recon/AOT_Optimizers/MLEM.py +360 -154
- AOT_biomaps/AOT_Recon/AOT_Optimizers/PDHG.py +150 -111
- AOT_biomaps/AOT_Recon/AOT_PotentialFunctions/RelativeDifferences.py +10 -14
- AOT_biomaps/AOT_Recon/AOT_SparseSMatrix/SparseSMatrix_CSR.py +281 -0
- AOT_biomaps/AOT_Recon/AOT_SparseSMatrix/SparseSMatrix_SELL.py +328 -0
- AOT_biomaps/AOT_Recon/AOT_SparseSMatrix/__init__.py +2 -0
- AOT_biomaps/AOT_Recon/AOT_biomaps_kernels.cubin +0 -0
- AOT_biomaps/AOT_Recon/AlgebraicRecon.py +359 -238
- AOT_biomaps/AOT_Recon/AnalyticRecon.py +29 -41
- AOT_biomaps/AOT_Recon/BayesianRecon.py +165 -91
- AOT_biomaps/AOT_Recon/DeepLearningRecon.py +4 -1
- AOT_biomaps/AOT_Recon/PrimalDualRecon.py +175 -31
- AOT_biomaps/AOT_Recon/ReconEnums.py +38 -3
- AOT_biomaps/AOT_Recon/ReconTools.py +184 -77
- AOT_biomaps/AOT_Recon/__init__.py +1 -0
- AOT_biomaps/AOT_Recon/_mainRecon.py +144 -74
- AOT_biomaps/__init__.py +4 -36
- {aot_biomaps-2.9.138.dist-info → aot_biomaps-2.9.279.dist-info}/METADATA +2 -1
- aot_biomaps-2.9.279.dist-info/RECORD +47 -0
- aot_biomaps-2.9.138.dist-info/RECORD +0 -43
- {aot_biomaps-2.9.138.dist-info → aot_biomaps-2.9.279.dist-info}/WHEEL +0 -0
- {aot_biomaps-2.9.138.dist-info → aot_biomaps-2.9.279.dist-info}/top_level.txt +0 -0
|
@@ -1,17 +1,95 @@
|
|
|
1
|
-
|
|
2
1
|
from AOT_biomaps.AOT_Recon.ReconEnums import PotentialType
|
|
3
2
|
from AOT_biomaps.AOT_Recon.AOT_PotentialFunctions.Quadratic import _Omega_QUADRATIC_CPU, _Omega_QUADRATIC_GPU
|
|
4
3
|
from AOT_biomaps.AOT_Recon.AOT_PotentialFunctions.RelativeDifferences import _Omega_RELATIVE_DIFFERENCE_CPU, _Omega_RELATIVE_DIFFERENCE_GPU
|
|
5
4
|
from AOT_biomaps.AOT_Recon.AOT_PotentialFunctions.Huber import _Omega_HUBER_PIECEWISE_CPU, _Omega_HUBER_PIECEWISE_GPU
|
|
6
|
-
from AOT_biomaps.AOT_Recon.ReconTools import
|
|
5
|
+
from AOT_biomaps.AOT_Recon.ReconTools import _build_adjacency_sparse, check_gpu_memory, calculate_memory_requirement
|
|
7
6
|
from AOT_biomaps.Config import config
|
|
8
7
|
|
|
8
|
+
import warnings
|
|
9
9
|
import numpy as np
|
|
10
10
|
import torch
|
|
11
11
|
from tqdm import trange
|
|
12
12
|
|
|
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
|
+
|
|
13
91
|
|
|
14
|
-
def _MAPEM_CPU_STOP(SMatrix, y, Omega,
|
|
92
|
+
def _MAPEM_CPU_STOP(SMatrix, y, Omega, beta, delta, gamma, sigma, numIterations, isSavingEachIteration, tumor_str, max_saves, show_logs=True):
|
|
15
93
|
"""
|
|
16
94
|
MAPEM version CPU simple - sans GPU - torch uniquement
|
|
17
95
|
"""
|
|
@@ -44,55 +122,62 @@ def _MAPEM_CPU_STOP(SMatrix, y, Omega, numIterations, beta, delta, gamma, sigma,
|
|
|
44
122
|
I_0 = torch.ones((Z, X), dtype=torch.float32)
|
|
45
123
|
theta_list = [I_0]
|
|
46
124
|
results = [I_0.numpy()]
|
|
47
|
-
|
|
125
|
+
saved_indices = [0]
|
|
48
126
|
normalization_factor = SMatrix.sum(dim=(0, 3)).reshape(-1)
|
|
49
|
-
adj_index, adj_values =
|
|
127
|
+
adj_index, adj_values = _build_adjacency_sparse(Z, X)
|
|
128
|
+
|
|
129
|
+
# Calculate save indices
|
|
130
|
+
if numIterations <= max_saves:
|
|
131
|
+
save_indices = list(range(numIterations))
|
|
132
|
+
else:
|
|
133
|
+
step = numIterations // max_saves
|
|
134
|
+
save_indices = list(range(0, numIterations, step))
|
|
135
|
+
if save_indices[-1] != numIterations - 1:
|
|
136
|
+
save_indices.append(numIterations - 1)
|
|
50
137
|
|
|
51
138
|
if Omega == PotentialType.HUBER_PIECEWISE:
|
|
52
|
-
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 ----"
|
|
53
140
|
elif Omega == PotentialType.RELATIVE_DIFFERENCE:
|
|
54
|
-
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 ----"
|
|
55
142
|
elif Omega == PotentialType.QUADRATIC:
|
|
56
|
-
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 ----"
|
|
57
144
|
|
|
58
|
-
|
|
145
|
+
iterator = trange(numIterations, desc=description) if show_logs else range(numIterations)
|
|
146
|
+
for it in iterator:
|
|
59
147
|
theta_p = theta_list[-1]
|
|
60
148
|
theta_p_flat = theta_p.reshape(-1)
|
|
61
149
|
q_flat = A_flat @ theta_p_flat
|
|
62
150
|
e_flat = (y_flat - q_flat) / (q_flat + torch.finfo(torch.float32).tiny)
|
|
63
151
|
c_flat = A_flat.T @ e_flat
|
|
64
|
-
|
|
65
152
|
if Omega == PotentialType.HUBER_PIECEWISE:
|
|
66
153
|
grad_U, hess_U, U_value = _Omega_HUBER_PIECEWISE_CPU(theta_p_flat, adj_index, adj_values, delta=delta)
|
|
67
154
|
elif Omega == PotentialType.RELATIVE_DIFFERENCE:
|
|
68
155
|
grad_U, hess_U, U_value = _Omega_RELATIVE_DIFFERENCE_CPU(theta_p_flat, adj_index, adj_values, gamma=gamma)
|
|
69
156
|
elif Omega == PotentialType.QUADRATIC:
|
|
70
157
|
grad_U, hess_U, U_value = _Omega_QUADRATIC_CPU(theta_p_flat, adj_index, adj_values, sigma=sigma)
|
|
71
|
-
|
|
72
158
|
denom = normalization_factor + theta_p_flat * beta * hess_U
|
|
73
159
|
num = theta_p_flat * (c_flat - beta * grad_U)
|
|
74
160
|
theta_next_flat = theta_p_flat + num / (denom + torch.finfo(torch.float32).tiny)
|
|
75
161
|
theta_next_flat = torch.clamp(theta_next_flat, min=0)
|
|
76
162
|
theta_next = theta_next_flat.reshape(Z, X)
|
|
77
163
|
theta_list[-1] = theta_next
|
|
78
|
-
|
|
79
|
-
|
|
164
|
+
if isSavingEachIteration and it in save_indices:
|
|
165
|
+
results.append(theta_next.numpy())
|
|
166
|
+
saved_indices.append(it+1)
|
|
80
167
|
log_likelihood = (y_flat * torch.log(q_flat + 1e-8) - (q_flat + 1e-8)).sum()
|
|
81
168
|
penalized_log_likelihood = log_likelihood - beta * U_value
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (p + 1) % 100 == 0:
|
|
85
|
-
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}")
|
|
86
171
|
|
|
87
172
|
if isSavingEachIteration:
|
|
88
|
-
return results
|
|
173
|
+
return results, saved_indices
|
|
89
174
|
else:
|
|
90
|
-
return results
|
|
175
|
+
return results[-1], None
|
|
91
176
|
except Exception as e:
|
|
92
177
|
print(f"An error occurred in _MAPEM_CPU_STOP: {e}")
|
|
93
|
-
return None
|
|
178
|
+
return None, None
|
|
94
179
|
|
|
95
|
-
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):
|
|
96
181
|
"""
|
|
97
182
|
Maximum A Posteriori (MAP) estimation for Bayesian reconstruction.
|
|
98
183
|
This method computes the MAP estimate of the parameters given the data.
|
|
@@ -118,7 +203,6 @@ def _MAPEM_GPU_STOP(SMatrix, y, Omega, numIterations, beta, delta, gamma, sigma,
|
|
|
118
203
|
else:
|
|
119
204
|
raise ValueError(f"Unknown potential type: {Omega}")
|
|
120
205
|
|
|
121
|
-
device = torch.device(f"cuda:{config.select_best_gpu()}")
|
|
122
206
|
A_matrix_torch = torch.tensor(SMatrix, dtype=torch.float32).to(device)
|
|
123
207
|
y_torch = torch.tensor(y, dtype=torch.float32).to(device)
|
|
124
208
|
T, Z, X, N = SMatrix.shape
|
|
@@ -128,26 +212,36 @@ def _MAPEM_GPU_STOP(SMatrix, y, Omega, numIterations, beta, delta, gamma, sigma,
|
|
|
128
212
|
I_0 = torch.ones((Z, X), dtype=torch.float32, device=device)
|
|
129
213
|
matrix_theta_torch = [I_0]
|
|
130
214
|
matrix_theta_from_gpu_MAPEM = [I_0.cpu().numpy()]
|
|
215
|
+
saved_indices = [0]
|
|
131
216
|
normalization_factor = A_matrix_torch.sum(dim=(0, 3))
|
|
132
217
|
normalization_factor_flat = normalization_factor.reshape(-1)
|
|
133
218
|
previous = -np.inf
|
|
134
219
|
nb_false_successive = 0
|
|
135
|
-
adj_index, adj_values =
|
|
220
|
+
adj_index, adj_values = _build_adjacency_sparse(Z, X, device=device)
|
|
221
|
+
|
|
222
|
+
# Calculate save indices
|
|
223
|
+
if numIterations <= max_saves:
|
|
224
|
+
save_indices = list(range(numIterations))
|
|
225
|
+
else:
|
|
226
|
+
step = numIterations // max_saves
|
|
227
|
+
save_indices = list(range(0, numIterations, step))
|
|
228
|
+
if save_indices[-1] != numIterations - 1:
|
|
229
|
+
save_indices.append(numIterations - 1)
|
|
136
230
|
|
|
137
231
|
if Omega == PotentialType.HUBER_PIECEWISE:
|
|
138
|
-
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()} ----"
|
|
139
233
|
elif Omega == PotentialType.RELATIVE_DIFFERENCE:
|
|
140
|
-
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()} ----"
|
|
141
235
|
elif Omega == PotentialType.QUADRATIC:
|
|
142
|
-
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()} ----"
|
|
143
237
|
|
|
144
|
-
|
|
238
|
+
iterator = trange(numIterations, desc=description) if show_logs else range(numIterations)
|
|
239
|
+
for it in iterator:
|
|
145
240
|
theta_p = matrix_theta_torch[-1]
|
|
146
241
|
theta_p_flat = theta_p.reshape(-1)
|
|
147
242
|
q_flat = A_flat @ theta_p_flat
|
|
148
243
|
e_flat = (y_flat - q_flat) / (q_flat + torch.finfo(torch.float32).tiny)
|
|
149
244
|
c_flat = A_flat.T @ e_flat
|
|
150
|
-
|
|
151
245
|
if Omega == PotentialType.HUBER_PIECEWISE:
|
|
152
246
|
grad_U, hess_U, U_value = _Omega_HUBER_PIECEWISE_GPU(theta_p_flat, adj_index, adj_values, device=device, delta=delta)
|
|
153
247
|
elif Omega == PotentialType.RELATIVE_DIFFERENCE:
|
|
@@ -156,43 +250,39 @@ def _MAPEM_GPU_STOP(SMatrix, y, Omega, numIterations, beta, delta, gamma, sigma,
|
|
|
156
250
|
grad_U, hess_U, U_value = _Omega_QUADRATIC_GPU(theta_p_flat, adj_index, adj_values, device=device, sigma=sigma)
|
|
157
251
|
else:
|
|
158
252
|
raise ValueError(f"Unknown potential type: {Omega}")
|
|
159
|
-
|
|
160
253
|
denom = normalization_factor_flat + theta_p_flat * beta * hess_U
|
|
161
254
|
num = theta_p_flat * (c_flat - beta * grad_U)
|
|
162
255
|
theta_p_plus_1_flat = theta_p_flat + num / (denom + torch.finfo(torch.float32).tiny)
|
|
163
256
|
theta_p_plus_1_flat = torch.clamp(theta_p_plus_1_flat, min=0)
|
|
164
257
|
theta_next = theta_p_plus_1_flat.reshape(Z, X)
|
|
165
258
|
matrix_theta_torch[-1] = theta_next
|
|
166
|
-
|
|
167
|
-
if p % 1 == 0:
|
|
259
|
+
if isSavingEachIteration and it in save_indices:
|
|
168
260
|
matrix_theta_from_gpu_MAPEM.append(theta_next.cpu().numpy())
|
|
169
|
-
|
|
261
|
+
saved_indices.append(it+1)
|
|
170
262
|
log_likelihood = (y_flat * (torch.log(q_flat + torch.finfo(torch.float32).tiny)) - (q_flat + torch.finfo(torch.float32).tiny)).sum()
|
|
171
263
|
penalized_log_likelihood = log_likelihood - beta * U_value
|
|
172
|
-
|
|
173
|
-
if p == 0 or (p + 1) % 100 == 0:
|
|
264
|
+
if it == 0 or (it + 1) % 100 == 0:
|
|
174
265
|
current = penalized_log_likelihood.item()
|
|
175
266
|
if current <= previous:
|
|
176
267
|
nb_false_successive += 1
|
|
177
268
|
else:
|
|
178
269
|
nb_false_successive = 0
|
|
179
|
-
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}")
|
|
180
271
|
previous = current
|
|
181
272
|
|
|
182
273
|
del A_matrix_torch, y_torch, A_flat, y_flat, I_0, normalization_factor, normalization_factor_flat
|
|
183
274
|
torch.cuda.empty_cache()
|
|
184
|
-
|
|
185
275
|
if isSavingEachIteration:
|
|
186
|
-
return matrix_theta_from_gpu_MAPEM
|
|
276
|
+
return matrix_theta_from_gpu_MAPEM, saved_indices
|
|
187
277
|
else:
|
|
188
|
-
return matrix_theta_from_gpu_MAPEM[-1]
|
|
278
|
+
return matrix_theta_from_gpu_MAPEM[-1], None
|
|
189
279
|
except Exception as e:
|
|
190
280
|
print(f"An error occurred in _MAPEM_GPU_STOP: {e}")
|
|
191
281
|
del A_matrix_torch, y_torch, A_flat, y_flat, I_0, normalization_factor, normalization_factor_flat
|
|
192
282
|
torch.cuda.empty_cache()
|
|
193
|
-
return None
|
|
283
|
+
return None, None
|
|
194
284
|
|
|
195
|
-
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):
|
|
196
286
|
try:
|
|
197
287
|
if not isinstance(Omega, PotentialType):
|
|
198
288
|
raise TypeError(f"Omega must be of type PotentialType, got {type(Omega)}")
|
|
@@ -215,56 +305,64 @@ def _MAPEM_CPU(SMatrix, y, Omega, numIterations, beta, delta, gamma, sigma, isSa
|
|
|
215
305
|
raise ValueError(f"Unknown potential type: {Omega}")
|
|
216
306
|
|
|
217
307
|
T, Z, X, N = SMatrix.shape
|
|
218
|
-
J = Z * X
|
|
219
308
|
A_flat = np.transpose(SMatrix, (0, 3, 1, 2)).reshape(T * N, Z * X)
|
|
220
309
|
y_flat = y.reshape(-1)
|
|
221
310
|
theta_0 = np.ones((Z, X), dtype=np.float32)
|
|
222
311
|
matrix_theta_np = [theta_0]
|
|
223
312
|
I_reconMatrix = [theta_0.copy()]
|
|
313
|
+
saved_indices = [0]
|
|
224
314
|
normalization_factor = SMatrix.sum(axis=(0, 3))
|
|
225
315
|
normalization_factor_flat = normalization_factor.reshape(-1)
|
|
226
|
-
adj_index, adj_values =
|
|
316
|
+
adj_index, adj_values = _build_adjacency_sparse(Z, X)
|
|
317
|
+
|
|
318
|
+
# Calculate save indices
|
|
319
|
+
if numIterations <= max_saves:
|
|
320
|
+
save_indices = list(range(numIterations))
|
|
321
|
+
else:
|
|
322
|
+
step = numIterations // max_saves
|
|
323
|
+
save_indices = list(range(0, numIterations, step))
|
|
324
|
+
if save_indices[-1] != numIterations - 1:
|
|
325
|
+
save_indices.append(numIterations - 1)
|
|
227
326
|
|
|
228
327
|
if Omega == PotentialType.HUBER_PIECEWISE:
|
|
229
|
-
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 ----"
|
|
230
329
|
elif Omega == PotentialType.RELATIVE_DIFFERENCE:
|
|
231
|
-
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 ----"
|
|
232
331
|
elif Omega == PotentialType.QUADRATIC:
|
|
233
|
-
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 ----"
|
|
234
333
|
|
|
235
|
-
|
|
334
|
+
iterator = trange(numIterations, desc=description) if show_logs else range(numIterations)
|
|
335
|
+
for it in iterator:
|
|
236
336
|
theta_p = matrix_theta_np[-1]
|
|
237
337
|
theta_p_flat = theta_p.reshape(-1)
|
|
238
338
|
q_flat = A_flat @ theta_p_flat
|
|
239
339
|
e_flat = (y_flat - q_flat) / (q_flat + np.finfo(np.float32).tiny)
|
|
240
340
|
c_flat = A_flat.T @ e_flat
|
|
241
|
-
|
|
242
341
|
if Omega == PotentialType.HUBER_PIECEWISE:
|
|
243
342
|
grad_U, hess_U, _ = _Omega_HUBER_PIECEWISE_CPU(theta_p_flat, adj_index, adj_values, delta=delta)
|
|
244
343
|
elif Omega == PotentialType.RELATIVE_DIFFERENCE:
|
|
245
344
|
grad_U, hess_U, _ = _Omega_RELATIVE_DIFFERENCE_CPU(theta_p_flat, adj_index, adj_values, gamma=gamma)
|
|
246
345
|
elif Omega == PotentialType.QUADRATIC:
|
|
247
346
|
grad_U, hess_U, _ = _Omega_QUADRATIC_CPU(theta_p_flat, adj_index, adj_values, sigma=sigma)
|
|
248
|
-
|
|
249
347
|
denom = normalization_factor_flat + theta_p_flat * beta * hess_U
|
|
250
348
|
num = theta_p_flat * (c_flat - beta * grad_U)
|
|
251
349
|
theta_p_plus_1_flat = theta_p_flat + num / (denom + np.finfo(np.float32).tiny)
|
|
252
350
|
theta_p_plus_1_flat = np.clip(theta_p_plus_1_flat, 0, None)
|
|
253
351
|
theta_next = theta_p_plus_1_flat.reshape(Z, X)
|
|
254
352
|
matrix_theta_np.append(theta_next)
|
|
255
|
-
|
|
256
|
-
if p % 1 == 0:
|
|
353
|
+
if isSavingEachIteration and it in save_indices:
|
|
257
354
|
I_reconMatrix.append(theta_next.copy())
|
|
355
|
+
saved_indices.append(it+1)
|
|
258
356
|
|
|
259
357
|
if isSavingEachIteration:
|
|
260
|
-
return I_reconMatrix
|
|
358
|
+
return I_reconMatrix, saved_indices
|
|
261
359
|
else:
|
|
262
|
-
return I_reconMatrix[-1]
|
|
360
|
+
return I_reconMatrix[-1], None
|
|
263
361
|
except Exception as e:
|
|
264
362
|
print(f"An error occurred in _MAPEM_CPU: {e}")
|
|
265
|
-
return None
|
|
363
|
+
return None, None
|
|
266
364
|
|
|
267
|
-
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):
|
|
268
366
|
"""
|
|
269
367
|
Maximum A Posteriori (MAP) estimation for Bayesian reconstruction using GPU.
|
|
270
368
|
This method computes the MAP estimate of the parameters given the data.
|
|
@@ -290,7 +388,6 @@ def _MAPEM_GPU(SMatrix, y, Omega, numIterations, beta, delta, gamma, sigma, isSa
|
|
|
290
388
|
else:
|
|
291
389
|
raise ValueError(f"Unknown potential type: {Omega}")
|
|
292
390
|
|
|
293
|
-
device = torch.device(f"cuda:{config.select_best_gpu()}")
|
|
294
391
|
A_matrix_torch = torch.tensor(SMatrix, dtype=torch.float32).to(device)
|
|
295
392
|
y_torch = torch.tensor(y, dtype=torch.float32).to(device)
|
|
296
393
|
T, Z, X, N = SMatrix.shape
|
|
@@ -300,24 +397,34 @@ def _MAPEM_GPU(SMatrix, y, Omega, numIterations, beta, delta, gamma, sigma, isSa
|
|
|
300
397
|
theta_0 = torch.ones((Z, X), dtype=torch.float32, device=device)
|
|
301
398
|
matrix_theta_torch = [theta_0]
|
|
302
399
|
I_reconMatrix = [theta_0.cpu().numpy()]
|
|
400
|
+
saved_indices = [0]
|
|
303
401
|
normalization_factor = A_matrix_torch.sum(dim=(0, 3))
|
|
304
402
|
normalization_factor_flat = normalization_factor.reshape(-1)
|
|
305
|
-
adj_index, adj_values =
|
|
403
|
+
adj_index, adj_values = _build_adjacency_sparse(Z, X, device=device)
|
|
404
|
+
|
|
405
|
+
# Calculate save indices
|
|
406
|
+
if numIterations <= max_saves:
|
|
407
|
+
save_indices = list(range(numIterations))
|
|
408
|
+
else:
|
|
409
|
+
step = numIterations // max_saves
|
|
410
|
+
save_indices = list(range(0, numIterations, step))
|
|
411
|
+
if save_indices[-1] != numIterations - 1:
|
|
412
|
+
save_indices.append(numIterations - 1)
|
|
306
413
|
|
|
307
414
|
if Omega == PotentialType.HUBER_PIECEWISE:
|
|
308
|
-
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()} ----"
|
|
309
416
|
elif Omega == PotentialType.RELATIVE_DIFFERENCE:
|
|
310
|
-
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()} ----"
|
|
311
418
|
elif Omega == PotentialType.QUADRATIC:
|
|
312
|
-
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()} ----"
|
|
313
420
|
|
|
314
|
-
|
|
421
|
+
iterator = trange(numIterations, desc=description) if show_logs else range(numIterations)
|
|
422
|
+
for it in iterator:
|
|
315
423
|
theta_p = matrix_theta_torch[-1]
|
|
316
424
|
theta_p_flat = theta_p.reshape(-1)
|
|
317
425
|
q_flat = A_flat @ theta_p_flat
|
|
318
426
|
e_flat = (y_flat - q_flat) / (q_flat + torch.finfo(torch.float32).tiny)
|
|
319
427
|
c_flat = A_flat.T @ e_flat
|
|
320
|
-
|
|
321
428
|
if Omega == PotentialType.HUBER_PIECEWISE:
|
|
322
429
|
grad_U, hess_U, _ = _Omega_HUBER_PIECEWISE_GPU(theta_p_flat, adj_index, adj_values, device=device, delta=delta)
|
|
323
430
|
elif Omega == PotentialType.RELATIVE_DIFFERENCE:
|
|
@@ -326,26 +433,24 @@ def _MAPEM_GPU(SMatrix, y, Omega, numIterations, beta, delta, gamma, sigma, isSa
|
|
|
326
433
|
grad_U, hess_U, _ = _Omega_QUADRATIC_GPU(theta_p_flat, adj_index, adj_values, device=device, sigma=sigma)
|
|
327
434
|
else:
|
|
328
435
|
raise ValueError(f"Unknown potential type: {Omega}")
|
|
329
|
-
|
|
330
436
|
denom = normalization_factor_flat + theta_p_flat * beta * hess_U
|
|
331
437
|
num = theta_p_flat * (c_flat - beta * grad_U)
|
|
332
438
|
theta_p_plus_1_flat = theta_p_flat + num / (denom + torch.finfo(torch.float32).tiny)
|
|
333
439
|
theta_p_plus_1_flat = torch.clamp(theta_p_plus_1_flat, min=0)
|
|
334
440
|
theta_next = theta_p_plus_1_flat.reshape(Z, X)
|
|
335
441
|
matrix_theta_torch.append(theta_next)
|
|
336
|
-
|
|
337
|
-
if p % 1 == 0:
|
|
442
|
+
if isSavingEachIteration and it in save_indices:
|
|
338
443
|
I_reconMatrix.append(theta_next.cpu().numpy())
|
|
444
|
+
saved_indices.append(it+1)
|
|
339
445
|
|
|
340
446
|
del A_matrix_torch, y_torch, A_flat, y_flat, theta_0, normalization_factor, normalization_factor_flat
|
|
341
447
|
torch.cuda.empty_cache()
|
|
342
|
-
|
|
343
448
|
if isSavingEachIteration:
|
|
344
|
-
return I_reconMatrix
|
|
449
|
+
return I_reconMatrix, saved_indices
|
|
345
450
|
else:
|
|
346
|
-
return I_reconMatrix[-1]
|
|
451
|
+
return I_reconMatrix[-1], None
|
|
347
452
|
except Exception as e:
|
|
348
453
|
print(f"An error occurred in _MAPEM_GPU: {e}")
|
|
349
454
|
del A_matrix_torch, y_torch, A_flat, y_flat, theta_0, normalization_factor, normalization_factor_flat
|
|
350
455
|
torch.cuda.empty_cache()
|
|
351
|
-
return None
|
|
456
|
+
return None, None
|