AOT-biomaps 2.9.369__py3-none-any.whl → 2.9.371__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.
@@ -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
- Nt = ceil((self.params['Zrange'][1] - self.params['Zrange'][0])*float(params.acoustic['f_AQ']) / self.params['c0'])
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']*2:
514
+ if dx >= self.params['element_width']:
509
515
  dx = self.params['element_width'] / 2
510
- Nx = int(round((self.params['Xrange'][1] - self.params['Xrange'][0]) / dx))
511
- Nz = int(round((self.params['Zrange'][1] - self.params['Zrange'][0]) / dx))
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
- Nx = self.params['Nx']
514
- Nz = self.params['Nz']
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=[pml_x_size, pml_z_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
- Nx = int(round((self.params['Xrange'][1] - self.params['Xrange'][0]) / dx))
587
- Nz = int(round((self.params['Zrange'][1] - self.params['Zrange'][0]) / dx))
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
- Nx = self.params['Nx']
590
- Nz = self.params['Nz']
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
AOT_biomaps/__init__.py CHANGED
@@ -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.369'
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
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: AOT_biomaps
3
- Version: 2.9.369
3
+ Version: 2.9.371
4
4
  Summary: Acousto-Optic Tomography
5
5
  Home-page: https://github.com/LucasDuclos/AcoustoOpticTomography
6
6
  Author: Lucas Duclos
@@ -1,6 +1,6 @@
1
1
  AOT_biomaps/Config.py,sha256=ghEOP1n8aO1pR-su13wMeAZAxZRfry5hH67NbtZ8SqI,3614
2
2
  AOT_biomaps/Settings.py,sha256=v8fPhnvvcfBJP29m1RLOTEr3jndGLGwbUiORXmsj2Bo,2853
3
- AOT_biomaps/__init__.py,sha256=qNo3jQkKKpID9HpxLuAz_gw19IAoBcg7PznnId14N8Q,4400
3
+ AOT_biomaps/__init__.py,sha256=5BCQtYU7kd9K8LSAUm0sbNRwQAotBuQiaT3D2rC1SCI,4404
4
4
  AOT_biomaps/AOT_Acoustic/AcousticEnums.py,sha256=s5kXa6jKzbS4btwbubrVcynLOr0yg5tth5vL_FGfbMk,1802
5
5
  AOT_biomaps/AOT_Acoustic/AcousticTools.py,sha256=7kuWIIGyzZPQrzRI0zVvdwNUp7qKUE67yCYOMzSb0Ug,8283
6
6
  AOT_biomaps/AOT_Acoustic/FocusedWave.py,sha256=3kGKKDx_3Msy5COYqIwzROPORGWvNjw8UsDanBfkMXE,11037
@@ -8,7 +8,7 @@ AOT_biomaps/AOT_Acoustic/IrregularWave.py,sha256=yZhtxkR6zlciRcEpdTR0BAhvgQl40XH
8
8
  AOT_biomaps/AOT_Acoustic/PlaneWave.py,sha256=xza-rj5AUWDecLkGDxRcULrwZVWeBvGnEP2d51TyR04,1447
9
9
  AOT_biomaps/AOT_Acoustic/StructuredWave.py,sha256=DRTjD-zrmX12FHrvwOeEo-Rk1fHYm9gfCcebz4WhtXc,18930
10
10
  AOT_biomaps/AOT_Acoustic/__init__.py,sha256=t9M2rRqa_L9pk7W2FeELTkHEMuP4DBr4gBRldMqsQbg,491
11
- AOT_biomaps/AOT_Acoustic/_mainAcoustic.py,sha256=RdmhRF1i0KAlpsP7_wnZ7F4J27br3eUc4XR91Qq7C64,44158
11
+ AOT_biomaps/AOT_Acoustic/_mainAcoustic.py,sha256=7P1UCrKaJ7smvOCYzJ1XIChvPqYSV2esIK39TVnr5Go,46150
12
12
  AOT_biomaps/AOT_Experiment/ExperimentTools.py,sha256=aFvJw6J_jfFVTDFnG7J3a61SHEgORdZKZS0UI82VMaY,2637
13
13
  AOT_biomaps/AOT_Experiment/Focus.py,sha256=B2nBawmv-NG2AWJx9zgQ8GlN6aFB9FwTSqX-M-phKXg,3193
14
14
  AOT_biomaps/AOT_Experiment/Tomography.py,sha256=9mJDwV9WVphoX8drL7MgN3WhS6fjYwS6HWQD3x1CrVs,37625
@@ -21,14 +21,14 @@ AOT_biomaps/AOT_Optic/__init__.py,sha256=HSUVhfz0NzwHHZZ9KP9Xyfu33IgP_rYJX86J-gE
21
21
  AOT_biomaps/AOT_Optic/_mainOptic.py,sha256=Wk63CcgWbU-ygMfjNK80islaUbGGJpTXgZY3_C2KQNY,8179
22
22
  AOT_biomaps/AOT_Recon/AOT_biomaps_kernels.cubin,sha256=JWy-bdtBTZdnNlDbJGZKwXyF-2u1wICtmlOC_YxEL6o,82528
23
23
  AOT_biomaps/AOT_Recon/AlgebraicRecon.py,sha256=CGBXZyYEZ3TOTFOKSt-h7NGuFbuI9PNr3YTWTbSLxDo,46832
24
- AOT_biomaps/AOT_Recon/AnalyticRecon.py,sha256=0Y--McisWqKZTDF86eLxPaVgWlSLp_f-b7HsEOmkxOM,18097
24
+ AOT_biomaps/AOT_Recon/AnalyticRecon.py,sha256=z4VJtqL-atoZLflG7vQKHNeTXXjhYG_us8l0xfo5XsU,14514
25
25
  AOT_biomaps/AOT_Recon/BayesianRecon.py,sha256=RnnPa-tTcvirwiNPnCRZnSM4NWeEEltYET-piBbp34g,12671
26
26
  AOT_biomaps/AOT_Recon/DeepLearningRecon.py,sha256=RfVcEsi4GeGqJn0_SPxwQPQx6IQjin79WKh2UarMRLI,1383
27
27
  AOT_biomaps/AOT_Recon/PrimalDualRecon.py,sha256=JbFhxiyUoSTnlJgHbOWIfUUwhwfZoi39RJMnfkagegY,16504
28
28
  AOT_biomaps/AOT_Recon/ReconEnums.py,sha256=KAf55RqHAr2ilt6pxFrUBGQOn-7HA8NP6TyL-1FNiXo,19714
29
29
  AOT_biomaps/AOT_Recon/ReconTools.py,sha256=CV2BwdEwvNd3B02G5LYoKsRGlONwIupuv617S2AOWZE,25322
30
30
  AOT_biomaps/AOT_Recon/__init__.py,sha256=xs_argJqXKFl76xP7-jiUc1ynOEEtY7XZ0gDxD5uVZc,246
31
- AOT_biomaps/AOT_Recon/_mainRecon.py,sha256=nBL4V__MrClHtaRCvsO16xE8Dy8LylbGkwFkvKRyV_g,14408
31
+ AOT_biomaps/AOT_Recon/_mainRecon.py,sha256=hubU5SWEeAv94k_DNbdze4wfUeBw-4smboqRyzlmy_k,18058
32
32
  AOT_biomaps/AOT_Recon/AOT_Optimizers/DEPIERRO.py,sha256=qA1n722GLQJH3V8HcLr5q_GxEwBS_NRlIT3E6JZk-Ag,9479
33
33
  AOT_biomaps/AOT_Recon/AOT_Optimizers/LS.py,sha256=bCu1rKzFXPbYQ7jV3L3E_jVQpb6LIEC5MIlN1-mCNdY,22814
34
34
  AOT_biomaps/AOT_Recon/AOT_Optimizers/MAPEM.py,sha256=vQLCB0L4FSXJKn2_6kdIdWrI6WZ82KuqUh7CSqBGVuo,25766
@@ -42,7 +42,7 @@ AOT_biomaps/AOT_Recon/AOT_PotentialFunctions/__init__.py,sha256=RwrJdLOFbAFBFnRx
42
42
  AOT_biomaps/AOT_Recon/AOT_SparseSMatrix/SparseSMatrix_CSR.py,sha256=RACc2P5oxmp0uPLAGnNj9mEtAxa_OlepNgCawKij3jI,12062
43
43
  AOT_biomaps/AOT_Recon/AOT_SparseSMatrix/SparseSMatrix_SELL.py,sha256=ti3dZQsb_Uu62C7Bn65Z-yf-R5NKCFsmnBT5GlLd_HY,15138
44
44
  AOT_biomaps/AOT_Recon/AOT_SparseSMatrix/__init__.py,sha256=8nou-hqjQjuCTLhoL5qv4EM_lMPFviAZAZKSPhi84jE,67
45
- aot_biomaps-2.9.369.dist-info/METADATA,sha256=nh-60m3Ov7--SWNt6P581a6PhQq6BXPnR7_8Cyd6THo,700
46
- aot_biomaps-2.9.369.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
47
- aot_biomaps-2.9.369.dist-info/top_level.txt,sha256=6STF-lT4kaAnBHJYCripmN5mZABoHjMuY689JdiDphk,12
48
- aot_biomaps-2.9.369.dist-info/RECORD,,
45
+ aot_biomaps-2.9.371.dist-info/METADATA,sha256=lrlpfF_LlYs1yvZnwsFF_xWaA4oTaaaOhwxG-iXias4,700
46
+ aot_biomaps-2.9.371.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
47
+ aot_biomaps-2.9.371.dist-info/top_level.txt,sha256=6STF-lT4kaAnBHJYCripmN5mZABoHjMuY689JdiDphk,12
48
+ aot_biomaps-2.9.371.dist-info/RECORD,,