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.

Files changed (31) hide show
  1. AOT_biomaps/AOT_Acoustic/AcousticTools.py +35 -115
  2. AOT_biomaps/AOT_Acoustic/StructuredWave.py +2 -2
  3. AOT_biomaps/AOT_Acoustic/_mainAcoustic.py +22 -18
  4. AOT_biomaps/AOT_Experiment/Tomography.py +74 -4
  5. AOT_biomaps/AOT_Experiment/_mainExperiment.py +102 -68
  6. AOT_biomaps/AOT_Optic/_mainOptic.py +124 -58
  7. AOT_biomaps/AOT_Recon/AOT_Optimizers/DEPIERRO.py +72 -108
  8. AOT_biomaps/AOT_Recon/AOT_Optimizers/LS.py +474 -289
  9. AOT_biomaps/AOT_Recon/AOT_Optimizers/MAPEM.py +173 -68
  10. AOT_biomaps/AOT_Recon/AOT_Optimizers/MLEM.py +360 -154
  11. AOT_biomaps/AOT_Recon/AOT_Optimizers/PDHG.py +150 -111
  12. AOT_biomaps/AOT_Recon/AOT_PotentialFunctions/RelativeDifferences.py +10 -14
  13. AOT_biomaps/AOT_Recon/AOT_SparseSMatrix/SparseSMatrix_CSR.py +281 -0
  14. AOT_biomaps/AOT_Recon/AOT_SparseSMatrix/SparseSMatrix_SELL.py +328 -0
  15. AOT_biomaps/AOT_Recon/AOT_SparseSMatrix/__init__.py +2 -0
  16. AOT_biomaps/AOT_Recon/AOT_biomaps_kernels.cubin +0 -0
  17. AOT_biomaps/AOT_Recon/AlgebraicRecon.py +359 -238
  18. AOT_biomaps/AOT_Recon/AnalyticRecon.py +29 -41
  19. AOT_biomaps/AOT_Recon/BayesianRecon.py +165 -91
  20. AOT_biomaps/AOT_Recon/DeepLearningRecon.py +4 -1
  21. AOT_biomaps/AOT_Recon/PrimalDualRecon.py +175 -31
  22. AOT_biomaps/AOT_Recon/ReconEnums.py +38 -3
  23. AOT_biomaps/AOT_Recon/ReconTools.py +184 -77
  24. AOT_biomaps/AOT_Recon/__init__.py +1 -0
  25. AOT_biomaps/AOT_Recon/_mainRecon.py +144 -74
  26. AOT_biomaps/__init__.py +4 -36
  27. {aot_biomaps-2.9.138.dist-info → aot_biomaps-2.9.279.dist-info}/METADATA +2 -1
  28. aot_biomaps-2.9.279.dist-info/RECORD +47 -0
  29. aot_biomaps-2.9.138.dist-info/RECORD +0 -43
  30. {aot_biomaps-2.9.138.dist-info → aot_biomaps-2.9.279.dist-info}/WHEEL +0 -0
  31. {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
- if config.get_process() == 'gpu':
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
- def _DEPIERRO_GPU(SMatrix, y, numIterations, beta, sigma, isSavingEachIteration, withTumor):
16
- # Initialisation du device
17
- device = torch.device(f"cuda:{config.select_best_gpu()}")
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}) ---- {'WITH' if withTumor else 'WITHOUT'} TUMOR ---- processing on single GPU no.{torch.cuda.current_device()}"
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
- if isSavingEachIteration:
48
- step = max(1, numIterations // 1000) # Sauvegarder au plus 1000 images
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
- for it in trange(numIterations, desc=description):
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 (it % step == 0 or it == numIterations - 1):
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
- description = f"AOT-BioMaps -- Bayesian Reconstruction Tomography: DE PIERRO (Sparse QUADRATIC β:{beta:.4f}, σ:{sigma:.4f}) ---- {'WITH' if withTumor else 'WITHOUT'} TUMOR ---- processing on single CPU ----"
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
- for p in trange(numIterations, desc=description):
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