antspymm 1.5.0__py3-none-any.whl → 1.5.2__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.
- antspymm/__init__.py +2 -0
- antspymm/mm.py +249 -39
- {antspymm-1.5.0.dist-info → antspymm-1.5.2.dist-info}/METADATA +1 -1
- antspymm-1.5.2.dist-info/RECORD +7 -0
- antspymm-1.5.0.dist-info/RECORD +0 -7
- {antspymm-1.5.0.dist-info → antspymm-1.5.2.dist-info}/WHEEL +0 -0
- {antspymm-1.5.0.dist-info → antspymm-1.5.2.dist-info}/licenses/LICENSE +0 -0
- {antspymm-1.5.0.dist-info → antspymm-1.5.2.dist-info}/top_level.txt +0 -0
antspymm/__init__.py
CHANGED
@@ -7,6 +7,8 @@ except:
|
|
7
7
|
from .mm import get_data
|
8
8
|
from .mm import ants_to_nibabel_affine
|
9
9
|
from .mm import get_dti
|
10
|
+
from .mm import efficient_tensor_fit
|
11
|
+
from .mm import efficient_dwi_fit
|
10
12
|
from .mm import triangular_to_tensor
|
11
13
|
from .mm import dti_numpy_to_image
|
12
14
|
from .mm import transform_and_reorient_dti
|
antspymm/mm.py
CHANGED
@@ -3555,6 +3555,239 @@ def trim_dti_mask( fa, mask, param=4.0 ):
|
|
3555
3555
|
trim_mask = ants.iMath(trim_mask,"MD",paramVox-1)
|
3556
3556
|
return trim_mask
|
3557
3557
|
|
3558
|
+
|
3559
|
+
|
3560
|
+
def efficient_tensor_fit( gtab, fit_method, imagein, maskin, diffusion_model='DTI',
|
3561
|
+
chunk_size=10, num_threads=1, verbose=True):
|
3562
|
+
"""
|
3563
|
+
Efficient and optionally parallelized tensor reconstruction using DiPy.
|
3564
|
+
|
3565
|
+
Parameters
|
3566
|
+
----------
|
3567
|
+
gtab : GradientTable
|
3568
|
+
Dipy gradient table.
|
3569
|
+
fit_method : str
|
3570
|
+
Tensor fitting method (e.g. 'WLS', 'OLS', 'RESTORE').
|
3571
|
+
imagein : ants.ANTsImage
|
3572
|
+
4D diffusion-weighted image.
|
3573
|
+
maskin : ants.ANTsImage
|
3574
|
+
Binary brain mask image.
|
3575
|
+
diffusion_model : string, optional
|
3576
|
+
DTI, FreeWater, DKI.
|
3577
|
+
chunk_size : int, optional
|
3578
|
+
Number of slices (along z-axis) to process at once.
|
3579
|
+
num_threads : int, optional
|
3580
|
+
Number of threads to use (1 = single-threaded).
|
3581
|
+
verbose : bool, optional
|
3582
|
+
Print status updates.
|
3583
|
+
|
3584
|
+
Returns
|
3585
|
+
-------
|
3586
|
+
tenfit : TensorFit or FreeWaterTensorFit
|
3587
|
+
Fitted tensor model.
|
3588
|
+
FA : ants.ANTsImage
|
3589
|
+
Fractional anisotropy image.
|
3590
|
+
MD : ants.ANTsImage
|
3591
|
+
Mean diffusivity image.
|
3592
|
+
RGB : ants.ANTsImage
|
3593
|
+
RGB FA map.
|
3594
|
+
"""
|
3595
|
+
assert imagein.dimension == 4, "Input image must be 4D"
|
3596
|
+
|
3597
|
+
import ants
|
3598
|
+
import numpy as np
|
3599
|
+
import dipy.reconst.dti as dti
|
3600
|
+
import dipy.reconst.fwdti as fwdti
|
3601
|
+
from dipy.reconst.dti import fractional_anisotropy
|
3602
|
+
from dipy.reconst.dti import color_fa
|
3603
|
+
from concurrent.futures import ThreadPoolExecutor, as_completed
|
3604
|
+
|
3605
|
+
img_data = imagein.numpy()
|
3606
|
+
mask = maskin.numpy().astype(bool)
|
3607
|
+
X, Y, Z, N = img_data.shape
|
3608
|
+
if verbose:
|
3609
|
+
print(f"Input shape: {img_data.shape}, Processing in chunks of {chunk_size} slices.")
|
3610
|
+
|
3611
|
+
model = fwdti.FreeWaterTensorModel(gtab) if diffusion_model == 'FreeWater' else dti.TensorModel(gtab, fit_method=fit_method)
|
3612
|
+
|
3613
|
+
def process_chunk(z_start):
|
3614
|
+
z_end = min(Z, z_start + chunk_size)
|
3615
|
+
local_data = img_data[:, :, z_start:z_end, :]
|
3616
|
+
local_mask = mask[:, :, z_start:z_end]
|
3617
|
+
masked_data = local_data * local_mask[..., None]
|
3618
|
+
masked_data = np.nan_to_num(masked_data, nan=0)
|
3619
|
+
fit = model.fit(masked_data)
|
3620
|
+
FA_chunk = fractional_anisotropy(fit.evals)
|
3621
|
+
FA_chunk[np.isnan(FA_chunk)] = 1
|
3622
|
+
FA_chunk = np.clip(FA_chunk, 0, 1)
|
3623
|
+
MD_chunk = dti.mean_diffusivity(fit.evals)
|
3624
|
+
RGB_chunk = color_fa(FA_chunk, fit.evecs)
|
3625
|
+
return z_start, z_end, FA_chunk, MD_chunk, RGB_chunk
|
3626
|
+
|
3627
|
+
FA_vol = np.zeros((X, Y, Z), dtype=np.float32)
|
3628
|
+
MD_vol = np.zeros((X, Y, Z), dtype=np.float32)
|
3629
|
+
RGB_vol = np.zeros((X, Y, Z, 3), dtype=np.float32)
|
3630
|
+
|
3631
|
+
chunks = range(0, Z, chunk_size)
|
3632
|
+
if num_threads > 1:
|
3633
|
+
with ThreadPoolExecutor(max_workers=num_threads) as executor:
|
3634
|
+
futures = {executor.submit(process_chunk, z): z for z in chunks}
|
3635
|
+
for f in as_completed(futures):
|
3636
|
+
z_start, z_end, FA_chunk, MD_chunk, RGB_chunk = f.result()
|
3637
|
+
FA_vol[:, :, z_start:z_end] = FA_chunk
|
3638
|
+
MD_vol[:, :, z_start:z_end] = MD_chunk
|
3639
|
+
RGB_vol[:, :, z_start:z_end, :] = RGB_chunk
|
3640
|
+
else:
|
3641
|
+
for z in chunks:
|
3642
|
+
z_start, z_end, FA_chunk, MD_chunk, RGB_chunk = process_chunk(z)
|
3643
|
+
FA_vol[:, :, z_start:z_end] = FA_chunk
|
3644
|
+
MD_vol[:, :, z_start:z_end] = MD_chunk
|
3645
|
+
RGB_vol[:, :, z_start:z_end, :] = RGB_chunk
|
3646
|
+
|
3647
|
+
b0 = ants.slice_image(imagein, axis=3, idx=0)
|
3648
|
+
FA = ants.copy_image_info(b0, ants.from_numpy(FA_vol))
|
3649
|
+
MD = ants.copy_image_info(b0, ants.from_numpy(MD_vol))
|
3650
|
+
RGB_channels = [ants.copy_image_info(b0, ants.from_numpy(RGB_vol[..., i])) for i in range(3)]
|
3651
|
+
RGB = ants.merge_channels(RGB_channels)
|
3652
|
+
|
3653
|
+
return model.fit(img_data * mask[..., None]), FA, MD, RGB
|
3654
|
+
|
3655
|
+
|
3656
|
+
|
3657
|
+
def efficient_dwi_fit(gtab, diffusion_model, imagein, maskin,
|
3658
|
+
model_params=None, bvals_to_use=None,
|
3659
|
+
chunk_size=1024, num_threads=1, verbose=True):
|
3660
|
+
"""
|
3661
|
+
Efficient and optionally parallelized diffusion model reconstruction using DiPy.
|
3662
|
+
|
3663
|
+
Parameters
|
3664
|
+
----------
|
3665
|
+
gtab : GradientTable
|
3666
|
+
DiPy gradient table.
|
3667
|
+
diffusion_model : str
|
3668
|
+
One of ['DTI', 'FreeWater', 'DKI'].
|
3669
|
+
imagein : ants.ANTsImage
|
3670
|
+
4D diffusion-weighted image.
|
3671
|
+
maskin : ants.ANTsImage
|
3672
|
+
Binary brain mask image.
|
3673
|
+
model_params : dict, optional
|
3674
|
+
Additional parameters passed to model constructors.
|
3675
|
+
bvals_to_use : list of int, optional
|
3676
|
+
Subset of b-values to use for the fit (e.g., [0, 1000, 2000]).
|
3677
|
+
chunk_size : int, optional
|
3678
|
+
Maximum number of voxels per chunk (default 1024).
|
3679
|
+
num_threads : int, optional
|
3680
|
+
Number of parallel threads.
|
3681
|
+
verbose : bool, optional
|
3682
|
+
Whether to print status messages.
|
3683
|
+
|
3684
|
+
Returns
|
3685
|
+
-------
|
3686
|
+
fit : dipy ModelFit
|
3687
|
+
The fitted model object.
|
3688
|
+
FA : ants.ANTsImage or None
|
3689
|
+
Fractional anisotropy image (if applicable).
|
3690
|
+
MD : ants.ANTsImage or None
|
3691
|
+
Mean diffusivity image (if applicable).
|
3692
|
+
RGB : ants.ANTsImage or None
|
3693
|
+
Color FA image (if applicable).
|
3694
|
+
"""
|
3695
|
+
import ants
|
3696
|
+
import numpy as np
|
3697
|
+
import dipy.reconst.dti as dti
|
3698
|
+
import dipy.reconst.fwdti as fwdti
|
3699
|
+
import dipy.reconst.dki as dki
|
3700
|
+
from dipy.core.gradients import gradient_table
|
3701
|
+
from dipy.reconst.dti import fractional_anisotropy, color_fa, mean_diffusivity
|
3702
|
+
from concurrent.futures import ThreadPoolExecutor, as_completed
|
3703
|
+
|
3704
|
+
assert imagein.dimension == 4, "Input image must be 4D"
|
3705
|
+
model_params = model_params or {}
|
3706
|
+
|
3707
|
+
img_data = imagein.numpy()
|
3708
|
+
mask = maskin.numpy().astype(bool)
|
3709
|
+
X, Y, Z, N = img_data.shape
|
3710
|
+
inplane_size = X * Y
|
3711
|
+
|
3712
|
+
# Convert chunk_size from voxel count to number of slices
|
3713
|
+
slices_per_chunk = max(1, chunk_size // inplane_size)
|
3714
|
+
|
3715
|
+
if verbose:
|
3716
|
+
print(f"[INFO] Image shape: {img_data.shape}")
|
3717
|
+
print(f"[INFO] Using model: {diffusion_model}")
|
3718
|
+
print(f"[INFO] Max voxels per chunk: {chunk_size} (→ {slices_per_chunk} slices) | Threads: {num_threads}")
|
3719
|
+
|
3720
|
+
if bvals_to_use is not None:
|
3721
|
+
bvals_to_use = set(bvals_to_use)
|
3722
|
+
sel = np.isin(gtab.bvals, list(bvals_to_use))
|
3723
|
+
img_data = img_data[..., sel]
|
3724
|
+
gtab = gradient_table(gtab.bvals[sel], bvecs=gtab.bvecs[sel])
|
3725
|
+
if verbose:
|
3726
|
+
print(f"[INFO] Selected b-values: {sorted(bvals_to_use)}")
|
3727
|
+
print(f"[INFO] Selected volumes: {sel.sum()} / {N}")
|
3728
|
+
|
3729
|
+
def get_model(name, gtab, **params):
|
3730
|
+
if name == 'DTI':
|
3731
|
+
return dti.TensorModel(gtab, **params)
|
3732
|
+
elif name == 'FreeWater':
|
3733
|
+
return fwdti.FreeWaterTensorModel(gtab)
|
3734
|
+
elif name == 'DKI':
|
3735
|
+
return dki.DiffusionKurtosisModel(gtab, **params)
|
3736
|
+
else:
|
3737
|
+
raise ValueError(f"Unsupported model: {name}")
|
3738
|
+
|
3739
|
+
model = get_model(diffusion_model, gtab, **model_params)
|
3740
|
+
|
3741
|
+
FA_vol = np.zeros((X, Y, Z), dtype=np.float32)
|
3742
|
+
MD_vol = np.zeros((X, Y, Z), dtype=np.float32)
|
3743
|
+
RGB_vol = np.zeros((X, Y, Z, 3), dtype=np.float32)
|
3744
|
+
has_tensor_metrics = diffusion_model in ['DTI', 'FreeWater']
|
3745
|
+
|
3746
|
+
def process_chunk(z_start):
|
3747
|
+
z_end = min(Z, z_start + slices_per_chunk)
|
3748
|
+
local_data = img_data[:, :, z_start:z_end, :]
|
3749
|
+
local_mask = mask[:, :, z_start:z_end]
|
3750
|
+
masked_data = local_data * local_mask[..., None]
|
3751
|
+
masked_data = np.nan_to_num(masked_data, nan=0)
|
3752
|
+
fit = model.fit(masked_data)
|
3753
|
+
if has_tensor_metrics and hasattr(fit, 'evals') and hasattr(fit, 'evecs'):
|
3754
|
+
FA = fractional_anisotropy(fit.evals)
|
3755
|
+
FA[np.isnan(FA)] = 1
|
3756
|
+
FA = np.clip(FA, 0, 1)
|
3757
|
+
MD = mean_diffusivity(fit.evals)
|
3758
|
+
RGB = color_fa(FA, fit.evecs)
|
3759
|
+
return z_start, z_end, FA, MD, RGB
|
3760
|
+
return z_start, z_end, None, None, None
|
3761
|
+
|
3762
|
+
chunks = range(0, Z, slices_per_chunk)
|
3763
|
+
if num_threads > 1:
|
3764
|
+
with ThreadPoolExecutor(max_workers=num_threads) as executor:
|
3765
|
+
futures = {executor.submit(process_chunk, z): z for z in chunks}
|
3766
|
+
for f in as_completed(futures):
|
3767
|
+
z_start, z_end, FA, MD, RGB = f.result()
|
3768
|
+
if FA is not None:
|
3769
|
+
FA_vol[:, :, z_start:z_end] = FA
|
3770
|
+
MD_vol[:, :, z_start:z_end] = MD
|
3771
|
+
RGB_vol[:, :, z_start:z_end, :] = RGB
|
3772
|
+
else:
|
3773
|
+
for z in chunks:
|
3774
|
+
z_start, z_end, FA, MD, RGB = process_chunk(z)
|
3775
|
+
if FA is not None:
|
3776
|
+
FA_vol[:, :, z_start:z_end] = FA
|
3777
|
+
MD_vol[:, :, z_start:z_end] = MD
|
3778
|
+
RGB_vol[:, :, z_start:z_end, :] = RGB
|
3779
|
+
|
3780
|
+
b0 = ants.slice_image(imagein, axis=3, idx=0)
|
3781
|
+
FA_img = ants.copy_image_info(b0, ants.from_numpy(FA_vol)) if has_tensor_metrics else None
|
3782
|
+
MD_img = ants.copy_image_info(b0, ants.from_numpy(MD_vol)) if has_tensor_metrics else None
|
3783
|
+
RGB_img = (ants.merge_channels([
|
3784
|
+
ants.copy_image_info(b0, ants.from_numpy(RGB_vol[..., i])) for i in range(3)
|
3785
|
+
]) if has_tensor_metrics else None)
|
3786
|
+
|
3787
|
+
full_fit = model.fit(img_data * mask[..., None])
|
3788
|
+
return full_fit, FA_img, MD_img, RGB_img
|
3789
|
+
|
3790
|
+
|
3558
3791
|
def dipy_dti_recon(
|
3559
3792
|
image,
|
3560
3793
|
bvalsfn,
|
@@ -3565,7 +3798,7 @@ def dipy_dti_recon(
|
|
3565
3798
|
mask_closing = 5,
|
3566
3799
|
fit_method='WLS',
|
3567
3800
|
trim_the_mask=2.0,
|
3568
|
-
|
3801
|
+
diffusion_model='DTI',
|
3569
3802
|
verbose=False ):
|
3570
3803
|
"""
|
3571
3804
|
DiPy DTI reconstruction - building on the DiPy basic DTI example
|
@@ -3592,7 +3825,8 @@ def dipy_dti_recon(
|
|
3592
3825
|
|
3593
3826
|
trim_the_mask : float >=0 post-hoc method for trimming the mask
|
3594
3827
|
|
3595
|
-
|
3828
|
+
diffusion_model : string
|
3829
|
+
DTI, FreeWater, DKI
|
3596
3830
|
|
3597
3831
|
verbose : boolean
|
3598
3832
|
|
@@ -3645,47 +3879,22 @@ def dipy_dti_recon(
|
|
3645
3879
|
if verbose:
|
3646
3880
|
print("recon dti.TensorModel",flush=True)
|
3647
3881
|
|
3648
|
-
def justthefit( gtab, fit_method, imagein, maskin, free_water=False ):
|
3649
|
-
if fit_method is None:
|
3650
|
-
return None, None, None, None
|
3651
|
-
maskedimage=[]
|
3652
|
-
for myidx in range(imagein.shape[3]):
|
3653
|
-
b0 = ants.slice_image( imagein, axis=3, idx=myidx)
|
3654
|
-
maskedimage.append( b0 * maskin )
|
3655
|
-
maskedimage = ants.list_to_ndimage( imagein, maskedimage )
|
3656
|
-
maskdata = maskedimage.numpy()
|
3657
|
-
if free_water:
|
3658
|
-
tenmodel = fwdti.FreeWaterTensorModel(gtab)
|
3659
|
-
else:
|
3660
|
-
tenmodel = dti.TensorModel(gtab,fit_method=fit_method)
|
3661
|
-
tenfit = tenmodel.fit(maskdata)
|
3662
|
-
FA = fractional_anisotropy(tenfit.evals)
|
3663
|
-
FA[np.isnan(FA)] = 1
|
3664
|
-
FA = np.clip(FA, 0, 1)
|
3665
|
-
MD1 = dti.mean_diffusivity(tenfit.evals)
|
3666
|
-
MD1 = ants.copy_image_info( b0, ants.from_numpy( MD1.astype(np.float32) ) )
|
3667
|
-
FA = ants.copy_image_info( b0, ants.from_numpy( FA.astype(np.float32) ) )
|
3668
|
-
FA, MD1 = impute_fa( FA, MD1 )
|
3669
|
-
RGB = color_fa(FA.numpy(), tenfit.evecs)
|
3670
|
-
RGB = ants.from_numpy( RGB.astype(np.float32) )
|
3671
|
-
RGB0 = ants.copy_image_info( b0, ants.slice_image( RGB, axis=3, idx=0 ) )
|
3672
|
-
RGB1 = ants.copy_image_info( b0, ants.slice_image( RGB, axis=3, idx=1 ) )
|
3673
|
-
RGB2 = ants.copy_image_info( b0, ants.slice_image( RGB, axis=3, idx=2 ) )
|
3674
|
-
RGB = ants.merge_channels( [RGB0,RGB1,RGB2] )
|
3675
|
-
return tenfit, FA, MD1, RGB
|
3676
|
-
|
3677
3882
|
bvecs = repair_bvecs( bvecs )
|
3678
3883
|
gtab = gradient_table(bvals, bvecs=bvecs, atol=2.0 )
|
3679
|
-
|
3680
|
-
|
3681
|
-
|
3884
|
+
mynt=1
|
3885
|
+
threads_env = os.environ.get("ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS")
|
3886
|
+
if threads_env is not None:
|
3887
|
+
mynt = int(threads_env)
|
3888
|
+
tenfit, FA, MD1, RGB = efficient_dwi_fit( gtab, diffusion_model, image, maskdil,
|
3889
|
+
num_threads=mynt )
|
3682
3890
|
if verbose:
|
3683
3891
|
print("recon dti.TensorModel done",flush=True)
|
3684
3892
|
|
3685
3893
|
# change the brain mask based on high FA values
|
3686
3894
|
if trim_the_mask > 0 and fit_method is not None:
|
3687
3895
|
mask = trim_dti_mask( FA, mask, trim_the_mask )
|
3688
|
-
tenfit, FA, MD1, RGB =
|
3896
|
+
tenfit, FA, MD1, RGB = efficient_dwi_fit( gtab, diffusion_model, image, maskdil,
|
3897
|
+
num_threads=mynt )
|
3689
3898
|
|
3690
3899
|
return {
|
3691
3900
|
'tensormodel' : tenfit,
|
@@ -3769,7 +3978,7 @@ def joint_dti_recon(
|
|
3769
3978
|
fit_method='WLS',
|
3770
3979
|
impute = False,
|
3771
3980
|
censor = True,
|
3772
|
-
|
3981
|
+
diffusion_model = 'DTI',
|
3773
3982
|
verbose = False ):
|
3774
3983
|
"""
|
3775
3984
|
1. pass in subject data and 1mm JHU atlas/labels
|
@@ -3824,7 +4033,8 @@ def joint_dti_recon(
|
|
3824
4033
|
|
3825
4034
|
censor : boolean
|
3826
4035
|
|
3827
|
-
|
4036
|
+
diffusion_model : string
|
4037
|
+
DTI, FreeWater, DKI
|
3828
4038
|
|
3829
4039
|
verbose : boolean
|
3830
4040
|
|
@@ -3944,7 +4154,7 @@ def joint_dti_recon(
|
|
3944
4154
|
img_LRdwp, bval_LR, bvec_LR,
|
3945
4155
|
mask = brain_mask,
|
3946
4156
|
fit_method=fit_method,
|
3947
|
-
mask_dilation=0,
|
4157
|
+
mask_dilation=0, diffusion_model=diffusion_model, verbose=True )
|
3948
4158
|
if verbose:
|
3949
4159
|
print("recon done", flush=True)
|
3950
4160
|
|
@@ -4245,7 +4455,7 @@ def dwi_deterministic_tracking(
|
|
4245
4455
|
gtab = gradient_table(bvals, bvecs=bvecs, atol=2.0 )
|
4246
4456
|
if mask is None:
|
4247
4457
|
mask = ants.threshold_image( fa, fa_thresh, 2.0 ).iMath("GetLargestComponent")
|
4248
|
-
dwi_data = dwi.numpy()
|
4458
|
+
dwi_data = dwi.numpy()
|
4249
4459
|
dwi_mask = mask.numpy() == 1
|
4250
4460
|
dti_model = dti.TensorModel(gtab,fit_method=fit_method)
|
4251
4461
|
if verbose:
|
@@ -0,0 +1,7 @@
|
|
1
|
+
antspymm/__init__.py,sha256=DnkidUfEu3Dl0tuWNTA-9VOUkBtH_cROKiPGNNXNagU,4637
|
2
|
+
antspymm/mm.py,sha256=NbT1IBiuEMtMoanr_8yO3kLNpSSfV0j1_155gykGOM0,526972
|
3
|
+
antspymm-1.5.2.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
4
|
+
antspymm-1.5.2.dist-info/METADATA,sha256=3Ttc-cPytZsiNct2MRz4PZwe5JmdZzaEsEgu7hxKxvA,25939
|
5
|
+
antspymm-1.5.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
6
|
+
antspymm-1.5.2.dist-info/top_level.txt,sha256=iyD1sRhCKzfwKRJLq5ZUeV9xsv1cGQl8Ejp6QwXM1Zg,9
|
7
|
+
antspymm-1.5.2.dist-info/RECORD,,
|
antspymm-1.5.0.dist-info/RECORD
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
antspymm/__init__.py,sha256=3t4jqSbQVRfecm1ekc02ytWlZ3yAGcPyB_kzQAcg4Bc,4566
|
2
|
-
antspymm/mm.py,sha256=UdmKcS4wYazBdC8DUchdnzXZzM4tetFx3RfDS9zH4ys,519104
|
3
|
-
antspymm-1.5.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
4
|
-
antspymm-1.5.0.dist-info/METADATA,sha256=fXgNR7g8l0I1AFjAPIZwTRpN_RBrW5FiaBtdjg5z0Mc,25939
|
5
|
-
antspymm-1.5.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
6
|
-
antspymm-1.5.0.dist-info/top_level.txt,sha256=iyD1sRhCKzfwKRJLq5ZUeV9xsv1cGQl8Ejp6QwXM1Zg,9
|
7
|
-
antspymm-1.5.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|