antspymm 1.5.3__py3-none-any.whl → 1.5.5__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 CHANGED
@@ -135,5 +135,6 @@ from .mm import fix_LR_RL_stuff
135
135
  from .mm import segment_timeseries_by_bvalue
136
136
  from .mm import shorten_pymm_names
137
137
  from .mm import pet3d_summary
138
+ from .mm import deformation_gradient_optimized
138
139
 
139
140
 
antspymm/mm.py CHANGED
@@ -2195,65 +2195,206 @@ def dti_numpy_to_image( reference_image, tensorarray, upper_triangular=True):
2195
2195
  ants.copy_image_info( reference_image, dtiAnts )
2196
2196
  return dtiAnts
2197
2197
 
2198
- def transform_and_reorient_dti( fixed, moving_dti, composite_transform, py_based=True, verbose=False, **kwargs):
2198
+
2199
+ def deformation_gradient_optimized(warp_image, to_rotation=False, to_inverse_rotation=False):
2199
2200
  """
2200
- apply a transform to DTI in the style of ants.apply_transforms. this function
2201
- expects a pre-computed composite transform which it will use to reorient
2202
- the DTI using preservation of principle directions. BUG fix by cookpa 2025
2203
- 06 18.
2201
+ Compute the deformation gradient tensor from a displacement (warp) field image.
2204
2202
 
2205
- fixed : antsImage reference space
2203
+ This function computes the **deformation gradient** `F = ∂φ/∂x` where `φ(x) = x + u(x)` is the mapping
2204
+ induced by the displacement field `u(x)` stored in `warp_image`.
2206
2205
 
2207
- moving_dti : antsImage DTI in upper triangular format
2206
+ The returned tensor field has shape `(x, y, z, dim, dim)` (for 3D), where each matrix represents
2207
+ the **Jacobian** of the transformation at that voxel. The gradient is computed in the physical space
2208
+ of the image using spacing and direction metadata.
2208
2209
 
2209
- composite_transform : should be a composition of all transforms to be applied stored on disk ( a filename ) ... might change this in the future.
2210
+ Optionally, the deformation gradient can be projected onto the space of pure rotations using the polar
2211
+ decomposition (via SVD). This is useful for applications like reorientation of tensors (e.g., DTI).
2210
2212
 
2211
- py_based : boolean
2213
+ Parameters
2214
+ ----------
2215
+ warp_image : ants.ANTsImage
2216
+ A vector-valued ANTsImage encoding the warp/displacement field. It must have `dim` components
2217
+ (e.g., shape `(x, y, z, 3)` for 3D) representing the displacements in each spatial direction.
2218
+
2219
+ to_rotation : bool, optional
2220
+ If True, the deformation gradient will be replaced with its **nearest rotation matrix**
2221
+ using the polar decomposition (`F → R`, where `F = R U`).
2222
+
2223
+ to_inverse_rotation : bool, optional
2224
+ If True, the deformation gradient will be replaced with the **inverse of the rotation**
2225
+ (`F → R.T`), which is often needed for transforming tensors **back** to their original frame.
2212
2226
 
2213
- verbose : boolean
2227
+ Returns
2228
+ -------
2229
+ F : np.ndarray
2230
+ A NumPy array of shape `(x, y, z, dim, dim)` (or `(dim1, dim2, ..., dim, dim)` in general),
2231
+ representing the deformation gradient tensor field at each voxel.
2214
2232
 
2215
- **kwargs : passed to ants.apply_transforms
2233
+ Raises
2234
+ ------
2235
+ RuntimeError
2236
+ If `warp_image` is not an `ants.ANTsImage`.
2216
2237
 
2238
+ Notes
2239
+ -----
2240
+ - The function computes gradients in physical space using the spacing of the image and applies
2241
+ the image direction matrix (`tdir`) to properly orient gradients.
2242
+ - The gradient is added to the identity matrix to yield the deformation gradient `F = I + ∂u/∂x`.
2243
+ - The polar decomposition ensures `F` is replaced with the closest rotation matrix (orthogonal, det=1).
2244
+ - This is a **vectorized pure NumPy implementation**, intended for performance and simplicity.
2245
+
2246
+ Examples
2247
+ --------
2248
+ >>> warp = ants.create_warp_image(reference_image, displacement_field)
2249
+ >>> F = deformation_gradient_optimized(warp)
2250
+ >>> R = deformation_gradient_optimized(warp, to_rotation=True)
2251
+ >>> Rinv = deformation_gradient_optimized(warp, to_inverse_rotation=True)
2252
+ """
2253
+ if not ants.is_image(warp_image):
2254
+ raise RuntimeError("antsimage is required")
2255
+ dim = warp_image.dimension
2256
+ tshp = warp_image.shape
2257
+ tdir = warp_image.direction
2258
+ spc = warp_image.spacing
2259
+ warpnp = warp_image.numpy()
2260
+ gradient_list = [np.gradient(warpnp[..., k], *spc, axis=range(dim)) for k in range(dim)]
2261
+ # This correctly calculates J.T, where dg[..., i, j] = d(u_j)/d(x_i)
2262
+ dg = np.stack([np.stack(grad_k, axis=-1) for grad_k in gradient_list], axis=-1)
2263
+ dg = (tdir @ dg).swapaxes(-1, -2)
2264
+ dg += np.eye(dim)
2265
+ if to_rotation or to_inverse_rotation:
2266
+ U, s, Vh = np.linalg.svd(dg)
2267
+ Z = U @ Vh
2268
+ dets = np.linalg.det(Z)
2269
+ reflection_mask = dets < 0
2270
+ Vh[reflection_mask, -1, :] *= -1
2271
+ Z[reflection_mask] = U[reflection_mask] @ Vh[reflection_mask]
2272
+ dg = Z
2273
+ if to_inverse_rotation:
2274
+ dg = np.transpose(dg, axes=(*range(dg.ndim - 2), dg.ndim - 1, dg.ndim - 2))
2275
+ new_shape = tshp + (dim,dim)
2276
+ return np.reshape(dg, new_shape)
2277
+
2278
+
2279
+ def transform_and_reorient_dti( fixed, moving_dti, composite_transform, verbose=False, **kwargs):
2280
+ """
2281
+ Applies a transformation to a DTI image using an ANTs composite transform,
2282
+ including local tensor reorientation via the Finite Strain method.
2283
+
2284
+ This function expects:
2285
+ - Input `moving_dti` to be a 6-component ANTsImage (upper triangular format).
2286
+ - `composite_transform` to point to an ANTs-readable transform file,
2287
+ which maps points from `fixed` space to `moving` space.
2288
+
2289
+ Args:
2290
+ fixed (ants.ANTsImage): The reference space image (defines the output grid).
2291
+ moving_dti (ants.ANTsImage): The input DTI (6-component), to be transformed.
2292
+ composite_transform (str): File path to an ANTs transform
2293
+ (e.g., from `ants.read_transform` or a written composite transform).
2294
+ verbose (bool): Whether to print verbose output during execution.
2295
+ **kwargs: Additional keyword arguments passed to `ants.apply_transforms`.
2296
+
2297
+ Returns:
2298
+ ants.ANTsImage: The transformed and reoriented DTI image in the `fixed` space,
2299
+ in 6-component upper triangular format.
2217
2300
  """
