AOT-biomaps 2.9.384__py3-none-any.whl → 2.9.386__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.
@@ -563,8 +563,6 @@ class AcousticField(ABC):
563
563
  kgrid.setTime(self.kgrid.Nt, dt) # Garder Nt constant
564
564
 
565
565
  factorT = int(np.ceil((1/dt) / (self.params['f_saving'])))
566
- print(f"factorT: {factorT}")
567
- print(f"dt: {dt}")
568
566
 
569
567
  source = kSource()
570
568
  source.p_mask = np.zeros((Nx, Nz))
@@ -554,7 +554,6 @@ def CP_TV_Tikhonov_sparseSELL_pycuda(
554
554
  pass
555
555
  raise
556
556
 
557
-
558
557
  def CP_KL(
559
558
  SMatrix,
560
559
  y,
@@ -649,4 +648,248 @@ def CP_KL(
649
648
  if isSavingEachIteration:
650
649
  return I_reconMatrix, saved_indices
651
650
  else:
652
- return I_reconMatrix[-1], None
651
+ return I_reconMatrix[-1], None
652
+
653
+ def CP_TV_Tikhonov_Preconditioned_SELL_pycuda(
654
+ SMatrix,
655
+ y,
656
+ alpha=None, # TV param
657
+ beta=1e-4, # Tikhonov param
658
+ numIterations=2000,
659
+ isSavingEachIteration=True,
660
+ tumor_str="",
661
+ device=None,
662
+ max_saves=2000,
663
+ show_logs=True,
664
+ k_security=1.0, # Pock condition: tau*sigma * ||A||^2 < 1. Avec precond, souvent k=1.0 suffit.
665
+ apply_positivity_clamp=True
666
+ ):
667
+
668
+ if SMatrix.ctx:
669
+ SMatrix.ctx.push()
670
+
671
+ dtype = np.float32
672
+ TN = int(SMatrix.N * SMatrix.T)
673
+ ZX = int(SMatrix.Z * SMatrix.X)
674
+ Z, X = SMatrix.Z, SMatrix.X
675
+ block_size = 256
676
+
677
+ # --- Récupération des Kernels (Existants + Nouveaux) ---
678
+ projection_kernel = SMatrix.sparse_mod.get_function("projection_kernel__SELL")
679
+ backprojection_kernel = SMatrix.sparse_mod.get_function("backprojection_kernel__SELL")
680
+ axpby_kernel = SMatrix.sparse_mod.get_function("vector_axpby_kernel")
681
+ minus_axpy_kernel = SMatrix.sparse_mod.get_function("vector_minus_axpy_kernel")
682
+ gradient_kernel = SMatrix.sparse_mod.get_function("gradient_kernel")
683
+ divergence_kernel = SMatrix.sparse_mod.get_function("divergence_kernel")
684
+ proj_tv_kernel = SMatrix.sparse_mod.get_function("proj_tv_kernel")
685
+
686
+ # Nouveaux kernels pour le préconditionnement
687
+ try:
688
+ update_dual_data_precond = SMatrix.sparse_mod.get_function("update_dual_data_precond_kernel")
689
+ update_primal_precond = SMatrix.sparse_mod.get_function("update_primal_precond_kernel")
690
+ invert_vector_kernel = SMatrix.sparse_mod.get_function("invert_vector_kernel")
691
+ clamp_positive_kernel = SMatrix.sparse_mod.get_function("clamp_positive_kernel")
692
+ except Exception as e:
693
+ print("Erreur: Il manque les kernels C++ de préconditionnement (update_dual_data_precond_kernel, etc).")
694
+ raise e
695
+
696
+ stream = drv.Stream()
697
+
698
+ # --- 1. SETUP PRECONDITIONERS (tau_vec, sigma_vec) ---
699
+ # Au lieu de calculer L, on calcule les sommes lignes/colonnes
700
+
701
+ # Allocations vecteurs de pas
702
+ sigma_vec_gpu = drv.mem_alloc(TN * np.dtype(dtype).itemsize)
703
+ tau_vec_gpu = drv.mem_alloc(ZX * np.dtype(dtype).itemsize)
704
+
705
+ # Buffer temporaire de 1 pour les sommes
706
+ ones_TN_gpu = drv.mem_alloc(TN * np.dtype(dtype).itemsize)
707
+ ones_ZX_gpu = drv.mem_alloc(ZX * np.dtype(dtype).itemsize)
708
+
709
+ # Remplir de 1.0
710
+ # On utilise une astuce : axpby(out, out, out, 0, 0) pour clear puis ajout de 1 ? Non, memset n'écrit pas des float 1.0.
711
+ # On va transférer un array de 1 depuis le host (rapide au setup)
712
+ drv.memcpy_htod_async(ones_TN_gpu, np.ones(TN, dtype=dtype), stream)
713
+ drv.memcpy_htod_async(ones_ZX_gpu, np.ones(ZX, dtype=dtype), stream)
714
+
715
+ # A) Calcul de Sigma (Inverse des Row Sums) : A * 1_ZX
716
+ # On utilise ton kernel de projection existant : q = A * theta (avec theta=1)
717
+ projection_kernel(sigma_vec_gpu, SMatrix.sell_values_gpu, SMatrix.sell_colinds_gpu, SMatrix.slice_ptr_gpu, SMatrix.slice_len_gpu,
718
+ ones_ZX_gpu, np.int32(TN), np.int32(SMatrix.slice_height),
719
+ block=(block_size, 1, 1), grid=((TN + block_size - 1) // block_size, 1, 1), stream=stream)
720
+
721
+ # Inversion : sigma_vec = 1 / (sum + eps)
722
+ # Note : sigma_vec doit être divisé par k_security ? Dans Pock precond, tau_i = 1/sum. On garde k_security global si besoin.
723
+ invert_vector_kernel(sigma_vec_gpu, sigma_vec_gpu, np.float32(1e-6), np.int32(TN),
724
+ block=(block_size, 1, 1), grid=((TN + block_size - 1) // block_size, 1, 1), stream=stream)
725
+
726
+ # B) Calcul de Tau (Inverse des Col Sums - Carte Sensibilité) : A^T * 1_TN
727
+ # On utilise ton kernel de backprojection : c += A^T * e (avec e=1)
728
+ # Important : backproj fait un atomicAdd, il faut mettre à 0 avant
729
+ drv.memset_d32_async(tau_vec_gpu, 0, ZX, stream)
730
+ backprojection_kernel(SMatrix.sell_values_gpu, SMatrix.sell_colinds_gpu, SMatrix.slice_ptr_gpu, SMatrix.slice_len_gpu,
731
+ ones_TN_gpu, tau_vec_gpu, np.int32(TN), np.int32(SMatrix.slice_height),
732
+ block=(block_size, 1, 1), grid=((TN + block_size - 1) // block_size, 1, 1), stream=stream)
733
+
734
+ invert_vector_kernel(tau_vec_gpu, tau_vec_gpu, np.float32(1e-6), np.int32(ZX),
735
+ block=(block_size, 1, 1), grid=((ZX + block_size - 1) // block_size, 1, 1), stream=stream)
736
+
737
+ # Nettoyage temp
738
+ ones_TN_gpu.free()
739
+ ones_ZX_gpu.free()
740
+
741
+ # --- 2. PREPARE DATA ---
742
+ y = y.T.astype(dtype).reshape(-1)
743
+ maxy = float(np.max(np.abs(y))) if y.size > 0 else 0.0
744
+ y_normed = (y / maxy).copy() if maxy > 0 else y.copy()
745
+
746
+ # Allocations Variables Principales
747
+ bufs = []
748
+ y_gpu = drv.mem_alloc(y_normed.nbytes); bufs.append(y_gpu)
749
+ drv.memcpy_htod_async(y_gpu, y_normed, stream)
750
+
751
+ x_gpu = drv.mem_alloc(ZX * np.dtype(dtype).itemsize); bufs.append(x_gpu)
752
+ drv.memset_d32_async(x_gpu, 0, ZX, stream)
753
+
754
+ x_old_gpu = drv.mem_alloc(ZX * np.dtype(dtype).itemsize); bufs.append(x_old_gpu)
755
+ x_tilde_gpu = drv.mem_alloc(ZX * np.dtype(dtype).itemsize); bufs.append(x_tilde_gpu)
756
+ drv.memset_d32_async(x_tilde_gpu, 0, ZX, stream) # Important: x_tilde init à 0
757
+
758
+ # Dual Variables
759
+ p_gpu = drv.mem_alloc(2 * ZX * np.dtype(dtype).itemsize); bufs.append(p_gpu) # Gradient
760
+ q_gpu = drv.mem_alloc(TN * np.dtype(dtype).itemsize); bufs.append(q_gpu) # Data term
761
+ drv.memset_d32_async(p_gpu, 0, 2 * ZX, stream)
762
+ drv.memset_d32_async(q_gpu, 0, TN, stream)
763
+
764
+ # Buffers intermédiaires
765
+ grad_gpu = drv.mem_alloc(2 * ZX * np.dtype(dtype).itemsize); bufs.append(grad_gpu)
766
+ div_gpu = drv.mem_alloc(ZX * np.dtype(dtype).itemsize); bufs.append(div_gpu)
767
+ Ax_gpu = drv.mem_alloc(TN * np.dtype(dtype).itemsize); bufs.append(Ax_gpu)
768
+ ATq_gpu = drv.mem_alloc(ZX * np.dtype(dtype).itemsize); bufs.append(ATq_gpu)
769
+
770
+ # --- PARAMETRES & LOGS ---
771
+ # Pour le TV, on a besoin d'un sigma scalaire pour le dual update du gradient.
772
+ # Dans le preconditionning diagonal complet, c'est complexe.
773
+ # Approximation robuste : on utilise sigma_tv fixe.
774
+ # Cependant, alpha (le poids TV) joue le rôle de seuil.
775
+ sigma_tv = np.float32(1.0) # Le scaling est absorbé par alpha et tau_vec
776
+
777
+ if alpha is None:
778
+ # Auto-alpha simplifié (ou tu gardes ta logique précédente)
779
+ alpha = 0.01 # Valeur par défaut si non spécifié
780
+ print(f"Warning: Alpha not set, using default {alpha}")
781
+
782
+ # Description
783
+ desc = f"Pock-Precond | {tumor_str} | Alpha={alpha} | Beta={beta}"
784
+
785
+ # Saving setup
786
+ x_host = np.empty(ZX, dtype=dtype)
787
+ save_indices_all = list(range(0, numIterations + 1, max(1, numIterations // max_saves)))
788
+ I_reconMatrix = []
789
+ saved_indices = []
790
+
791
+ try:
792
+ iterator = trange(numIterations, desc=desc) if show_logs else range(numIterations)
793
+
794
+ for it in iterator:
795
+
796
+ # =======================
797
+ # 1. UPDATE DUAL (P - TV)
798
+ # =======================
799
+ # Gradient de x_bar (x_tilde)
800
+ gradient_kernel(grad_gpu, x_tilde_gpu, np.int32(Z), np.int32(X), np.int32(ZX),
801
+ block=(block_size, 1, 1), grid=((X + block_size - 1) // block_size, (Z + block_size - 1) // block_size, 1), stream=stream)
802
+
803
+ # p = p + sigma_tv * grad
804
+ axpby_kernel(p_gpu, p_gpu, grad_gpu, np.float32(1.0), sigma_tv, np.int32(2 * ZX),
805
+ block=(block_size, 1, 1), grid=((2*ZX + block_size - 1) // block_size, 1, 1), stream=stream)
806
+
807
+ # Prox TV (Projection boule unité)
808
+ # Attention : ici le pas "alpha" doit être adapté car on utilise un tau vectoriel ailleurs.
809
+ # On passe alpha brut.
810
+ proj_tv_kernel(p_gpu, np.float32(alpha), np.int32(ZX),
811
+ block=(block_size, 1, 1), grid=((ZX + block_size - 1) // block_size, 1, 1), stream=stream)
812
+
813
+ # ==========================
814
+ # 2. UPDATE DUAL (Q - DATA)
815
+ # ==========================
816
+ # Calcul Ax_bar
817
+ projection_kernel(Ax_gpu, SMatrix.sell_values_gpu, SMatrix.sell_colinds_gpu, SMatrix.slice_ptr_gpu, SMatrix.slice_len_gpu,
818
+ x_tilde_gpu, np.int32(TN), np.int32(SMatrix.slice_height),
819
+ block=(block_size, 1, 1), grid=((TN + block_size - 1) // block_size, 1, 1), stream=stream)
820
+
821
+ # Update q avec sigma vectoriel
822
+ # q = (q + sigma_vec * (Ax - y)) / (1 + sigma_vec)
823
+ update_dual_data_precond(q_gpu, Ax_gpu, y_gpu, sigma_vec_gpu, np.int32(TN),
824
+ block=(block_size, 1, 1), grid=((TN + block_size - 1) // block_size, 1, 1), stream=stream)
825
+
826
+ # ==========================
827
+ # 3. UPDATE PRIMAL (X)
828
+ # ==========================
829
+ # Sauvegarde x_old
830
+ drv.memcpy_dtod_async(x_old_gpu, x_gpu, ZX * np.dtype(dtype).itemsize, stream)
831
+
832
+ # Calcul ATq (Backprojection)
833
+ drv.memset_d32_async(ATq_gpu, 0, ZX, stream)
834
+ backprojection_kernel(SMatrix.sell_values_gpu, SMatrix.sell_colinds_gpu, SMatrix.slice_ptr_gpu, SMatrix.slice_len_gpu,
835
+ q_gpu, ATq_gpu, np.int32(TN), np.int32(SMatrix.slice_height),
836
+ block=(block_size, 1, 1), grid=((TN + block_size - 1) // block_size, 1, 1), stream=stream)
837
+
838
+ # Calcul Div p
839
+ divergence_kernel(div_gpu, p_gpu, np.int32(Z), np.int32(X), np.int32(ZX),
840
+ block=(block_size, 1, 1), grid=((X + block_size - 1) // block_size, (Z + block_size - 1) // block_size, 1), stream=stream)
841
+
842
+ # Combiner les gradients : ATq - Div p
843
+ minus_axpy_kernel(ATq_gpu, div_gpu, np.float32(1.0), np.int32(ZX),
844
+ block=(block_size, 1, 1), grid=((ZX + block_size - 1) // block_size, 1, 1), stream=stream)
845
+
846
+ # Update X avec tau vectoriel
847
+ # x = x - tau_vec * (ATq - Div p)
848
+ # Note: ATq_gpu contient maintenant le gradient total
849
+ update_primal_precond(x_gpu, ATq_gpu, tau_vec_gpu, np.int32(ZX),
850
+ block=(block_size, 1, 1), grid=((ZX + block_size - 1) // block_size, 1, 1), stream=stream)
851
+
852
+ # Positivity
853
+ if apply_positivity_clamp:
854
+ clamp_positive_kernel(x_gpu, np.int32(ZX),
855
+ block=(block_size, 1, 1), grid=((ZX + block_size - 1) // block_size, 1, 1), stream=stream)
856
+
857
+ # Tikhonov (simplifié : decay)
858
+ if beta > 0:
859
+ # x = x / (1 + beta * tau_vec) ?
860
+ # Approx rapide : x *= (1 - beta * mean_tau) ou juste x *= (1-beta)
861
+ # Utilisons axpby simple pour un petit decay
862
+ axpby_kernel(x_gpu, x_gpu, x_gpu, np.float32(1.0 - beta), np.float32(0.0), np.int32(ZX),
863
+ block=(block_size, 1, 1), grid=((ZX + block_size - 1) // block_size, 1, 1), stream=stream)
864
+
865
+ # ==========================
866
+ # 4. EXTRAPOLATION
867
+ # ==========================
868
+ # x_tilde = x + theta * (x - x_old)
869
+ axpby_kernel(x_tilde_gpu, x_gpu, x_old_gpu, np.float32(2.0), np.float32(-1.0), np.int32(ZX),
870
+ block=(block_size, 1, 1), grid=((ZX + block_size - 1) // block_size, 1, 1), stream=stream)
871
+
872
+ # Save
873
+ if isSavingEachIteration and (it + 1) in save_indices_all:
874
+ stream.synchronize()
875
+ drv.memcpy_dtoh(x_host, x_gpu)
876
+ x_saved = x_host.reshape((Z, X)).copy()
877
+ if maxy > 0: x_saved *= maxy
878
+ I_reconMatrix.append(x_saved)
879
+ saved_indices.append(it + 1)
880
+
881
+ # Fin boucle
882
+ stream.synchronize()
883
+ # Cleanup (buffers)
884
+ for b in bufs: b.free()
885
+ sigma_vec_gpu.free()
886
+ tau_vec_gpu.free()
887
+ if SMatrix.ctx: SMatrix.ctx.pop()
888
+
889
+ return I_reconMatrix, saved_indices
890
+
891
+ except Exception as e:
892
+ print(f"Error: {e}")
893
+ if SMatrix.ctx: SMatrix.ctx.pop()
894
+ return None, None
895
+
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.384'
88
+ __version__ = '2.9.386'
89
89
  __process__ = config.get_process()
90
90
 
91
91
  def initialize(process=None):
@@ -245,6 +245,8 @@ def initialize(process=None):
245
245
 
246
246
 
247
247
 
248
+
249
+
248
250
 
249
251
 
250
252
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: AOT_biomaps
3
- Version: 2.9.384
3
+ Version: 2.9.386
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=v5zaM6In37AdyS1xtkJdFUucdfR1ho7Wa6cOfoqtQxI,4430
3
+ AOT_biomaps/__init__.py,sha256=khayoJ2i2AgFcpmXaDxizLDrK8JfWe_LyyfKwJIQ9zU,4434
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=GPh_mD6TUVolKa32tu6juPxvmzgLB7eXBfuXO-8ZhEg,21243
10
10
  AOT_biomaps/AOT_Acoustic/__init__.py,sha256=t9M2rRqa_L9pk7W2FeELTkHEMuP4DBr4gBRldMqsQbg,491
11
- AOT_biomaps/AOT_Acoustic/_mainAcoustic.py,sha256=ql-6W9mwIpxC4PGxF2XFa8iWF5SN69VFeYZh3312Fzw,47588
11
+ AOT_biomaps/AOT_Acoustic/_mainAcoustic.py,sha256=fnVWzu0cnbQc6mqnCDemiwdaGR1RGIIpqszvnYM-Dis,47514
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
@@ -33,7 +33,7 @@ AOT_biomaps/AOT_Recon/AOT_Optimizers/DEPIERRO.py,sha256=qA1n722GLQJH3V8HcLr5q_Gx
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
35
35
  AOT_biomaps/AOT_Recon/AOT_Optimizers/MLEM.py,sha256=4omsqzHEZJfv0mEfmxfK71IovDbRstVE4x3Flf4cR3o,22441
36
- AOT_biomaps/AOT_Recon/AOT_Optimizers/PDHG.py,sha256=oSojwug5mcZedKOWAV7YPMlCp0Qy_Aed0fjHRuyZWpo,28622
36
+ AOT_biomaps/AOT_Recon/AOT_Optimizers/PDHG.py,sha256=K-SnzLIMNJdnSu1GT5a-N_qv_Ve06xILaJM3G69AAV0,41129
37
37
  AOT_biomaps/AOT_Recon/AOT_Optimizers/__init__.py,sha256=tNGVulINaqQZzcs5cvCMAT5ypGdoFWRnxtl9y7ePECk,106
38
38
  AOT_biomaps/AOT_Recon/AOT_PotentialFunctions/Huber.py,sha256=dRd1t5OBag_gVmfji3L0QrA1GJ_702LcCkLH32Bot0M,3285
39
39
  AOT_biomaps/AOT_Recon/AOT_PotentialFunctions/Quadratic.py,sha256=wTbzcXxMdEl9ReEXrL43DOJQecokBwJYU_s2kQUASZY,2545
@@ -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.384.dist-info/METADATA,sha256=WlQIgGgKBoWMec_aU1J81_EFhOqHA63nndEPdnYnMh4,700
46
- aot_biomaps-2.9.384.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
47
- aot_biomaps-2.9.384.dist-info/top_level.txt,sha256=6STF-lT4kaAnBHJYCripmN5mZABoHjMuY689JdiDphk,12
48
- aot_biomaps-2.9.384.dist-info/RECORD,,
45
+ aot_biomaps-2.9.386.dist-info/METADATA,sha256=9vAXgvhWtKvXT09vFheT2t_6-g2qCQF-ViXfz17KJ5k,700
46
+ aot_biomaps-2.9.386.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
47
+ aot_biomaps-2.9.386.dist-info/top_level.txt,sha256=6STF-lT4kaAnBHJYCripmN5mZABoHjMuY689JdiDphk,12
48
+ aot_biomaps-2.9.386.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5