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,76 +1,105 @@
|
|
|
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
4
|
|
|
5
|
+
import warnings
|
|
5
6
|
import numpy as np
|
|
6
7
|
import torch
|
|
7
8
|
from tqdm import trange
|
|
8
|
-
|
|
9
|
+
|
|
10
|
+
if config.get_process() == 'gpu':
|
|
9
11
|
try:
|
|
10
12
|
from torch_scatter import scatter
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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):
|
|
18
52
|
# Conversion des données en tenseurs PyTorch (float64)
|
|
19
53
|
A_matrix_torch = torch.tensor(SMatrix, dtype=torch.float64, device=device)
|
|
20
54
|
y_torch = torch.tensor(y, dtype=torch.float64, device=device)
|
|
21
|
-
|
|
22
55
|
# Dimensions
|
|
23
56
|
T, Z, X, N = SMatrix.shape
|
|
24
57
|
J = Z * X
|
|
25
|
-
|
|
26
58
|
# Redimensionnement des matrices
|
|
27
59
|
A_flat = A_matrix_torch.permute(0, 3, 1, 2).reshape(T * N, J)
|
|
28
60
|
y_flat = y_torch.reshape(-1)
|
|
29
|
-
|
|
30
61
|
# Initialisation de theta
|
|
31
62
|
theta_0 = torch.ones((Z, X), dtype=torch.float64, device=device)
|
|
32
63
|
matrix_theta_torch = [theta_0.clone()] # Clone pour éviter les références
|
|
33
64
|
I_reconMatrix = [theta_0.cpu().numpy()]
|
|
34
|
-
|
|
35
65
|
# Facteur de normalisation
|
|
36
66
|
normalization_factor = A_matrix_torch.sum(dim=(0, 3))
|
|
37
67
|
normalization_factor_flat = normalization_factor.reshape(-1)
|
|
38
|
-
|
|
39
68
|
# Construction de la matrice d'adjacence
|
|
40
69
|
adj_index, adj_values = _build_adjacency_sparse(Z, X, device=device, dtype=torch.float64)
|
|
41
|
-
|
|
42
70
|
# Description pour la barre de progression
|
|
43
|
-
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: DE PIERRO (Sparse QUADRATIC β:{beta:.4f}, σ:{sigma:.4f}) ---- {
|
|
44
|
-
|
|
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()}"
|
|
45
72
|
# Configuration pour la sauvegarde des itérations
|
|
46
|
-
saved_indices = []
|
|
47
|
-
|
|
48
|
-
|
|
73
|
+
saved_indices = [0]
|
|
74
|
+
|
|
75
|
+
# Calculate save indices
|
|
76
|
+
if numIterations <= max_saves:
|
|
77
|
+
save_indices = list(range(numIterations))
|
|
78
|
+
else:
|
|
79
|
+
step = numIterations // max_saves
|
|
80
|
+
save_indices = list(range(0, numIterations, step))
|
|
81
|
+
if save_indices[-1] != numIterations - 1:
|
|
82
|
+
save_indices.append(numIterations - 1)
|
|
49
83
|
|
|
50
84
|
# Boucle principale MAP-EM
|
|
51
|
-
|
|
85
|
+
iterator = trange(numIterations, desc=description) if show_logs else range(numIterations)
|
|
86
|
+
for it in iterator:
|
|
52
87
|
theta_p = matrix_theta_torch[-1]
|
|
53
88
|
theta_p_flat = theta_p.reshape(-1)
|
|
54
|
-
|
|
55
89
|
# Étape 1 : Projection avant
|
|
56
90
|
q_flat = A_flat @ theta_p_flat
|
|
57
91
|
q_flat = q_flat + torch.finfo(torch.float64).tiny # Évite la division par zéro
|
|
58
|
-
|
|
59
92
|
# Étape 2 : Estimation de l'erreur
|
|
60
93
|
e_flat = y_flat / q_flat
|
|
61
|
-
|
|
62
94
|
# Étape 3 : Rétroprojection de l'erreur
|
|
63
95
|
c_flat = A_flat.T @ e_flat
|
|
64
|
-
|
|
65
96
|
# Étape 4 : Mise à jour multiplicative (EM)
|
|
66
97
|
theta_EM_p_flat = theta_p_flat * c_flat
|
|
67
|
-
|
|
68
98
|
# Étape 5 : Calcul de W_j et gamma_j
|
|
69
99
|
W_j = scatter(adj_values, adj_index[0], dim=0, dim_size=J, reduce='sum') * (1.0 / (sigma**2))
|
|
70
100
|
theta_k = theta_p_flat[adj_index[1]]
|
|
71
101
|
weighted_theta_k = theta_k * adj_values
|
|
72
102
|
gamma_j = theta_p_flat * W_j + scatter(weighted_theta_k, adj_index[0], dim=0, dim_size=J, reduce='sum')
|
|
73
|
-
|
|
74
103
|
# Étape 6 : Mise à jour de De Pierro (résolution quadratique)
|
|
75
104
|
A_coeff = 2 * beta * W_j
|
|
76
105
|
B = -beta * gamma_j + normalization_factor_flat
|
|
@@ -79,18 +108,13 @@ def _DEPIERRO_GPU(SMatrix, y, numIterations, beta, sigma, isSavingEachIteration,
|
|
|
79
108
|
discriminant = torch.clamp(discriminant, min=0)
|
|
80
109
|
theta_p_plus_1_flat = (-B + torch.sqrt(discriminant)) / (2 * A_coeff + torch.finfo(torch.float64).tiny)
|
|
81
110
|
theta_p_plus_1_flat = torch.clamp(theta_p_plus_1_flat, min=0)
|
|
82
|
-
|
|
83
111
|
# Étape 7 : Mise à jour de theta
|
|
84
112
|
theta_next = theta_p_plus_1_flat.reshape(Z, X)
|
|
85
113
|
matrix_theta_torch.append(theta_next) # Ajoute la nouvelle itération
|
|
86
|
-
|
|
87
114
|
# Sauvegarde conditionnelle
|
|
88
|
-
if isSavingEachIteration and
|
|
115
|
+
if isSavingEachIteration and it in save_indices:
|
|
89
116
|
I_reconMatrix.append(theta_next.cpu().numpy())
|
|
90
117
|
saved_indices.append(it)
|
|
91
|
-
if len(I_reconMatrix) >= 1000: # Limite stricte
|
|
92
|
-
break
|
|
93
|
-
|
|
94
118
|
# Libération mémoire partielle (optionnel, à ajuster selon besoin)
|
|
95
119
|
del theta_p_flat, q_flat, e_flat, c_flat, theta_EM_p_flat, theta_p_plus_1_flat
|
|
96
120
|
torch.cuda.empty_cache()
|
|
@@ -98,83 +122,14 @@ def _DEPIERRO_GPU(SMatrix, y, numIterations, beta, sigma, isSavingEachIteration,
|
|
|
98
122
|
# Libération finale des tenseurs GPU
|
|
99
123
|
del A_matrix_torch, y_torch, A_flat, y_flat, normalization_factor, normalization_factor_flat
|
|
100
124
|
torch.cuda.empty_cache()
|
|
101
|
-
|
|
102
125
|
# Retour du résultat
|
|
103
126
|
if isSavingEachIteration:
|
|
104
127
|
return I_reconMatrix, saved_indices
|
|
105
128
|
else:
|
|
106
129
|
return matrix_theta_torch[-1].cpu().numpy(), None
|
|
107
130
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
# def _DEPIERRO_GPU(SMatrix, y, Omega, numIterations, beta, sigma, isSavingEachIteration, withTumor):
|
|
111
|
-
# try:
|
|
112
|
-
# if Omega != PotentialType.QUADRATIC:
|
|
113
|
-
# raise ValueError("Depierro95 optimizer only supports QUADRATIC potential function.")
|
|
114
|
-
# if beta is None or sigma is None:
|
|
115
|
-
# raise ValueError("Depierro95 optimizer requires beta and sigma parameters.")
|
|
116
|
-
|
|
117
|
-
# device = torch.device(f"cuda:{config.select_best_gpu()}")
|
|
118
|
-
# A_matrix_torch = torch.tensor(SMatrix, dtype=torch.float32).to(device)
|
|
119
|
-
# y_torch = torch.tensor(y, dtype=torch.float32).to(device)
|
|
120
|
-
# T, Z, X, N = SMatrix.shape
|
|
121
|
-
# J = Z * X
|
|
122
|
-
# A_flat = A_matrix_torch.permute(0, 3, 1, 2).reshape(T * N, Z * X)
|
|
123
|
-
# y_flat = y_torch.reshape(-1)
|
|
124
|
-
# theta_0 = torch.ones((Z, X), dtype=torch.float32, device=device)
|
|
125
|
-
# matrix_theta_torch = [theta_0]
|
|
126
|
-
# I_reconMatrix = [theta_0.cpu().numpy()]
|
|
127
|
-
# normalization_factor = A_matrix_torch.sum(dim=(0, 3))
|
|
128
|
-
# normalization_factor_flat = normalization_factor.reshape(-1)
|
|
129
|
-
# adj_index, adj_values = _build_adjacency_sparse(Z, X, device=device)
|
|
130
|
-
|
|
131
|
-
# description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: DE PIERRO (Sparse QUADRATIC β:{beta:.4f}, σ:{sigma:.4f}) ---- {'WITH' if withTumor else 'WITHOUT'} TUMOR ---- processing on single GPU no.{torch.cuda.current_device()} ----"
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
# for p in trange(numIterations, desc=description):
|
|
135
|
-
# theta_p = matrix_theta_torch[-1]
|
|
136
|
-
# theta_p_flat = theta_p.reshape(-1)
|
|
137
|
-
# q_flat = A_flat @ theta_p_flat
|
|
138
|
-
# e_flat = y_flat / (q_flat + torch.finfo(torch.float32).tiny)
|
|
139
|
-
# c_flat = A_flat.T @ e_flat
|
|
140
|
-
# theta_EM_p_flat = theta_p_flat * c_flat
|
|
141
|
-
# alpha_j = normalization_factor_flat
|
|
142
|
-
# W_j = scatter(adj_values, adj_index[0], dim=0, dim_size=J, reduce='sum') * (1.0 / sigma**2)
|
|
143
|
-
# theta_k = theta_p_flat[adj_index[1]]
|
|
144
|
-
# weighted_theta_k = theta_k * adj_values
|
|
145
|
-
# gamma_j = theta_p_flat * W_j + scatter(weighted_theta_k, adj_index[0], dim=0, dim_size=J, reduce='sum')
|
|
146
|
-
# A = 2 * beta * W_j
|
|
147
|
-
# B = -beta * gamma_j + alpha_j
|
|
148
|
-
# C = -theta_EM_p_flat
|
|
149
|
-
# theta_p_plus_1_flat = (-B + torch.sqrt(B ** 2 - 4 * A * C)) / (2 * A + torch.finfo(torch.float32).tiny)
|
|
150
|
-
# theta_p_plus_1_flat = torch.clamp(theta_p_plus_1_flat, min=0)
|
|
151
|
-
# theta_next = theta_p_plus_1_flat.reshape(Z, X)
|
|
152
|
-
# matrix_theta_torch[-1] = theta_next
|
|
153
|
-
|
|
154
|
-
# if p % 1 == 0:
|
|
155
|
-
# I_reconMatrix.append(theta_next.cpu().numpy())
|
|
156
|
-
|
|
157
|
-
# del theta_p_flat, q_flat, e_flat, c_flat, theta_EM_p_flat, theta_p_plus_1_flat, theta_next
|
|
158
|
-
# torch.cuda.empty_cache()
|
|
159
|
-
|
|
160
|
-
# del A_matrix_torch, y_torch, A_flat, y_flat, theta_0, normalization_factor, normalization_factor_flat
|
|
161
|
-
# torch.cuda.empty_cache()
|
|
162
|
-
|
|
163
|
-
# if isSavingEachIteration:
|
|
164
|
-
# return I_reconMatrix
|
|
165
|
-
# else:
|
|
166
|
-
# return I_reconMatrix[-1]
|
|
167
|
-
|
|
168
|
-
# except Exception as e:
|
|
169
|
-
# print(f"An error occurred in _DEPIERRO_GPU: {e}")
|
|
170
|
-
# del A_matrix_torch, y_torch, A_flat, y_flat, theta_0, normalization_factor, normalization_factor_flat
|
|
171
|
-
# torch.cuda.empty_cache()
|
|
172
|
-
# return None
|
|
173
|
-
|
|
174
|
-
def _DEPIERRO_CPU(SMatrix, y, Omega, numIterations, beta, sigma, isSavingEachIteration, withTumor):
|
|
131
|
+
def _DEPIERRO_CPU(SMatrix, y, numIterations, beta, sigma, isSavingEachIteration, tumor_str, device, max_saves, show_logs=True):
|
|
175
132
|
try:
|
|
176
|
-
if Omega != PotentialType.QUADRATIC:
|
|
177
|
-
raise ValueError("Depierro95 optimizer only supports QUADRATIC potential function.")
|
|
178
133
|
if beta is None or sigma is None:
|
|
179
134
|
raise ValueError("Depierro95 optimizer requires beta and sigma parameters.")
|
|
180
135
|
|
|
@@ -187,14 +142,24 @@ def _DEPIERRO_CPU(SMatrix, y, Omega, numIterations, beta, sigma, isSavingEachIte
|
|
|
187
142
|
theta_0 = np.ones((Z, X), dtype=np.float32)
|
|
188
143
|
matrix_theta = [theta_0]
|
|
189
144
|
I_reconMatrix = [theta_0.copy()]
|
|
145
|
+
saved_indices = [0]
|
|
190
146
|
normalization_factor = A_matrix.sum(axis=(0, 3))
|
|
191
147
|
normalization_factor_flat = normalization_factor.reshape(-1)
|
|
192
148
|
adj_index, adj_values = _build_adjacency_sparse(Z, X)
|
|
193
149
|
|
|
194
|
-
|
|
150
|
+
# Calculate save indices
|
|
151
|
+
if numIterations <= max_saves:
|
|
152
|
+
save_indices = list(range(numIterations))
|
|
153
|
+
else:
|
|
154
|
+
step = numIterations // max_saves
|
|
155
|
+
save_indices = list(range(0, numIterations, step))
|
|
156
|
+
if save_indices[-1] != numIterations - 1:
|
|
157
|
+
save_indices.append(numIterations - 1)
|
|
195
158
|
|
|
159
|
+
description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: DE PIERRO (Sparse QUADRATIC β:{beta:.4f}, σ:{sigma:.4f}) ---- {tumor_str} TUMOR ---- processing on single CPU ----"
|
|
196
160
|
|
|
197
|
-
|
|
161
|
+
iterator = trange(numIterations, desc=description) if show_logs else range(numIterations)
|
|
162
|
+
for it in iterator:
|
|
198
163
|
theta_p = matrix_theta[-1]
|
|
199
164
|
theta_p_flat = theta_p.reshape(-1)
|
|
200
165
|
q_flat = np.dot(A_flat, theta_p_flat)
|
|
@@ -213,15 +178,14 @@ def _DEPIERRO_CPU(SMatrix, y, Omega, numIterations, beta, sigma, isSavingEachIte
|
|
|
213
178
|
theta_p_plus_1_flat = np.clip(theta_p_plus_1_flat, a_min=0, a_max=None)
|
|
214
179
|
theta_next = theta_p_plus_1_flat.reshape(Z, X)
|
|
215
180
|
matrix_theta[-1] = theta_next
|
|
216
|
-
|
|
217
|
-
if p % 1 == 0:
|
|
181
|
+
if isSavingEachIteration and it in save_indices:
|
|
218
182
|
I_reconMatrix.append(theta_next.copy())
|
|
183
|
+
saved_indices.append(it)
|
|
219
184
|
|
|
220
185
|
if isSavingEachIteration:
|
|
221
|
-
return I_reconMatrix
|
|
186
|
+
return I_reconMatrix, saved_indices
|
|
222
187
|
else:
|
|
223
|
-
return I_reconMatrix[-1]
|
|
224
|
-
|
|
188
|
+
return I_reconMatrix[-1], None
|
|
225
189
|
except Exception as e:
|
|
226
190
|
print(f"An error occurred in _DEPIERRO_CPU: {e}")
|
|
227
|
-
return None
|
|
191
|
+
return None, None
|