2218
2301
  if moving_dti.dimension != 3:
2219
- raise ValueError('moving image should have 3 dimensions')
2302
+ raise ValueError('moving_dti must be 3-dimensional.')
2220
2303
  if moving_dti.components != 6:
2221
- raise ValueError('moving image should have 6 components')
2222
- # now apply the transform to the template
2223
- # 1. transform the tensor components
2304
+ raise ValueError('moving_dti must have 6 components (upper triangular format).')
2305
+
2306
+ if verbose:
2307
+ print("1. Spatially transforming DTI scalar components from moving to fixed space...")
2308
+
2309
+ # ants.apply_transforms resamples the *values* of each DTI component from 'moving_dti'
2310
+ # onto the grid of 'fixed'.
2311
+ # The output 'dtiw' will have the same spatial metadata (spacing, origin, direction) as 'fixed'.
2312
+ # However, the tensor values contained within it are still oriented as they were in
2313
+ # 'moving_dti's original image space, not 'fixed' image space, and certainly not yet reoriented
2314
+ # by the local deformation.
2224
2315
  dtsplit = moving_dti.split_channels()
2225
- dtiw = []
2316
+ dtiw_channels = []
2226
2317
  for k in range(len(dtsplit)):
2227
- dtiw.append( ants.apply_transforms( fixed, dtsplit[k], composite_transform ) )
2228
- dtiw=ants.merge_channels(dtiw) # resampled into fixed space but still based in moving index space
2318
+ dtiw_channels.append( ants.apply_transforms( fixed, dtsplit[k], composite_transform, **kwargs ) )
2319
+ dtiw = ants.merge_channels(dtiw_channels)
2320
+
2229
2321
  if verbose:
