AOT-biomaps 2.1.3__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_Acoustic/AcousticEnums.py +64 -0
- AOT_biomaps/AOT_Acoustic/AcousticTools.py +221 -0
- AOT_biomaps/AOT_Acoustic/FocusedWave.py +244 -0
- AOT_biomaps/AOT_Acoustic/IrregularWave.py +66 -0
- AOT_biomaps/AOT_Acoustic/PlaneWave.py +43 -0
- AOT_biomaps/AOT_Acoustic/StructuredWave.py +392 -0
- AOT_biomaps/AOT_Acoustic/__init__.py +15 -0
- AOT_biomaps/AOT_Acoustic/_mainAcoustic.py +978 -0
- AOT_biomaps/AOT_Experiment/Focus.py +55 -0
- AOT_biomaps/AOT_Experiment/Tomography.py +505 -0
- AOT_biomaps/AOT_Experiment/__init__.py +9 -0
- AOT_biomaps/AOT_Experiment/_mainExperiment.py +532 -0
- AOT_biomaps/AOT_Optic/Absorber.py +24 -0
- AOT_biomaps/AOT_Optic/Laser.py +70 -0
- AOT_biomaps/AOT_Optic/OpticEnums.py +17 -0
- AOT_biomaps/AOT_Optic/__init__.py +10 -0
- AOT_biomaps/AOT_Optic/_mainOptic.py +204 -0
- AOT_biomaps/AOT_Recon/AOT_Optimizers/DEPIERRO.py +191 -0
- AOT_biomaps/AOT_Recon/AOT_Optimizers/LS.py +106 -0
- AOT_biomaps/AOT_Recon/AOT_Optimizers/MAPEM.py +456 -0
- AOT_biomaps/AOT_Recon/AOT_Optimizers/MLEM.py +333 -0
- AOT_biomaps/AOT_Recon/AOT_Optimizers/PDHG.py +221 -0
- AOT_biomaps/AOT_Recon/AOT_Optimizers/__init__.py +5 -0
- AOT_biomaps/AOT_Recon/AOT_PotentialFunctions/Huber.py +90 -0
- AOT_biomaps/AOT_Recon/AOT_PotentialFunctions/Quadratic.py +86 -0
- AOT_biomaps/AOT_Recon/AOT_PotentialFunctions/RelativeDifferences.py +59 -0
- AOT_biomaps/AOT_Recon/AOT_PotentialFunctions/__init__.py +3 -0
- AOT_biomaps/AOT_Recon/AlgebraicRecon.py +1023 -0
- AOT_biomaps/AOT_Recon/AnalyticRecon.py +154 -0
- AOT_biomaps/AOT_Recon/BayesianRecon.py +230 -0
- AOT_biomaps/AOT_Recon/DeepLearningRecon.py +35 -0
- AOT_biomaps/AOT_Recon/PrimalDualRecon.py +210 -0
- AOT_biomaps/AOT_Recon/ReconEnums.py +375 -0
- AOT_biomaps/AOT_Recon/ReconTools.py +273 -0
- AOT_biomaps/AOT_Recon/__init__.py +11 -0
- AOT_biomaps/AOT_Recon/_mainRecon.py +288 -0
- AOT_biomaps/Config.py +95 -0
- AOT_biomaps/Settings.py +45 -13
- AOT_biomaps/__init__.py +271 -18
- aot_biomaps-2.9.233.dist-info/METADATA +22 -0
- aot_biomaps-2.9.233.dist-info/RECORD +43 -0
- {AOT_biomaps-2.1.3.dist-info → aot_biomaps-2.9.233.dist-info}/WHEEL +1 -1
- AOT_biomaps/AOT_Acoustic.py +0 -1881
- AOT_biomaps/AOT_Experiment.py +0 -541
- AOT_biomaps/AOT_Optic.py +0 -219
- AOT_biomaps/AOT_Reconstruction.py +0 -1416
- AOT_biomaps/config.py +0 -54
- AOT_biomaps-2.1.3.dist-info/METADATA +0 -20
- AOT_biomaps-2.1.3.dist-info/RECORD +0 -11
- {AOT_biomaps-2.1.3.dist-info → aot_biomaps-2.9.233.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
from AOT_biomaps.Config import config
|
|
2
|
+
from AOT_biomaps.AOT_Experiment.Tomography import Tomography
|
|
3
|
+
from .ReconEnums import ReconType
|
|
4
|
+
from .ReconTools import mse, ssim
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import numpy as np
|
|
8
|
+
import matplotlib.pyplot as plt
|
|
9
|
+
from abc import ABC, abstractmethod
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Recon(ABC):
|
|
13
|
+
def __init__(self, experiment, saveDir = None, isGPU = config.get_process() == 'gpu', isMultiGPU = True if config.numGPUs > 1 else False, isMultiCPU = True):
|
|
14
|
+
self.reconPhantom = None
|
|
15
|
+
self.reconLaser = None
|
|
16
|
+
self.experiment = experiment
|
|
17
|
+
self.reconType = None
|
|
18
|
+
self.saveDir = saveDir
|
|
19
|
+
self.MSE = None
|
|
20
|
+
self.SSIM = None
|
|
21
|
+
self.CRC = None
|
|
22
|
+
|
|
23
|
+
self.isGPU = isGPU
|
|
24
|
+
self.isMultiGPU = isMultiGPU
|
|
25
|
+
self.isMultiCPU = isMultiCPU
|
|
26
|
+
|
|
27
|
+
if str(type(self.experiment)) != str(Tomography):
|
|
28
|
+
raise TypeError(f"Experiment must be of type {Tomography}")
|
|
29
|
+
|
|
30
|
+
@abstractmethod
|
|
31
|
+
def run(self,withTumor = True):
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
def save(self, withTumor=True, overwrite=False, date=None, show_logs=True):
|
|
35
|
+
"""
|
|
36
|
+
Save the reconstruction results (reconPhantom is with tumor, reconLaser is without tumor) and indices of the saved recon results, in numpy format.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
withTumor (bool): If True, saves reconPhantom. If False, saves reconLaser. Default is True.
|
|
40
|
+
overwrite (bool): If False, does not save if the file already exists. Default is False.
|
|
41
|
+
|
|
42
|
+
Warnings:
|
|
43
|
+
reconPhantom and reconLaser are lists of 2D numpy arrays, each array corresponding to one iteration.
|
|
44
|
+
"""
|
|
45
|
+
isExisting, filepath = self.checkExistingFile(date=date)
|
|
46
|
+
if isExisting and not overwrite:
|
|
47
|
+
return
|
|
48
|
+
|
|
49
|
+
filename = 'reconPhantom.npy' if withTumor else 'reconLaser.npy'
|
|
50
|
+
filepathRecon = os.path.join(filepath, filename)
|
|
51
|
+
|
|
52
|
+
if withTumor:
|
|
53
|
+
if not self.reconPhantom or len(self.reconPhantom) == 0:
|
|
54
|
+
raise ValueError("Reconstructed phantom is empty. Run reconstruction first.")
|
|
55
|
+
np.save(filepathRecon, np.array(self.reconPhantom))
|
|
56
|
+
else:
|
|
57
|
+
if not self.reconLaser or len(self.reconLaser) == 0:
|
|
58
|
+
raise ValueError("Reconstructed laser is empty. Run reconstruction first.")
|
|
59
|
+
np.save(filepathRecon, np.array(self.reconLaser))
|
|
60
|
+
|
|
61
|
+
if self.indices is not None and len(self.indices) > 0:
|
|
62
|
+
filepathIndices = os.path.join(filepath, "indices.npy")
|
|
63
|
+
np.save(filepathIndices, np.array(self.indices))
|
|
64
|
+
|
|
65
|
+
if show_logs:
|
|
66
|
+
print(f"Reconstruction results saved to {os.path.dirname(filepath)}")
|
|
67
|
+
|
|
68
|
+
@abstractmethod
|
|
69
|
+
def checkExistingFile(self, date = None):
|
|
70
|
+
pass
|
|
71
|
+
|
|
72
|
+
def calculateCRC(self, use_ROI=True):
|
|
73
|
+
"""
|
|
74
|
+
Computes the Contrast Recovery Coefficient (CRC) for all ROIs combined or globally.
|
|
75
|
+
For analytic reconstruction: returns a single CRC value.
|
|
76
|
+
For iterative reconstruction: returns a list of CRC values (one per iteration).
|
|
77
|
+
If iteration is specified, returns CRC for that specific iteration only.
|
|
78
|
+
|
|
79
|
+
:param iteration: Specific iteration index (optional). If None, computes for all iterations.
|
|
80
|
+
:param use_ROI: If True, computes CRC for all ROIs combined. If False, computes global CRC.
|
|
81
|
+
:return: CRC value or list of CRC values.
|
|
82
|
+
"""
|
|
83
|
+
if self.reconType is None:
|
|
84
|
+
raise ValueError("Run reconstruction first")
|
|
85
|
+
|
|
86
|
+
if self.reconLaser is None or self.reconLaser == []:
|
|
87
|
+
raise ValueError("Reconstructed laser is empty. Run reconstruction first.")
|
|
88
|
+
if self.reconPhantom is None or self.reconPhantom == []:
|
|
89
|
+
raise ValueError("Reconstructed phantom is empty. Run reconstruction first.")
|
|
90
|
+
|
|
91
|
+
# Handle empty reconstructions
|
|
92
|
+
if self.reconLaser is None or self.reconLaser == []:
|
|
93
|
+
print("Reconstructed laser is empty. Running reconstruction without tumor...")
|
|
94
|
+
self.run(withTumor=False, isSavingEachIteration=True)
|
|
95
|
+
|
|
96
|
+
# Get the ROI mask(s) from the phantom if needed
|
|
97
|
+
if use_ROI:
|
|
98
|
+
self.experiment.OpticImage.find_ROI()
|
|
99
|
+
global_mask = np.logical_or.reduce(self.experiment.OpticImage.maskList)
|
|
100
|
+
|
|
101
|
+
# Analytic reconstruction case
|
|
102
|
+
if self.reconType is ReconType.Analytic:
|
|
103
|
+
if use_ROI:
|
|
104
|
+
recon_ratio = np.mean(self.reconPhantom[global_mask]) / np.mean(self.reconLaser[global_mask])
|
|
105
|
+
lambda_ratio = np.mean(self.experiment.OpticImage.phantom[global_mask]) / np.mean(self.experiment.OpticImage.laser.intensity[global_mask])
|
|
106
|
+
else:
|
|
107
|
+
recon_ratio = np.mean(self.reconPhantom) / np.mean(self.reconLaser)
|
|
108
|
+
lambda_ratio = np.mean(self.experiment.OpticImage.phantom) / np.mean(self.experiment.OpticImage.laser.intensity)
|
|
109
|
+
|
|
110
|
+
self.CRC =(recon_ratio - 1) / (lambda_ratio - 1)
|
|
111
|
+
|
|
112
|
+
# Iterative reconstruction case
|
|
113
|
+
else:
|
|
114
|
+
iterations = range(len(self.reconPhantom))
|
|
115
|
+
|
|
116
|
+
crc_list = []
|
|
117
|
+
for it in iterations:
|
|
118
|
+
if use_ROI:
|
|
119
|
+
recon_ratio = np.mean(self.reconPhantom[it][global_mask]) / np.mean(self.reconLaser[it][global_mask])
|
|
120
|
+
lambda_ratio = np.mean(self.experiment.OpticImage.phantom[global_mask]) / np.mean(self.experiment.OpticImage.laser.intensity[global_mask])
|
|
121
|
+
else:
|
|
122
|
+
recon_ratio = np.mean(self.reconPhantom[it]) / np.mean(self.reconLaser[it])
|
|
123
|
+
lambda_ratio = np.mean(self.experiment.OpticImage.phantom) / np.mean(self.experiment.OpticImage.laser.intensity)
|
|
124
|
+
|
|
125
|
+
crc_list.append((recon_ratio - 1) / (lambda_ratio - 1))
|
|
126
|
+
|
|
127
|
+
self.CRC = crc_list
|
|
128
|
+
|
|
129
|
+
def calculateMSE(self):
|
|
130
|
+
"""
|
|
131
|
+
Calculate the Mean Squared Error (MSE) of the reconstruction.
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
mse: float or list of floats, Mean Squared Error of the reconstruction
|
|
135
|
+
"""
|
|
136
|
+
|
|
137
|
+
if self.reconPhantom is None or self.reconPhantom == []:
|
|
138
|
+
raise ValueError("Reconstructed phantom is empty. Run reconstruction first.")
|
|
139
|
+
|
|
140
|
+
if self.reconType in (ReconType.Analytic, ReconType.DeepLearning):
|
|
141
|
+
self.MSE = mse(self.experiment.OpticImage.phantom, self.reconPhantom)
|
|
142
|
+
|
|
143
|
+
elif self.reconType in (ReconType.Algebraic, ReconType.Bayesian, ReconType.Convex):
|
|
144
|
+
self.MSE = []
|
|
145
|
+
for theta in self.reconPhantom:
|
|
146
|
+
self.MSE.append(mse(self.experiment.OpticImage.phantom, theta))
|
|
147
|
+
|
|
148
|
+
def calculateSSIM(self):
|
|
149
|
+
"""
|
|
150
|
+
Calculate the Structural Similarity Index (SSIM) of the reconstruction.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
ssim: float or list of floats, Structural Similarity Index of the reconstruction
|
|
154
|
+
"""
|
|
155
|
+
|
|
156
|
+
if self.reconPhantom is None or self.reconPhantom == []:
|
|
157
|
+
raise ValueError("Reconstructed phantom is empty. Run reconstruction first.")
|
|
158
|
+
|
|
159
|
+
if self.reconType in (ReconType.Analytic, ReconType.DeepLearning):
|
|
160
|
+
data_range = self.reconPhantom.max() - self.reconPhantom.min()
|
|
161
|
+
self.SSIM = ssim(self.experiment.OpticImage.phantom, self.reconPhantom, data_range=data_range)
|
|
162
|
+
|
|
163
|
+
elif self.reconType in (ReconType.Algebraic, ReconType.Bayesian):
|
|
164
|
+
self.SSIM = []
|
|
165
|
+
for theta in self.reconPhantom:
|
|
166
|
+
data_range = theta.max() - theta.min()
|
|
167
|
+
ssim_value = ssim(self.experiment.OpticImage.phantom, theta, data_range=data_range)
|
|
168
|
+
self.SSIM.append(ssim_value)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def show(self, withTumor=True, savePath=None):
|
|
172
|
+
if withTumor:
|
|
173
|
+
if self.reconPhantom is None or self.reconPhantom == []:
|
|
174
|
+
raise ValueError("Reconstructed phantom with tumor is empty. Run reconstruction first.")
|
|
175
|
+
if isinstance(self.reconPhantom, list):
|
|
176
|
+
image = self.reconPhantom[-1]
|
|
177
|
+
else:
|
|
178
|
+
image = self.reconPhantom
|
|
179
|
+
if self.experiment.OpticImage is None:
|
|
180
|
+
fig, axs = plt.subplots(1, 1, figsize=(10, 10))
|
|
181
|
+
else:
|
|
182
|
+
fig, axs = plt.subplots(1, 2, figsize=(20, 10))
|
|
183
|
+
# Phantom original
|
|
184
|
+
im1 = axs[1].imshow(
|
|
185
|
+
self.experiment.OpticImage.phantom,
|
|
186
|
+
cmap='hot',
|
|
187
|
+
vmin=0,
|
|
188
|
+
vmax=1,
|
|
189
|
+
extent=(
|
|
190
|
+
self.experiment.params.general['Xrange'][0],
|
|
191
|
+
self.experiment.params.general['Xrange'][1],
|
|
192
|
+
self.experiment.params.general['Zrange'][1],
|
|
193
|
+
self.experiment.params.general['Zrange'][0]
|
|
194
|
+
),
|
|
195
|
+
aspect='equal'
|
|
196
|
+
)
|
|
197
|
+
axs[1].set_title("Phantom with tumor")
|
|
198
|
+
axs[1].set_xlabel("x (mm)", fontsize=12)
|
|
199
|
+
axs[1].set_ylabel("z (mm)", fontsize=12)
|
|
200
|
+
axs[1].tick_params(axis='both', which='major', labelsize=8)
|
|
201
|
+
# Phantom reconstruit
|
|
202
|
+
im0 = axs[0].imshow(
|
|
203
|
+
image,
|
|
204
|
+
cmap='hot',
|
|
205
|
+
vmin=0,
|
|
206
|
+
vmax=1,
|
|
207
|
+
extent=(
|
|
208
|
+
self.experiment.params.general['Xrange'][0],
|
|
209
|
+
self.experiment.params.general['Xrange'][1],
|
|
210
|
+
self.experiment.params.general['Zrange'][1],
|
|
211
|
+
self.experiment.params.general['Zrange'][0]
|
|
212
|
+
),
|
|
213
|
+
aspect='equal'
|
|
214
|
+
)
|
|
215
|
+
axs[0].set_title("Reconstructed phantom with tumor")
|
|
216
|
+
axs[0].set_xlabel("x (mm)", fontsize=12)
|
|
217
|
+
axs[0].set_ylabel("z (mm)", fontsize=12)
|
|
218
|
+
axs[0].tick_params(axis='both', which='major', labelsize=8)
|
|
219
|
+
axs[0].tick_params(axis='y', which='both', left=False, right=False, labelleft=False)
|
|
220
|
+
else:
|
|
221
|
+
if self.reconLaser is None or self.reconLaser == []:
|
|
222
|
+
raise ValueError("Reconstructed laser without tumor is empty. Run reconstruction first.")
|
|
223
|
+
if isinstance(self.reconLaser, list):
|
|
224
|
+
image = self.reconLaser[-1]
|
|
225
|
+
else:
|
|
226
|
+
image = self.reconLaser
|
|
227
|
+
if self.experiment.OpticImage is None:
|
|
228
|
+
fig, axs = plt.subplots(1, 1, figsize=(10, 10))
|
|
229
|
+
else:
|
|
230
|
+
fig, axs = plt.subplots(1, 2, figsize=(20, 10))
|
|
231
|
+
# Laser original
|
|
232
|
+
im1 = axs[1].imshow(
|
|
233
|
+
self.experiment.OpticImage.laser.intensity,
|
|
234
|
+
cmap='hot',
|
|
235
|
+
vmin=0,
|
|
236
|
+
vmax=np.max(self.experiment.OpticImage.laser.intensity),
|
|
237
|
+
extent=(
|
|
238
|
+
self.experiment.params.general['Xrange'][0],
|
|
239
|
+
self.experiment.params.general['Xrange'][1],
|
|
240
|
+
self.experiment.params.general['Zrange'][1],
|
|
241
|
+
self.experiment.params.general['Zrange'][0]
|
|
242
|
+
),
|
|
243
|
+
aspect='equal'
|
|
244
|
+
)
|
|
245
|
+
axs[1].set_title("Laser without tumor")
|
|
246
|
+
axs[1].set_xlabel("x (mm)", fontsize=12)
|
|
247
|
+
axs[1].set_ylabel("z (mm)", fontsize=12)
|
|
248
|
+
axs[1].tick_params(axis='both', which='major', labelsize=8)
|
|
249
|
+
# Laser reconstruit
|
|
250
|
+
im0 = axs[0].imshow(
|
|
251
|
+
image,
|
|
252
|
+
cmap='hot',
|
|
253
|
+
vmin=0,
|
|
254
|
+
vmax=np.max(self.experiment.OpticImage.laser.intensity),
|
|
255
|
+
extent=(
|
|
256
|
+
self.experiment.params.general['Xrange'][0],
|
|
257
|
+
self.experiment.params.general['Xrange'][1],
|
|
258
|
+
self.experiment.params.general['Zrange'][1],
|
|
259
|
+
self.experiment.params.general['Zrange'][0]
|
|
260
|
+
),
|
|
261
|
+
aspect='equal'
|
|
262
|
+
)
|
|
263
|
+
axs[0].set_title("Reconstructed laser without tumor")
|
|
264
|
+
axs[0].set_xlabel("x (mm)", fontsize=12)
|
|
265
|
+
axs[0].set_ylabel("z (mm)", fontsize=12)
|
|
266
|
+
axs[0].tick_params(axis='both', which='major', labelsize=8)
|
|
267
|
+
axs[0].tick_params(axis='y', which='both', left=False, right=False, labelleft=False)
|
|
268
|
+
|
|
269
|
+
# Colorbar commune
|
|
270
|
+
fig.subplots_adjust(bottom=0.2)
|
|
271
|
+
cbar_ax = fig.add_axes([0.25, 0.08, 0.5, 0.03])
|
|
272
|
+
cbar = fig.colorbar(im0, cax=cbar_ax, orientation='horizontal')
|
|
273
|
+
cbar.set_label('Normalized Intensity', fontsize=12)
|
|
274
|
+
cbar.ax.tick_params(labelsize=8)
|
|
275
|
+
|
|
276
|
+
plt.subplots_adjust(wspace=0.3)
|
|
277
|
+
|
|
278
|
+
if savePath is not None:
|
|
279
|
+
if not os.path.exists(savePath):
|
|
280
|
+
os.makedirs(savePath)
|
|
281
|
+
if withTumor:
|
|
282
|
+
plt.savefig(os.path.join(savePath, 'recon_with_tumor.png'), dpi=300, bbox_inches='tight')
|
|
283
|
+
else:
|
|
284
|
+
plt.savefig(os.path.join(savePath, 'recon_without_tumor.png'), dpi=300, bbox_inches='tight')
|
|
285
|
+
|
|
286
|
+
plt.show()
|
|
287
|
+
|
|
288
|
+
|
AOT_biomaps/Config.py
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
from pynvml import nvmlInit, nvmlDeviceGetCount, nvmlDeviceGetHandleByIndex, nvmlDeviceGetMemoryInfo, nvmlShutdown, NVMLError
|
|
2
|
+
import psutil
|
|
3
|
+
|
|
4
|
+
class Config:
|
|
5
|
+
_instance = None
|
|
6
|
+
|
|
7
|
+
def __new__(cls, *args, **kwargs):
|
|
8
|
+
if not cls._instance:
|
|
9
|
+
cls._instance = super(Config, cls).__new__(cls, *args, **kwargs)
|
|
10
|
+
return cls._instance
|
|
11
|
+
|
|
12
|
+
def __init__(self):
|
|
13
|
+
if not hasattr(self, 'initialized'):
|
|
14
|
+
self.initialized = True
|
|
15
|
+
self.numGPUs = 0
|
|
16
|
+
self.bestGPU = None
|
|
17
|
+
self.process = 'cpu' # Valeur par défaut
|
|
18
|
+
self.numCPUs = psutil.cpu_count(logical=False)
|
|
19
|
+
self.availableMemory = 100 - self.get_memory_usage()
|
|
20
|
+
self.batchSize = self.calculate_batch_size()
|
|
21
|
+
self._init_gpu()
|
|
22
|
+
|
|
23
|
+
def _init_gpu(self):
|
|
24
|
+
"""Initialise les informations liées au GPU."""
|
|
25
|
+
try:
|
|
26
|
+
nvmlInit()
|
|
27
|
+
self.numGPUs = nvmlDeviceGetCount()
|
|
28
|
+
if self.numGPUs > 0:
|
|
29
|
+
self.process = 'gpu'
|
|
30
|
+
self.bestGPU = self.select_best_gpu()
|
|
31
|
+
else:
|
|
32
|
+
self.process = 'cpu'
|
|
33
|
+
self.bestGPU = None
|
|
34
|
+
except NVMLError as e:
|
|
35
|
+
print(f"NVIDIA GPU not available: {e}")
|
|
36
|
+
self.process = 'cpu'
|
|
37
|
+
self.bestGPU = None
|
|
38
|
+
self.numGPUs = 0
|
|
39
|
+
except Exception as e:
|
|
40
|
+
print(f"Unexpected error during GPU initialization: {e}")
|
|
41
|
+
self.process = 'cpu'
|
|
42
|
+
self.bestGPU = None
|
|
43
|
+
self.numGPUs = 0
|
|
44
|
+
finally:
|
|
45
|
+
try:
|
|
46
|
+
nvmlShutdown()
|
|
47
|
+
except:
|
|
48
|
+
pass # Évite les erreurs si nvmlShutdown est appelé plusieurs fois
|
|
49
|
+
|
|
50
|
+
def set_process(self, process):
|
|
51
|
+
"""Définit le processus à utiliser ('cpu' ou 'gpu')."""
|
|
52
|
+
if process not in ['cpu', 'gpu']:
|
|
53
|
+
raise ValueError("process must be 'cpu' or 'gpu'")
|
|
54
|
+
self.process = process
|
|
55
|
+
|
|
56
|
+
def get_process(self):
|
|
57
|
+
"""Retourne le processus actuel ('cpu' ou 'gpu')."""
|
|
58
|
+
return self.process
|
|
59
|
+
|
|
60
|
+
def select_best_gpu(self):
|
|
61
|
+
"""Sélectionne le GPU avec le plus de mémoire disponible."""
|
|
62
|
+
try:
|
|
63
|
+
nvmlInit()
|
|
64
|
+
best_gpu = 0
|
|
65
|
+
max_memory = 0
|
|
66
|
+
for i in range(self.numGPUs):
|
|
67
|
+
handle = nvmlDeviceGetHandleByIndex(i)
|
|
68
|
+
mem_info = nvmlDeviceGetMemoryInfo(handle)
|
|
69
|
+
available_memory = mem_info.total - mem_info.used
|
|
70
|
+
if available_memory > max_memory:
|
|
71
|
+
max_memory = available_memory
|
|
72
|
+
best_gpu = i
|
|
73
|
+
return best_gpu
|
|
74
|
+
except NVMLError as e:
|
|
75
|
+
print(f"Failed to select GPU: {e}")
|
|
76
|
+
return 0 # Retourne le premier GPU par défaut en cas d'erreur
|
|
77
|
+
finally:
|
|
78
|
+
try:
|
|
79
|
+
nvmlShutdown()
|
|
80
|
+
except:
|
|
81
|
+
pass
|
|
82
|
+
|
|
83
|
+
def get_memory_usage(self):
|
|
84
|
+
"""Retourne l'utilisation actuelle de la mémoire RAM (en pourcentage)."""
|
|
85
|
+
return psutil.virtual_memory().percent
|
|
86
|
+
|
|
87
|
+
def calculate_batch_size(self, max_memory_usage=90, min_batch_size=1, max_batch_size=20):
|
|
88
|
+
"""Calcule dynamiquement la taille du batch en fonction de la mémoire disponible."""
|
|
89
|
+
if self.availableMemory > max_memory_usage:
|
|
90
|
+
return max_batch_size
|
|
91
|
+
else:
|
|
92
|
+
return max(min_batch_size, int((self.availableMemory / max_memory_usage) * max_batch_size))
|
|
93
|
+
|
|
94
|
+
# Initialisation unique de la configuration
|
|
95
|
+
config = Config()
|
AOT_biomaps/Settings.py
CHANGED
|
@@ -1,39 +1,71 @@
|
|
|
1
1
|
import yaml
|
|
2
2
|
|
|
3
|
-
# Définir la classe Paramètre
|
|
4
3
|
class Params:
|
|
5
4
|
def __init__(self, path):
|
|
6
|
-
config = self._initParams(path)
|
|
7
|
-
|
|
5
|
+
config = self._initParams(path)
|
|
6
|
+
print(f"Configuration loaded from {path}")
|
|
8
7
|
self.general = config.get('general', {})
|
|
9
8
|
self.acoustic = config.get('acoustic', {})
|
|
10
9
|
self.optic = config.get('optic', {})
|
|
11
10
|
self.reconstruction = config.get('reconstruction', {})
|
|
12
11
|
|
|
13
12
|
def __repr__(self):
|
|
14
|
-
return (f"Params(general={self.general}, acoustic={self.acoustic}, optic={self.optic}
|
|
13
|
+
return (f"Params(general={self.general}, acoustic={self.acoustic}, optic={self.optic}, "
|
|
14
|
+
f"reconstruction={self.reconstruction})")
|
|
15
15
|
|
|
16
16
|
def _initParams(self, path):
|
|
17
|
-
"""
|
|
18
|
-
Initialize parameters from the YAML configuration file.
|
|
19
|
-
"""
|
|
20
17
|
if not path.endswith('.yaml'):
|
|
21
18
|
raise ValueError("The configuration file must be a YAML file with a .yaml extension.")
|
|
22
|
-
|
|
23
19
|
try:
|
|
24
20
|
with open(path, 'r') as file:
|
|
25
21
|
config = yaml.safe_load(file)
|
|
26
22
|
if config is None:
|
|
27
23
|
raise ValueError("The configuration file is empty or not valid YAML.")
|
|
28
|
-
|
|
29
|
-
# Vérifiez si 'Parameters' est la clé racine
|
|
30
24
|
if 'Parameters' in config:
|
|
31
25
|
config = config['Parameters']
|
|
32
|
-
|
|
33
|
-
print("Configuration loaded:", config)
|
|
34
|
-
return config # Retourne le dictionnaire config
|
|
26
|
+
return config
|
|
35
27
|
except FileNotFoundError:
|
|
36
28
|
raise FileNotFoundError(f"The file {path} does not exist.")
|
|
37
29
|
except yaml.YAMLError as e:
|
|
38
30
|
raise ValueError(f"Error parsing YAML file: {e}")
|
|
39
31
|
|
|
32
|
+
def show_Parameters(self):
|
|
33
|
+
config = {
|
|
34
|
+
'general': self.general,
|
|
35
|
+
'acoustic': self.acoustic,
|
|
36
|
+
'optic': self.optic,
|
|
37
|
+
'reconstruction': self.reconstruction
|
|
38
|
+
}
|
|
39
|
+
self._print_config(config)
|
|
40
|
+
|
|
41
|
+
def _print_config(self, config, indent=0):
|
|
42
|
+
border = "+" + "-" * 100 + "+"
|
|
43
|
+
print(border)
|
|
44
|
+
print(f"|{' Configuration Loaded '.center(100)}|")
|
|
45
|
+
print(border)
|
|
46
|
+
categories = {
|
|
47
|
+
'General': config.get('general', {}),
|
|
48
|
+
'Acoustic': config.get('acoustic', {}),
|
|
49
|
+
'Optic': config.get('optic', {}),
|
|
50
|
+
'Reconstruction': config.get('reconstruction', {})
|
|
51
|
+
}
|
|
52
|
+
for category, params in categories.items():
|
|
53
|
+
print("|" + category.center(100) + "|")
|
|
54
|
+
print(border)
|
|
55
|
+
self._print_params(params, indent + 2)
|
|
56
|
+
print(border)
|
|
57
|
+
|
|
58
|
+
def _print_params(self, params, indent):
|
|
59
|
+
if isinstance(params, dict):
|
|
60
|
+
for key, value in params.items():
|
|
61
|
+
if isinstance(value, (dict, list)):
|
|
62
|
+
print(f"|{' ' * indent}{key}:")
|
|
63
|
+
self._print_params(value, indent + 2)
|
|
64
|
+
else:
|
|
65
|
+
print(f"|{' ' * indent}{key}: {value}")
|
|
66
|
+
elif isinstance(params, list):
|
|
67
|
+
for item in params:
|
|
68
|
+
if isinstance(item, (dict, list)):
|
|
69
|
+
self._print_params(item, indent)
|
|
70
|
+
else:
|
|
71
|
+
print(f"|{' ' * indent}- {item}")
|