AOT-biomaps 2.9.369__tar.gz → 2.9.371__tar.gz
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.
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Acoustic/_mainAcoustic.py +43 -15
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/AnalyticRecon.py +0 -85
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/_mainRecon.py +86 -3
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/__init__.py +3 -1
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps.egg-info/PKG-INFO +1 -1
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/PKG-INFO +1 -1
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/setup.py +3 -1
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Acoustic/AcousticEnums.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Acoustic/AcousticTools.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Acoustic/FocusedWave.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Acoustic/IrregularWave.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Acoustic/PlaneWave.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Acoustic/StructuredWave.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Acoustic/__init__.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Experiment/ExperimentTools.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Experiment/Focus.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Experiment/Tomography.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Experiment/__init__.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Experiment/_mainExperiment.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Optic/Absorber.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Optic/Laser.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Optic/OpticEnums.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Optic/__init__.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Optic/_mainOptic.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/AOT_Optimizers/DEPIERRO.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/AOT_Optimizers/LS.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/AOT_Optimizers/MAPEM.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/AOT_Optimizers/MLEM.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/AOT_Optimizers/PDHG.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/AOT_Optimizers/__init__.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/AOT_PotentialFunctions/Huber.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/AOT_PotentialFunctions/Quadratic.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/AOT_PotentialFunctions/RelativeDifferences.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/AOT_PotentialFunctions/__init__.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/AOT_SparseSMatrix/SparseSMatrix_CSR.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/AOT_SparseSMatrix/SparseSMatrix_SELL.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/AOT_SparseSMatrix/__init__.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/AOT_biomaps_kernels.cubin +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/AlgebraicRecon.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/BayesianRecon.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/DeepLearningRecon.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/PrimalDualRecon.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/ReconEnums.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/ReconTools.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/__init__.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/Config.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/Settings.py +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps.egg-info/SOURCES.txt +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps.egg-info/dependency_links.txt +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps.egg-info/requires.txt +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps.egg-info/top_level.txt +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/README.md +0 -0
- {aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/setup.cfg +0 -0
|
@@ -93,6 +93,8 @@ class AcousticField(ABC):
|
|
|
93
93
|
'num_elements': params.acoustic['num_elements'],
|
|
94
94
|
'element_width': params.acoustic['element_width'],
|
|
95
95
|
'element_height': params.acoustic['element_height'],
|
|
96
|
+
'height_phantom': params.acoustic.phantom['height'] if 'phantom' in params.acoustic and 'height' in params.acoustic.phantom else None,
|
|
97
|
+
'width_phantom': params.acoustic.phantom['width'] if 'phantom' in params.acoustic and 'width' in params.acoustic.phantom else None,
|
|
96
98
|
'Xrange': params.general['Xrange'],
|
|
97
99
|
'Yrange': params.general['Yrange'],
|
|
98
100
|
'Zrange': params.general['Zrange'],
|
|
@@ -104,6 +106,7 @@ class AcousticField(ABC):
|
|
|
104
106
|
'Nx': int(np.round((params.general['Xrange'][1] - params.general['Xrange'][0])/params.general['dx'])),
|
|
105
107
|
'Ny': int(np.round((params.general['Yrange'][1] - params.general['Yrange'][0])/params.general['dy'])) if params.general['Yrange'] is not None else 1,
|
|
106
108
|
'Nz': int(np.round((params.general['Zrange'][1] - params.general['Zrange'][0])/params.general['dz'])),
|
|
109
|
+
'Nt': params.general['Nt'] if 'Nt' in params.general else None,
|
|
107
110
|
'probeWidth': params.acoustic['num_elements'] * params.acoustic['element_width'],
|
|
108
111
|
'IsAbsorbingMedium': params.acoustic['isAbsorbingMedium'],
|
|
109
112
|
}
|
|
@@ -114,8 +117,11 @@ class AcousticField(ABC):
|
|
|
114
117
|
|
|
115
118
|
self.params['f_AQ'] = int(1/self.kgrid.dt)
|
|
116
119
|
else:
|
|
117
|
-
|
|
118
|
-
|
|
120
|
+
if self.params['Nt'] is None:
|
|
121
|
+
Nt = ceil((self.params['Zrange'][1] - self.params['Zrange'][0])*float(params.acoustic['f_AQ']) / self.params['c0'])
|
|
122
|
+
self.params['Nt'] = Nt
|
|
123
|
+
else:
|
|
124
|
+
Nt = self.params['Nt']
|
|
119
125
|
self.kgrid.setTime(Nt,1/float(params.acoustic['f_AQ']))
|
|
120
126
|
self.params['f_AQ'] = int(float(params.acoustic['f_AQ']))
|
|
121
127
|
|
|
@@ -505,13 +511,25 @@ class AcousticField(ABC):
|
|
|
505
511
|
try:
|
|
506
512
|
# --- 1. Grid setup ---
|
|
507
513
|
dx = self.params['dx']
|
|
508
|
-
if dx >= self.params['element_width']
|
|
514
|
+
if dx >= self.params['element_width']:
|
|
509
515
|
dx = self.params['element_width'] / 2
|
|
510
|
-
|
|
511
|
-
|
|
516
|
+
if self.params['width_phantom'] is not None:
|
|
517
|
+
Nx = int(np.round((self.params['width_phantom'])/dx))
|
|
518
|
+
else:
|
|
519
|
+
Nx = int(round((self.params['Xrange'][1] - self.params['Xrange'][0]) / dx))
|
|
520
|
+
if self.params['height_phantom'] is not None:
|
|
521
|
+
Nz = int(np.round((self.params['height_phantom'])/dx))
|
|
522
|
+
else:
|
|
523
|
+
Nz = int(round((self.params['Zrange'][1] - self.params['Zrange'][0]) / dx))
|
|
512
524
|
else:
|
|
513
|
-
|
|
514
|
-
|
|
525
|
+
if self.params['width_phantom'] is not None:
|
|
526
|
+
Nx = int(np.round((self.params['width_phantom'])/self.params['dx']))
|
|
527
|
+
else:
|
|
528
|
+
Nx = int(round((self.params['Xrange'][1] - self.params['Xrange'][0]) / self.params['dx']))
|
|
529
|
+
if self.params['height_phantom'] is not None:
|
|
530
|
+
Nz = int(np.round((self.params['height_phantom'])/self.params['dz']))
|
|
531
|
+
else:
|
|
532
|
+
Nz = int(round((self.params['Zrange'][1] - self.params['Zrange'][0]) / self.params['dz']))
|
|
515
533
|
|
|
516
534
|
# --- 2. Time and space factors ---
|
|
517
535
|
self.factorT = int(np.ceil(self.params['f_AQ'] / self.params['f_saving']))
|
|
@@ -530,17 +548,15 @@ class AcousticField(ABC):
|
|
|
530
548
|
sensor.mask = np.ones((Nx, Nz))
|
|
531
549
|
|
|
532
550
|
# --- 5. PML setup ---
|
|
533
|
-
total_size_x = next_power_of_2(Nx)
|
|
534
551
|
total_size_z = next_power_of_2(Nz)
|
|
535
|
-
pml_x_size = (total_size_x - Nx) // 2
|
|
536
552
|
pml_z_size = (total_size_z - Nz) // 2
|
|
537
|
-
pml_x_size = max(pml_x_size, 50) # Ensure a minimum PML size of 50 grid points to avoid parasitic reflections
|
|
538
553
|
pml_z_size = max(pml_z_size, 50) # Ensure a minimum PML size of 50 grid points to avoid parasitic reflections
|
|
539
554
|
|
|
540
555
|
# --- 6. Simulation options ---
|
|
541
556
|
simulation_options = SimulationOptions(
|
|
542
557
|
pml_inside=False,
|
|
543
|
-
pml_size=[
|
|
558
|
+
pml_size=[0, pml_z_size],
|
|
559
|
+
pml_header=True,
|
|
544
560
|
use_sg=False,
|
|
545
561
|
save_to_disk=True,
|
|
546
562
|
input_filename=os.path.join(gettempdir(), "KwaveIN.h5"),
|
|
@@ -583,11 +599,23 @@ class AcousticField(ABC):
|
|
|
583
599
|
dx = self.params['dx']
|
|
584
600
|
if dx >= self.params['element_width']:
|
|
585
601
|
dx = self.params['element_width'] / 2
|
|
586
|
-
|
|
587
|
-
|
|
602
|
+
if self.params['width_phantom'] is not None:
|
|
603
|
+
Nx = int(np.round((self.params['width_phantom'])/dx))
|
|
604
|
+
else:
|
|
605
|
+
Nx = int(round((self.params['Xrange'][1] - self.params['Xrange'][0]) / dx))
|
|
606
|
+
if self.params['height_phantom'] is not None:
|
|
607
|
+
Nz = int(np.round((self.params['height_phantom'])/dx))
|
|
608
|
+
else:
|
|
609
|
+
Nz = int(round((self.params['Zrange'][1] - self.params['Zrange'][0]) / dx))
|
|
588
610
|
else:
|
|
589
|
-
|
|
590
|
-
|
|
611
|
+
if self.params['width_phantom'] is not None:
|
|
612
|
+
Nx = int(np.round((self.params['width_phantom'])/self.params['dx']))
|
|
613
|
+
else:
|
|
614
|
+
Nx = int(round((self.params['Xrange'][1] - self.params['Xrange'][0]) / self.params['dx']))
|
|
615
|
+
if self.params['height_phantom'] is not None:
|
|
616
|
+
Nz = int(np.round((self.params['height_phantom'])/self.params['dz']))
|
|
617
|
+
else:
|
|
618
|
+
Nz = int(round((self.params['Zrange'][1] - self.params['Zrange'][0]) / self.params['dz']))
|
|
591
619
|
|
|
592
620
|
# --- 2. Time and space factors (common) ---
|
|
593
621
|
factorT = int(np.ceil(self.params['f_AQ'] / self.params['f_saving']))
|
|
@@ -18,91 +18,6 @@ class AnalyticRecon(Recon):
|
|
|
18
18
|
self.Lc = Lc # in meters
|
|
19
19
|
self.AOsignal_demoldulated = None
|
|
20
20
|
|
|
21
|
-
def parse_and_demodulate(self, withTumor=True):
|
|
22
|
-
|
|
23
|
-
if withTumor:
|
|
24
|
-
AOsignal = self.experiment.AOsignal_withTumor
|
|
25
|
-
else:
|
|
26
|
-
AOsignal = self.experiment.AOsignal_withoutTumor
|
|
27
|
-
delta_x = self.experiment.params.general['dx'] # en m
|
|
28
|
-
n_piezos = self.experiment.params.acoustic['num_elements']
|
|
29
|
-
demodulated_data = {}
|
|
30
|
-
structured_buffer = {}
|
|
31
|
-
|
|
32
|
-
for i in trange(len(self.experiment.AcousticFields), desc="Demodulating AO signals"):
|
|
33
|
-
label = self.experiment.AcousticFields[i].getName_field()
|
|
34
|
-
|
|
35
|
-
parts = label.split("_")
|
|
36
|
-
hex_pattern = parts[0]
|
|
37
|
-
angle_code = parts[-1]
|
|
38
|
-
|
|
39
|
-
# Angle
|
|
40
|
-
if angle_code.startswith("1"):
|
|
41
|
-
angle_deg = -int(angle_code[1:])
|
|
42
|
-
else:
|
|
43
|
-
angle_deg = int(angle_code)
|
|
44
|
-
angle_rad = np.deg2rad(angle_deg)
|
|
45
|
-
|
|
46
|
-
# Onde Plane (f_s = 0)
|
|
47
|
-
if set(hex_pattern.lower().replace(" ", "")) == {'f'}:
|
|
48
|
-
fs_key = 0.0 # fs_key est en mm^-1 (0.0 mm^-1)
|
|
49
|
-
demodulated_data[(fs_key, angle_rad)] = np.array(AOsignal[:,i])
|
|
50
|
-
continue
|
|
51
|
-
|
|
52
|
-
# Onde Structurée
|
|
53
|
-
profile = hex_to_binary_profile(hex_pattern, n_piezos)
|
|
54
|
-
|
|
55
|
-
# Calcul FS (Fréquence de Structuration)
|
|
56
|
-
ft_prof = np.fft.fft(profile)
|
|
57
|
-
# On regarde uniquement la partie positive non DC
|
|
58
|
-
idx_max = np.argmax(np.abs(ft_prof[1:len(profile)//2])) + 1
|
|
59
|
-
freqs = np.fft.fftfreq(len(profile), d=delta_x)
|
|
60
|
-
|
|
61
|
-
# freqs est en m^-1 car delta_x est en mètres.
|
|
62
|
-
fs_m_inv = abs(freqs[idx_max])
|
|
63
|
-
|
|
64
|
-
# *** CORRECTION 1: Conversion de f_s en mm^-1 (mm^-1 est utilisé dans iRadon) ***
|
|
65
|
-
fs_key = fs_m_inv / 1000.0 # Fréquence spatiale en mm^-1
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if fs_key == 0: continue
|
|
69
|
-
|
|
70
|
-
# Calcul de la Phase (Shift)
|
|
71
|
-
phase = get_phase_deterministic(profile)
|
|
72
|
-
|
|
73
|
-
# Stockage par (fs, theta) et phase
|
|
74
|
-
key = (fs_key, angle_rad)
|
|
75
|
-
if key not in structured_buffer:
|
|
76
|
-
structured_buffer[key] = {}
|
|
77
|
-
|
|
78
|
-
# La moyenne est nécessaire si plusieurs acquisitions ont la même phase (pour le SNR)
|
|
79
|
-
if phase in structured_buffer[key]:
|
|
80
|
-
structured_buffer[key][phase] = (structured_buffer[key][phase] + np.array(AOsignal[:,i])) / 2
|
|
81
|
-
else:
|
|
82
|
-
structured_buffer[key][phase] = np.array(AOsignal[:,i])
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
for (fs, theta), phases in structured_buffer.items():
|
|
87
|
-
s0 = phases.get(0.0, 0)
|
|
88
|
-
s_pi_2 = phases.get(np.pi/2, 0)
|
|
89
|
-
s_pi = phases.get(np.pi, 0)
|
|
90
|
-
s_3pi_2 = phases.get(3*np.pi/2, 0)
|
|
91
|
-
|
|
92
|
-
# Assurer que les zéros sont des vecteurs de la bonne taille
|
|
93
|
-
example = next(val for val in phases.values() if not isinstance(val, int))
|
|
94
|
-
if isinstance(s0, int): s0 = np.zeros_like(example)
|
|
95
|
-
if isinstance(s_pi, int): s_pi = np.zeros_like(example)
|
|
96
|
-
if isinstance(s_pi_2, int): s_pi_2 = np.zeros_like(example)
|
|
97
|
-
if isinstance(s_3pi_2, int): s_3pi_2 = np.zeros_like(example)
|
|
98
|
-
|
|
99
|
-
real = s0 - s_pi
|
|
100
|
-
imag = s_pi_2 - s_3pi_2
|
|
101
|
-
|
|
102
|
-
demodulated_data[(fs, theta)] = (real - 1j * imag) / (2/np.pi)
|
|
103
|
-
|
|
104
|
-
return demodulated_data
|
|
105
|
-
|
|
106
21
|
def run(self, processType = ProcessType.PYTHON, withTumor= True):
|
|
107
22
|
"""
|
|
108
23
|
This method is a placeholder for the analytic reconstruction process.
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
from AOT_biomaps.Config import config
|
|
2
|
-
from AOT_biomaps.AOT_Experiment.Tomography import Tomography
|
|
2
|
+
from AOT_biomaps.AOT_Experiment.Tomography import Tomography, hex_to_binary_profile
|
|
3
3
|
from .ReconEnums import ReconType
|
|
4
|
-
from .ReconTools import mse, ssim
|
|
4
|
+
from .ReconTools import mse, ssim, get_phase_deterministic
|
|
5
5
|
|
|
6
6
|
import os
|
|
7
7
|
import numpy as np
|
|
8
8
|
import matplotlib.pyplot as plt
|
|
9
9
|
from abc import ABC, abstractmethod
|
|
10
|
+
from tqdm import trange
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
class Recon(ABC):
|
|
@@ -166,7 +167,6 @@ class Recon(ABC):
|
|
|
166
167
|
ssim_value = ssim(self.experiment.OpticImage.phantom, theta, data_range=data_range)
|
|
167
168
|
self.SSIM.append(ssim_value)
|
|
168
169
|
|
|
169
|
-
|
|
170
170
|
def show(self, withTumor=True, savePath=None, scale='same'):
|
|
171
171
|
"""
|
|
172
172
|
Display the reconstructed images.
|
|
@@ -308,4 +308,87 @@ class Recon(ABC):
|
|
|
308
308
|
|
|
309
309
|
plt.show()
|
|
310
310
|
|
|
311
|
+
def parse_and_demodulate(self, withTumor=True):
|
|
311
312
|
|
|
313
|
+
if withTumor:
|
|
314
|
+
AOsignal = self.experiment.AOsignal_withTumor
|
|
315
|
+
else:
|
|
316
|
+
AOsignal = self.experiment.AOsignal_withoutTumor
|
|
317
|
+
delta_x = self.experiment.params.general['dx'] # en m
|
|
318
|
+
n_piezos = self.experiment.params.acoustic['num_elements']
|
|
319
|
+
demodulated_data = {}
|
|
320
|
+
structured_buffer = {}
|
|
321
|
+
|
|
322
|
+
for i in trange(len(self.experiment.AcousticFields), desc="Demodulating AO signals"):
|
|
323
|
+
label = self.experiment.AcousticFields[i].getName_field()
|
|
324
|
+
|
|
325
|
+
parts = label.split("_")
|
|
326
|
+
hex_pattern = parts[0]
|
|
327
|
+
angle_code = parts[-1]
|
|
328
|
+
|
|
329
|
+
# Angle
|
|
330
|
+
if angle_code.startswith("1"):
|
|
331
|
+
angle_deg = -int(angle_code[1:])
|
|
332
|
+
else:
|
|
333
|
+
angle_deg = int(angle_code)
|
|
334
|
+
angle_rad = np.deg2rad(angle_deg)
|
|
335
|
+
|
|
336
|
+
# Onde Plane (f_s = 0)
|
|
337
|
+
if set(hex_pattern.lower().replace(" ", "")) == {'f'}:
|
|
338
|
+
fs_key = 0.0 # fs_key est en mm^-1 (0.0 mm^-1)
|
|
339
|
+
demodulated_data[(fs_key, angle_rad)] = np.array(AOsignal[:,i])
|
|
340
|
+
continue
|
|
341
|
+
|
|
342
|
+
# Onde Structurée
|
|
343
|
+
profile = hex_to_binary_profile(hex_pattern, n_piezos)
|
|
344
|
+
|
|
345
|
+
# Calcul FS (Fréquence de Structuration)
|
|
346
|
+
ft_prof = np.fft.fft(profile)
|
|
347
|
+
# On regarde uniquement la partie positive non DC
|
|
348
|
+
idx_max = np.argmax(np.abs(ft_prof[1:len(profile)//2])) + 1
|
|
349
|
+
freqs = np.fft.fftfreq(len(profile), d=delta_x)
|
|
350
|
+
|
|
351
|
+
# freqs est en m^-1 car delta_x est en mètres.
|
|
352
|
+
fs_m_inv = abs(freqs[idx_max])
|
|
353
|
+
|
|
354
|
+
# *** CORRECTION 1: Conversion de f_s en mm^-1 (mm^-1 est utilisé dans iRadon) ***
|
|
355
|
+
fs_key = fs_m_inv / 1000.0 # Fréquence spatiale en mm^-1
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
if fs_key == 0: continue
|
|
359
|
+
|
|
360
|
+
# Calcul de la Phase (Shift)
|
|
361
|
+
phase = get_phase_deterministic(profile)
|
|
362
|
+
|
|
363
|
+
# Stockage par (fs, theta) et phase
|
|
364
|
+
key = (fs_key, angle_rad)
|
|
365
|
+
if key not in structured_buffer:
|
|
366
|
+
structured_buffer[key] = {}
|
|
367
|
+
|
|
368
|
+
# La moyenne est nécessaire si plusieurs acquisitions ont la même phase (pour le SNR)
|
|
369
|
+
if phase in structured_buffer[key]:
|
|
370
|
+
structured_buffer[key][phase] = (structured_buffer[key][phase] + np.array(AOsignal[:,i])) / 2
|
|
371
|
+
else:
|
|
372
|
+
structured_buffer[key][phase] = np.array(AOsignal[:,i])
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
for (fs, theta), phases in structured_buffer.items():
|
|
377
|
+
s0 = phases.get(0.0, 0)
|
|
378
|
+
s_pi_2 = phases.get(np.pi/2, 0)
|
|
379
|
+
s_pi = phases.get(np.pi, 0)
|
|
380
|
+
s_3pi_2 = phases.get(3*np.pi/2, 0)
|
|
381
|
+
|
|
382
|
+
# Assurer que les zéros sont des vecteurs de la bonne taille
|
|
383
|
+
example = next(val for val in phases.values() if not isinstance(val, int))
|
|
384
|
+
if isinstance(s0, int): s0 = np.zeros_like(example)
|
|
385
|
+
if isinstance(s_pi, int): s_pi = np.zeros_like(example)
|
|
386
|
+
if isinstance(s_pi_2, int): s_pi_2 = np.zeros_like(example)
|
|
387
|
+
if isinstance(s_3pi_2, int): s_3pi_2 = np.zeros_like(example)
|
|
388
|
+
|
|
389
|
+
real = s0 - s_pi
|
|
390
|
+
imag = s_pi_2 - s_3pi_2
|
|
391
|
+
|
|
392
|
+
demodulated_data[(fs, theta)] = (real - 1j * imag) / (2/np.pi)
|
|
393
|
+
|
|
394
|
+
return demodulated_data
|
|
@@ -85,7 +85,7 @@ from .AOT_Recon.AOT_PotentialFunctions.RelativeDifferences import *
|
|
|
85
85
|
from .Config import config
|
|
86
86
|
from .Settings import *
|
|
87
87
|
|
|
88
|
-
__version__ = '2.9.
|
|
88
|
+
__version__ = '2.9.371'
|
|
89
89
|
__process__ = config.get_process()
|
|
90
90
|
|
|
91
91
|
def initialize(process=None):
|
|
@@ -230,6 +230,8 @@ def initialize(process=None):
|
|
|
230
230
|
|
|
231
231
|
|
|
232
232
|
|
|
233
|
+
|
|
234
|
+
|
|
233
235
|
|
|
234
236
|
|
|
235
237
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/AOT_Optimizers/DEPIERRO.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/AOT_Optimizers/__init__.py
RENAMED
|
File without changes
|
{aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/AOT_PotentialFunctions/Huber.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/AOT_PotentialFunctions/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aot_biomaps-2.9.369 → aot_biomaps-2.9.371}/AOT_biomaps/AOT_Recon/AOT_SparseSMatrix/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|