2230
- print("reorient tensors locally: compose and get reo image")
2231
- locrot = ants.deformation_gradient( ants.image_read(composite_transform),
2232
- to_rotation = True, py_based=py_based ).numpy()
2233
- # rebases from moving index to fixed index space. Not quite what we need here
2234
- # rebaser = np.dot( np.transpose( fixed.direction ), moving_dti.direction )
2322
+ print(f" DTI scalar components resampled to fixed grid. Result shape: {dtiw.shape}")
2323
+ print("2. Computing local rotation field from composite transform...")
2324
+
2325
+ # Read the composite transform as an image (assumed to be a displacement field).
2326
+ # The 'deformation_gradient_optimized' function is assumed to be 100% correct,
2327
+ # meaning it returns the appropriate local rotation matrix field (R_moving_to_fixed)
2328
+ # in (spatial_dims..., 3, 3 ) format when called with these flags.
2329
+ wtx = ants.image_read(composite_transform)
2330
+ R_moving_to_fixed_forward = deformation_gradient_optimized(
2331
+ wtx,
2332
+ to_rotation=False, # This means the *deformation gradient* F=I+J is computed first.
2333
+ to_inverse_rotation=True # This requests the inverse of the rotation part of F.
2334
+ )
2335
+
2235
2336
  if verbose:
2236
- print("convert UT to full tensor")
2237
- dtiw2tensor = triangular_to_tensor( dtiw )
2337
+ print(f" Local reorientation matrices (R_moving_to_fixed_forward) computed. Shape: {R_moving_to_fixed_forward.shape}")
2338
+ print("3. Converting 6-component DTI to full 3x3 tensors for vectorized reorientation...")
2339
+
2340
+ # Convert `dtiw` (resampled, but still in moving-image-space orientation)
2341
+ # from 6-components to full 3x3 tensor representation.
2342
+ # dtiw2tensor_np will have shape (spatial_dims..., 3, 3).
2343
+ dtiw2tensor_np = triangular_to_tensor(dtiw)
2344
+
2238
2345
  if verbose:
2239
- print("rebase tensors to new space and apply reorientation via iterator")
2240
- it = np.ndindex( fixed.shape )
2241
- for i in it:
2242
- mmm = dtiw2tensor[i]
2243
- # Rebase mmm to physical space
2244
- mmm = np.dot( mmm, np.transpose( moving_dti.direction ) )
2245
- mmm = np.dot( moving_dti.direction, mmm )
2246
- # Now apply local rotation
2247
- locrotx = np.reshape( locrot[i], [3,3] )
2248
- mmm = np.dot( mmm, np.transpose( locrotx ) )
2249
- mmm = np.dot( locrotx, mmm )
2250
- # Now rebase to fixed index space
2251
- mmm = np.dot( mmm, np.transpose( fixed.direction ) )
2252
- mmm = np.dot( fixed.direction, mmm )
2253
- dtiw2tensor[i] = mmm
2346
+ print("4. Applying vectorized tensor reorientation (Finite Strain Method)...")
2347
+
2348
+ # --- Vectorized Tensor Reorientation ---
2349
+ # This replaces the entire `for i in it:` loop and its contents with efficient NumPy operations.
2350
+
2351
+ # Step 4.1: Rebase tensors from `moving_dti.direction` coordinate system to World Coordinates.
2352
+ # D_world_moving_orient = moving_dti.direction @ D_moving_image_frame @ moving_dti.direction.T
2353
+ # This transforms the tensor's components from being relative to `moving_dti`'s image axes
2354
+ # (where they are currently defined) into absolute World (physical) coordinates.
2355
+ D_world_moving_orient = np.einsum(
2356
+ 'ab, ...bc, cd -> ...ad',
2357
+ moving_dti.direction, # 3x3 matrix (moving_image_axes -> world_axes)
2358
+ dtiw2tensor_np, # (spatial_dims..., 3, 3)
2359
+ moving_dti.direction.T # 3x3 matrix (world_axes -> moving_image_axes) - inverse of moving_dti.direction
2360
+ )
2361
+
2362
+ # Step 4.2: Apply local rotation in World Coordinates (Finite Strain Reorientation).
2363
+ # D_reoriented_world = R_moving_to_fixed_forward @ D_world_moving_orient @ (R_moving_to_fixed_forward).T
2364
+ # This is the core reorientation step, transforming the tensor's orientation from
2365
+ # the original `moving` space to the new `fixed` space, all within world coordinates.
2366
+ D_world_fixed_orient = np.einsum(
2367
+ '...ab, ...bc, ...cd -> ...ad',
2368
+ R_moving_to_fixed_forward, # (spatial_dims..., 3, 3) - local rotation
2369
+ D_world_moving_orient, # (spatial_dims..., 3, 3) - tensor in world space, moving_orient
2370
+ np.swapaxes(R_moving_to_fixed_forward, -1, -2) # (spatial_dims..., 3, 3) - transpose of local rotation
2371
+ )
2372
+
2373
+ # Step 4.3: Rebase reoriented tensors from World Coordinates to `fixed.direction` coordinate system.
2374
+ # D_final_fixed_image_frame = (fixed.direction).T @ D_world_fixed_orient @ fixed.direction
2375
+ # This transforms the tensor's components from absolute World (physical) coordinates
2376
+ # back into `fixed.direction`'s image coordinate system.
2377
+ final_dti_tensors_numpy = np.einsum(
2378
+ 'ba, ...bc, cd -> ...ad',
2379
+ fixed.direction, # Using `fixed.direction` here, but 'ba' indices specify to use its transpose.
2380
+ D_world_fixed_orient, # (spatial_dims..., 3, 3)
2381
+ fixed.direction # 3x3 matrix (world_axes -> fixed_image_axes)
2382
+ )
2383
+
2254
2384
  if verbose:
2255
- print("done with rebasing")
2256
- return dti_numpy_to_image( fixed, dtiw2tensor )
2385
+ print(" Vectorized tensor reorientation complete.")
2386
+
2387
+ if verbose:
2388
+ print("5. Converting reoriented full tensors back to 6-component ANTsImage...")
2389
+
2390
+ # Convert the final (spatial_dims..., 3, 3) NumPy array of tensors back into a
2391
+ # 6-component ANTsImage with the correct spatial metadata from `fixed`.
2392
+ final_dti_image = dti_numpy_to_image(fixed, final_dti_tensors_numpy)
2393
+
2394
+ if verbose:
2395
+ print(f"Done. Final reoriented DTI image in fixed space generated. Shape: {final_dti_image.shape}")
2396
+
2397
+ return final_dti_image
2257
2398
 
2258
2399
  def dti_reg(
2259
2400
  image,
@@ -2772,7 +2913,7 @@ def template_figure_with_overlay(scalar_label_df, prefix, outputfilename=None, t
2772
2913
  toviz = temp['overlay']
2773
2914
  return { "underlay": seggm, 'overlay': toviz, 'seg': tcrop }
2774
2915
 
2775
- def get_data( name=None, force_download=False, version=25, target_extension='.csv' ):
2916
+ def get_data( name=None, force_download=False, version=26, target_extension='.csv' ):
2776
2917
  """
2777
2918
  Get ANTsPyMM data filename
2778
2919
 
@@ -6513,7 +6654,37 @@ def bold_perfusion_minimal(
6513
6654
  return convert_np_in_dict( outdict )
6514
6655
 
6515
6656
 
6516
- def bold_perfusion( fmri, t1head, t1, t1segmentation, t1dktcit,
6657
+
6658
+ def warn_if_small_mask( mask: ants.ANTsImage, threshold_fraction: float = 0.05, label: str = ' ' ):
6659
+ """
6660
+ Warn the user if the number of non-zero voxels in the mask
6661
+ is less than a given fraction of the total number of voxels in the mask.
6662
+
6663
+ Parameters
6664
+ ----------
6665
+ mask : ants.ANTsImage
6666
+ The binary mask to evaluate.
6667
+ threshold_fraction : float, optional
6668
+ Fraction threshold below which a warning is triggered (default is 0.05).
6669
+
6670
+ Returns
6671
+ -------
6672
+ None
6673
+ """
6674
+ import warnings
6675
+ image_size = np.prod(mask.shape)
6676
+ mask_size = np.count_nonzero(mask.numpy())
6677
+ if mask_size / image_size < threshold_fraction:
6678
+ percentage = 100.0 * mask_size / image_size
6679
+ warnings.warn(
6680
+ f"[ants] Warning: {label} contains only {mask_size} voxels "
6681
+ f"({percentage:.2f}% of image volume). "
6682
+ f"This is below the threshold of {threshold_fraction * 100:.2f}% and may lead to unreliable results.",
6683
+ UserWarning
6684
+ )
6685
+
6686
+ def bold_perfusion(
6687
+ fmri, t1head, t1, t1segmentation, t1dktcit,
6517
6688
  FD_threshold=0.5,
6518
6689
  spa = (0., 0., 0., 0.),
6519
6690
  nc = 3,
@@ -6714,11 +6885,18 @@ def bold_perfusion( fmri, t1head, t1, t1segmentation, t1dktcit,
6714
6885
  newspc = [minspc,minspc,minspc]
6715
6886
  fmri_template = ants.resample_image( fmri_template, newspc, interp_type=0 )
6716
6887
 
6888
+ if verbose:
6889
+ print( 'fmri_template')
6890
+ print( fmri_template )
6891
+
6717
6892
  rig = ants.registration( fmri_template, t1head, 'BOLDRigid' )
6718
6893
  bmask = ants.apply_transforms( fmri_template,
6719
6894
  ants.threshold_image(t1segmentation,1,6),
6720
6895
  rig['fwdtransforms'][0],
6721
6896
  interpolator='genericLabel' )
6897
+
6898
+ warn_if_small_mask( bmask, label='bold_perfusion:bmask')
6899
+
6722
6900
  corrmo = timeseries_reg(
6723
6901
  fmri, fmri_template,
6724
6902
  type_of_transform=type_of_transform,
@@ -6742,6 +6920,7 @@ def bold_perfusion( fmri, t1head, t1, t1segmentation, t1dktcit,
6742
6920
  mytsnrThresh = np.quantile( mytsnr.numpy(), 0.995 )
6743
6921
  tsnrmask = ants.threshold_image( mytsnr, 0, mytsnrThresh ).morphology("close",3)
6744
6922
  bmask = bmask * ants.iMath( tsnrmask, "FillHoles" )
6923
+ warn_if_small_mask( bmask, label='bold_perfusion:bmask*tsnrmask')
6745
6924
  fmrimotcorr=corrmo['motion_corrected']
6746
6925
  und = fmri_template * bmask
6747
6926
  t1reg = ants.registration( und, t1, "SyNBold" )
@@ -6754,13 +6933,16 @@ def bold_perfusion( fmri, t1head, t1, t1segmentation, t1dktcit,
6754
6933
  csfseg = ants.threshold_image( t1segmentation, 1, 1 )
6755
6934
  wmseg = ants.threshold_image( t1segmentation, 3, 3 )
6756
6935
  csfAndWM = ( csfseg + wmseg ).morphology("erode",1)
6936
+ compcorquantile=0.50
6757
6937
  csfAndWM = ants.apply_transforms( und, csfAndWM,
6758
6938
  t1reg['fwdtransforms'], interpolator = 'nearestNeighbor' ) * bmask
6759
6939
  csfseg = ants.apply_transforms( und, csfseg,
6760
6940
  t1reg['fwdtransforms'], interpolator = 'nearestNeighbor' ) * bmask
6761
6941
  wmseg = ants.apply_transforms( und, wmseg,
6762
6942
  t1reg['fwdtransforms'], interpolator = 'nearestNeighbor' ) * bmask
6763
- compcorquantile=0.50
6943
+ warn_if_small_mask( wmseg, label='bold_perfusion:wmseg')
6944
+ # warn_if_small_mask( csfseg, threshold_fraction=0.01, label='bold_perfusion:csfseg')
6945
+ warn_if_small_mask( csfAndWM, label='bold_perfusion:csfAndWM')
6764
6946
  mycompcor = ants.compcor( fmrimotcorr,
6765
6947
  ncompcor=nc, quantile=compcorquantile, mask = csfAndWM,
6766
6948
  filter_type='polynomial', degree=2 )
@@ -7252,7 +7434,7 @@ def mm(
7252
7434
  if do_kk:
7253
7435
  if verbose:
7254
7436
  print('kk')
7255
- output_dict['kk'] = antspyt1w.kelly_kapowski_thickness( hier['brain_n4_dnz'],
7437
+ output_dict['kk'] = antspyt1w.kelly_kapowski_thickness( t1atropos,
7256
7438
  labels=hier['dkt_parc']['dkt_cortex'], iterations=45 )
7257
7439
  if perfusion_image is not None:
7258
7440
  if perfusion_image.shape[3] > 1: # FIXME - better heuristic?
@@ -7609,7 +7791,7 @@ def mm(
7609
7791
  if srmodel is not None:
7610
7792
  tspc=[1.,1.,1.]
7611
7793
  group_template2mm = ants.resample_image( group_template, tspc )
7612
- normalization_dict['DTI_norm'] = transform_and_reorient_dti( group_template2mm, mydti['dti'], comptx, py_based=True, verbose=True )
7794
+ normalization_dict['DTI_norm'] = transform_and_reorient_dti( group_template2mm, mydti['dti'], comptx, verbose=False )
7613
7795
  import shutil
7614
7796
  shutil.rmtree(output_directory, ignore_errors=True )
7615
7797
  if output_dict['rsf'] is not None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: antspymm
3
- Version: 1.5.3
3
+ Version: 1.5.5
4
4
  Summary: multi-channel/time-series medical image processing with antspyx
5
5
  Author-email: "Avants, Gosselin, Tustison, Reardon" <stnava@gmail.com>
6
6
  License: Apache-2.0
@@ -9,20 +9,18 @@ Classifier: Programming Language :: Python :: 3
9
9
  Classifier: Operating System :: OS Independent
10
10
  Requires-Python: >=3.9
11
11
  Description-Content-Type: text/markdown
12
- License-File: LICENSE
13
12
  Requires-Dist: h5py>=2.10.0
14
13
  Requires-Dist: numpy>=1.19.4
15
14
  Requires-Dist: pandas>=1.0.1
16
15
  Requires-Dist: antspyx>=0.4.2
17
- Requires-Dist: antspynet>=0.2.8
18
- Requires-Dist: antspyt1w>=0.9.3
16
+ Requires-Dist: antspynet>=0.2.9
17
+ Requires-Dist: antspyt1w>=0.9.8
19
18
  Requires-Dist: pathlib
20
19
  Requires-Dist: dipy
21
20
  Requires-Dist: nibabel
22
21
  Requires-Dist: scipy
23
22
  Requires-Dist: siq
24
23
  Requires-Dist: scikit-learn
25
- Dynamic: license-file
26
24
 
27
25
  # ANTsPyMM
28
26
 
@@ -197,6 +195,8 @@ NOTE: an example process for BIDS data on a cluster is [here](https://github.com
197
195
 
198
196
  # example processing
199
197
 
198
+ see discussion [here](https://github.com/ANTsX/ANTsPyMM/issues/26) for the organization of tests and examples.
199
+
200
200
  see the latest help but this snippet gives an idea of how one might use the package:
201
201
 
202
202
  ```python
@@ -0,0 +1,6 @@
1
+ antspymm/__init__.py,sha256=hynrdvZDlPQ0Wam8tU6mBtbEk0Worwz_bLZk9N7N1CM,4684
2
+ antspymm/mm.py,sha256=Wln4YRRbzlZwLBmXCWODtd0X_6S7-4PgvpahSg9RW54,536460
3
+ antspymm-1.5.5.dist-info/METADATA,sha256=5w6LSE2Hi2NAGvcIp0cXh87bvM_u072hIXRtAb_k5Pg,26007
4
+ antspymm-1.5.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
5
+ antspymm-1.5.5.dist-info/top_level.txt,sha256=iyD1sRhCKzfwKRJLq5ZUeV9xsv1cGQl8Ejp6QwXM1Zg,9
6
+ antspymm-1.5.5.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- antspymm/__init__.py,sha256=DnkidUfEu3Dl0tuWNTA-9VOUkBtH_cROKiPGNNXNagU,4637
2
- antspymm/mm.py,sha256=8iZxrWenPeLhwc1dxDgvAhgNGZHOahTi1LegOhmHkL8,527319
3
- antspymm-1.5.3.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
4
- antspymm-1.5.3.dist-info/METADATA,sha256=pfNoP9vDefzKmOfRYk5z68qAJXXSmY2ELLLaRioiSHs,25939
5
- antspymm-1.5.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
6
- antspymm-1.5.3.dist-info/top_level.txt,sha256=iyD1sRhCKzfwKRJLq5ZUeV9xsv1cGQl8Ejp6QwXM1Zg,9
7
- antspymm-1.5.3.dist-info/RECORD,,
@@ -1,201 +0,0 @@
1
- Apache License
2
- Version 2.0, January 2004
3
- http://www.apache.org/licenses/
4
-
5
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
-
7
- 1. Definitions.
8
-
9
- "License" shall mean the terms and conditions for use, reproduction,
10
- and distribution as defined by Sections 1 through 9 of this document.
11
-
12
- "Licensor" shall mean the copyright owner or entity authorized by
13
- the copyright owner that is granting the License.
14
-
15
- "Legal Entity" shall mean the union of the acting entity and all
16
- other entities that control, are controlled by, or are under common
17
- control with that entity. For the purposes of this definition,
18
- "control" means (i) the power, direct or indirect, to cause the
19
- direction or management of such entity, whether by contract or
20
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
- outstanding shares, or (iii) beneficial ownership of such entity.
22
-
23
- "You" (or "Your") shall mean an individual or Legal Entity
24
- exercising permissions granted by this License.
25
-
26
- "Source" form shall mean the preferred form for making modifications,
27
- including but not limited to software source code, documentation
28
- source, and configuration files.
29
-
30
- "Object" form shall mean any form resulting from mechanical
31
- transformation or translation of a Source form, including but
32
- not limited to compiled object code, generated documentation,
33
- and conversions to other media types.
34
-
35
- "Work" shall mean the work of authorship, whether in Source or
36
- Object form, made available under the License, as indicated by a
37
- copyright notice that is included in or attached to the work
38
- (an example is provided in the Appendix below).
39
-
40
- "Derivative Works" shall mean any work, whether in Source or Object
41
- form, that is based on (or derived from) the Work and for which the
42
- editorial revisions, annotations, elaborations, or other modifications
43
- represent, as a whole, an original work of authorship. For the purposes
44
- of this License, Derivative Works shall not include works that remain
45
- separable from, or merely link (or bind by name) to the interfaces of,
46
- the Work and Derivative Works thereof.
47
-
48
- "Contribution" shall mean any work of authorship, including
49
- the original version of the Work and any modifications or additions
50
- to that Work or Derivative Works thereof, that is intentionally
51
- submitted to Licensor for inclusion in the Work by the copyright owner
52
- or by an individual or Legal Entity authorized to submit on behalf of
53
- the copyright owner. For the purposes of this definition, "submitted"
54
- means any form of electronic, verbal, or written communication sent
55
- to the Licensor or its representatives, including but not limited to
56
- communication on electronic mailing lists, source code control systems,
57
- and issue tracking systems that are managed by, or on behalf of, the
58
- Licensor for the purpose of discussing and improving the Work, but
59
- excluding communication that is conspicuously marked or otherwise
60
- designated in writing by the copyright owner as "Not a Contribution."
61
-
62
- "Contributor" shall mean Licensor and any individual or Legal Entity
63
- on behalf of whom a Contribution has been received by Licensor and
64
- subsequently incorporated within the Work.
65
-
66
- 2. Grant of Copyright License. Subject to the terms and conditions of
67
- this License, each Contributor hereby grants to You a perpetual,
68
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
- copyright license to reproduce, prepare Derivative Works of,
70
- publicly display, publicly perform, sublicense, and distribute the
71
- Work and such Derivative Works in Source or Object form.
72
-
73
- 3. Grant of Patent License. Subject to the terms and conditions of
74
- this License, each Contributor hereby grants to You a perpetual,
75
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
- (except as stated in this section) patent license to make, have made,
77
- use, offer to sell, sell, import, and otherwise transfer the Work,
78
- where such license applies only to those patent claims licensable
79
- by such Contributor that are necessarily infringed by their
80
- Contribution(s) alone or by combination of their Contribution(s)
81
- with the Work to which such Contribution(s) was submitted. If You
82
- institute patent litigation against any entity (including a
83
- cross-claim or counterclaim in a lawsuit) alleging that the Work
84
- or a Contribution incorporated within the Work constitutes direct
85
- or contributory patent infringement, then any patent licenses
86
- granted to You under this License for that Work shall terminate
87
- as of the date such litigation is filed.
88
-
89
- 4. Redistribution. You may reproduce and distribute copies of the
90
- Work or Derivative Works thereof in any medium, with or without
91
- modifications, and in Source or Object form, provided that You
92
- meet the following conditions:
93
-
94
- (a) You must give any other recipients of the Work or
95
- Derivative Works a copy of this License; and
96
-
97
- (b) You must cause any modified files to carry prominent notices
98
- stating that You changed the files; and
99
-
100
- (c) You must retain, in the Source form of any Derivative Works
101
- that You distribute, all copyright, patent, trademark, and
102
- attribution notices from the Source form of the Work,
103
- excluding those notices that do not pertain to any part of
104
- the Derivative Works; and
105
-
106
- (d) If the Work includes a "NOTICE" text file as part of its
107
- distribution, then any Derivative Works that You distribute must
108
- include a readable copy of the attribution notices contained
109
- within such NOTICE file, excluding those notices that do not
110
- pertain to any part of the Derivative Works, in at least one
111
- of the following places: within a NOTICE text file distributed
112
- as part of the Derivative Works; within the Source form or
113
- documentation, if provided along with the Derivative Works; or,
114
- within a display generated by the Derivative Works, if and
115
- wherever such third-party notices normally appear. The contents
116
- of the NOTICE file are for informational purposes only and
117
- do not modify the License. You may add Your own attribution
118
- notices within Derivative Works that You distribute, alongside
119
- or as an addendum to the NOTICE text from the Work, provided
120
- that such additional attribution notices cannot be construed
121
- as modifying the License.
122
-
123
- You may add Your own copyright statement to Your modifications and
124
- may provide additional or different license terms and conditions
125
- for use, reproduction, or distribution of Your modifications, or
126
- for any such Derivative Works as a whole, provided Your use,
127
- reproduction, and distribution of the Work otherwise complies with
128
- the conditions stated in this License.
129
-
130
- 5. Submission of Contributions. Unless You explicitly state otherwise,
131
- any Contribution intentionally submitted for inclusion in the Work
132
- by You to the Licensor shall be under the terms and conditions of
133
- this License, without any additional terms or conditions.
134
- Notwithstanding the above, nothing herein shall supersede or modify
135
- the terms of any separate license agreement you may have executed
136
- with Licensor regarding such Contributions.
137
-
138
- 6. Trademarks. This License does not grant permission to use the trade
139
- names, trademarks, service marks, or product names of the Licensor,
140
- except as required for reasonable and customary use in describing the
141
- origin of the Work and reproducing the content of the NOTICE file.
142
-
143
- 7. Disclaimer of Warranty. Unless required by applicable law or
144
- agreed to in writing, Licensor provides the Work (and each
145
- Contributor provides its Contributions) on an "AS IS" BASIS,
146
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
- implied, including, without limitation, any warranties or conditions
148
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
- PARTICULAR PURPOSE. You are solely responsible for determining the
150
- appropriateness of using or redistributing the Work and assume any
151
- risks associated with Your exercise of permissions under this License.
152
-
153
- 8. Limitation of Liability. In no event and under no legal theory,
154
- whether in tort (including negligence), contract, or otherwise,
155
- unless required by applicable law (such as deliberate and grossly
156
- negligent acts) or agreed to in writing, shall any Contributor be
157
- liable to You for damages, including any direct, indirect, special,
158
- incidental, or consequential damages of any character arising as a
159
- result of this License or out of the use or inability to use the
160
- Work (including but not limited to damages for loss of goodwill,
161
- work stoppage, computer failure or malfunction, or any and all
162
- other commercial damages or losses), even if such Contributor
163
- has been advised of the possibility of such damages.
164
-
165
- 9. Accepting Warranty or Additional Liability. While redistributing
166
- the Work or Derivative Works thereof, You may choose to offer,
167
- and charge a fee for, acceptance of support, warranty, indemnity,
168
- or other liability obligations and/or rights consistent with this
169
- License. However, in accepting such obligations, You may act only
170
- on Your own behalf and on Your sole responsibility, not on behalf
171
- of any other Contributor, and only if You agree to indemnify,
172
- defend, and hold each Contributor harmless for any liability
173
- incurred by, or claims asserted against, such Contributor by reason
174
- of your accepting any such warranty or additional liability.
175
-
176
- END OF TERMS AND CONDITIONS
177
-
178
- APPENDIX: How to apply the Apache License to your work.
179
-
180
- To apply the Apache License to your work, attach the following
181
- boilerplate notice, with the fields enclosed by brackets "[]"
182
- replaced with your own identifying information. (Don't include
183
- the brackets!) The text should be enclosed in the appropriate
184
- comment syntax for the file format. We also recommend that a
185
- file or class name and description of purpose be included on the
186
- same "printed page" as the copyright notice for easier
187
- identification within third-party archives.
188
-
189
- Copyright [yyyy] [name of copyright owner]
190
-
191
- Licensed under the Apache License, Version 2.0 (the "License");
192
- you may not use this file except in compliance with the License.
193
- You may obtain a copy of the License at
194
-
195
- http://www.apache.org/licenses/LICENSE-2.0
196
-
197
- Unless required by applicable law or agreed to in writing, software
198
- distributed under the License is distributed on an "AS IS" BASIS,
199
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
- See the License for the specific language governing permissions and
201
- limitations under the License.