nettracer3d 0.6.7__py3-none-any.whl → 0.6.9__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.
nettracer3d/proximity.py CHANGED
@@ -82,7 +82,7 @@ def _get_node_node_dict(label_array, label, dilate_xy, dilate_z, fastdil = False
82
82
  def process_label(args):
83
83
  """Modified to use pre-computed bounding boxes instead of argwhere"""
84
84
  nodes, label, dilate_xy, dilate_z, array_shape, bounding_boxes = args
85
- #print(f"Processing node {label}")
85
+ print(f"Processing node {label}")
86
86
 
87
87
  # Get the pre-computed bounding box for this label
88
88
  slice_obj = bounding_boxes[label-1] # -1 because label numbers start at 1
@@ -178,9 +178,31 @@ def populate_array(centroids):
178
178
 
179
179
  return array
180
180
 
181
- def find_neighbors_kdtree(array, radius, targets=None):
181
+ def find_neighbors_kdtree(radius, centroids=None, array=None, targets=None):
182
182
  # Get coordinates of nonzero points
183
- points = np.transpose(np.nonzero(array))
183
+ if centroids:
184
+ # If centroids is a dictionary mapping node IDs to coordinates
185
+ if isinstance(centroids, dict):
186
+ # Extract the node IDs and points
187
+ node_ids = list(centroids.keys())
188
+ points_list = list(centroids.values())
189
+ points = np.array(points_list, dtype=np.int32)
190
+ else:
191
+ # If centroids is just a list of points
192
+ points = np.array(centroids, dtype=np.int32)
193
+ node_ids = list(range(1, len(points) + 1)) # Default sequential IDs
194
+
195
+ # Create a temporary array only if we need it for lookups
196
+ if array is None:
197
+ max_coords = np.max(points, axis=0) + 1
198
+ array = np.zeros(tuple(max_coords), dtype=np.int32)
199
+ for i, point in enumerate(points):
200
+ array[tuple(point)] = node_ids[i] # Use the actual node ID
201
+ elif array is not None:
202
+ points = np.transpose(np.nonzero(array))
203
+ node_ids = None # Not used in array-based mode
204
+ else:
205
+ return []
184
206
 
185
207
  # Create KD-tree from all nonzero points
186
208
  tree = KDTree(points)
@@ -188,19 +210,29 @@ def find_neighbors_kdtree(array, radius, targets=None):
188
210
  if targets is None:
189
211
  # Original behavior: find neighbors for all points
190
212
  query_points = points
191
- query_indices = range(len(points)) # Add this line
213
+ query_indices = range(len(points))
192
214
  else:
193
215
  # Find coordinates of target values
194
216
  target_points = []
195
- target_indices = [] # Add this line
196
- for idx, point in enumerate(points):
197
- if array[tuple(point)] in targets:
198
- target_points.append(point)
199
- target_indices.append(idx) # Add this line
217
+ target_indices = []
218
+
219
+ if array is not None:
220
+ # Standard array-based filtering
221
+ for idx, point in enumerate(points):
222
+ point_tuple = tuple(point)
223
+ if array[point_tuple] in targets:
224
+ target_points.append(point)
225
+ target_indices.append(idx)
226
+ else:
227
+ # Filter based on node IDs directly
228
+ for idx, node_id in enumerate(node_ids):
229
+ if node_id in targets:
230
+ target_points.append(points[idx])
231
+ target_indices.append(idx)
200
232
 
201
233
  # Convert to numpy array for querying
202
234
  query_points = np.array(target_points)
203
- query_indices = target_indices # Add this line
235
+ query_indices = target_indices
204
236
 
205
237
  # Handle case where no target values were found
206
238
  if len(query_points) == 0:
@@ -214,17 +246,21 @@ def find_neighbors_kdtree(array, radius, targets=None):
214
246
 
215
247
  # Generate pairs
216
248
  for i, neighbors in enumerate(neighbor_indices):
217
- query_idx = query_indices[i] # Modified this line
249
+ query_idx = query_indices[i]
218
250
  for neighbor_idx in neighbors:
219
251
  # Skip self-pairing
220
252
  if neighbor_idx != query_idx:
221
- query_value = array[tuple(points[query_idx])]
222
- neighbor_value = array[tuple(points[neighbor_idx])]
253
+ # Use node IDs from the dictionary if available
254
+ if array is not None:
255
+ query_value = array[tuple(points[query_idx])]
256
+ neighbor_value = array[tuple(points[neighbor_idx])]
257
+ else:
258
+ query_value = node_ids[query_idx]
259
+ neighbor_value = node_ids[neighbor_idx]
223
260
  output.append([query_value, neighbor_value, 0])
224
261
 
225
262
  return output
226
263
 
227
-
228
264
  def extract_pairwise_connections(connections):
229
265
  output = []
230
266
 
nettracer3d/segmenter.py CHANGED
@@ -1011,7 +1011,7 @@ class InteractiveSegmenter:
1011
1011
  futures.append(future)
1012
1012
 
1013
1013
  def compute_dog_local(img, s1, s2):
1014
- g1 = ndimage.gaussian_filter(img, s1)
1014
+ g1 = ndimage.gaussian_filter(img, s1) # Consider just having this return the gaussians to
1015
1015
  g2 = ndimage.gaussian_filter(img, s2)
1016
1016
  return g1 - g2
1017
1017
 
@@ -192,7 +192,8 @@ def dilate_3D_dt(array, search_distance, xy_scaling=1.0, z_scaling=1.0, GPU = Fa
192
192
 
193
193
  return nettracer.dilate_2D(array, search_distance, scaling = xy_scaling)
194
194
 
195
- # Determine which dimension needs resampling
195
+ # Determine which dimension needs resampling. the moral of the story is read documentation before you do something unecessary.
196
+ """
196
197
  if (z_scaling > xy_scaling):
197
198
  # Z dimension needs to be stretched
198
199
  zoom_factor = [z_scaling/xy_scaling, 1, 1] # Scale factor for [z, y, x]
@@ -208,11 +209,11 @@ def dilate_3D_dt(array, search_distance, xy_scaling=1.0, z_scaling=1.0, GPU = Fa
208
209
  zoom_factor = None
209
210
  rev_factor = None
210
211
  cardinal = xy_scaling
211
-
212
+ """
212
213
 
213
214
  # Resample the mask if needed
214
- if zoom_factor:
215
- array = ndimage.zoom(array, zoom_factor, order=0) # Use order=0 for binary masks
215
+ #if zoom_factor:
216
+ #array = ndimage.zoom(array, zoom_factor, order=0) # Use order=0 for binary masks
216
217
 
217
218
  # Invert the array (find background)
218
219
  inv = array < 1
@@ -220,22 +221,22 @@ def dilate_3D_dt(array, search_distance, xy_scaling=1.0, z_scaling=1.0, GPU = Fa
220
221
  if GPU:
221
222
  try:
222
223
  print("Attempting on GPU...")
223
- inv, indices = compute_distance_transform_GPU(inv, return_dists = True)
224
+ inv, indices = compute_distance_transform_GPU(inv, return_dists = True, sampling = [z_scaling, xy_scaling, xy_scaling])
224
225
  except:
225
226
  print("Failed, attempting on CPU...")
226
227
  #Who would have seen this coming?:
227
- inv, indices = compute_distance_transform(inv, return_dists = True)
228
+ inv, indices = compute_distance_transform(inv, return_dists = True, sampling = [z_scaling, xy_scaling, xy_scaling])
228
229
  else:
229
- inv, indices = compute_distance_transform(inv, return_dists = True)
230
+ inv, indices = compute_distance_transform(inv, return_dists = True, sampling = [z_scaling, xy_scaling, xy_scaling])
230
231
 
231
232
 
232
- inv = inv * cardinal
233
+ #inv = inv * cardinal
233
234
 
234
235
  # Threshold the distance transform to get dilated result
235
236
  inv = inv <= search_distance
236
237
 
237
238
 
238
- return inv.astype(np.uint8), indices, array, rev_factor
239
+ return inv.astype(np.uint8), indices, array
239
240
 
240
241
 
241
242
 
@@ -275,7 +276,7 @@ def smart_dilate(nodes, dilate_xy, dilate_z, directory = None, GPU = True, fast_
275
276
  binary_nodes = binarize(nodes)
276
277
  dilated_binary_nodes = dilate_3D(binary_nodes, dilate_xy, dilate_xy, dilate_z)
277
278
  else:
278
- dilated_binary_nodes, nearest_label_indices, nodes, rev_factor = dilate_3D_dt(nodes, use_dt_dil_amount, GPU = GPU, xy_scaling = xy_scale, z_scaling = z_scale)
279
+ dilated_binary_nodes, nearest_label_indices, nodes = dilate_3D_dt(nodes, use_dt_dil_amount, GPU = GPU, xy_scaling = xy_scale, z_scaling = z_scale)
279
280
  binary_nodes = binarize(nodes)
280
281
 
281
282
  # Step 3: Isolate the ring (binary dilated mask minus original binary mask)
@@ -352,8 +353,6 @@ def smart_dilate(nodes, dilate_xy, dilate_z, directory = None, GPU = True, fast_
352
353
  if (dilated_nodes_with_labels.shape[1] < original_shape[1]) and fast_dil: #If downsample was used, upsample output
353
354
  dilated_nodes_with_labels = nettracer.upsample_with_padding(dilated_nodes_with_labels, downsample_needed, original_shape)
354
355
  dilated_nodes_with_labels = dilated_nodes_with_labels * dilated_mask
355
- elif (dilated_nodes_with_labels.shape[1] != original_shape[1]) and not fast_dil:
356
- dilated_nodes_with_labels = ndimage.zoom(dilated_nodes_with_labels, rev_factor, order=0)
357
356
 
358
357
  if directory is not None:
359
358
  try:
@@ -472,7 +471,7 @@ def smart_label(binary_array, label_array, directory = None, GPU = True, predown
472
471
 
473
472
  return dilated_nodes_with_labels
474
473
 
475
- def compute_distance_transform_GPU(nodes, return_dists = False):
474
+ def compute_distance_transform_GPU(nodes, return_dists = False, sampling = [1, 1, 1]):
476
475
  is_pseudo_3d = nodes.shape[0] == 1
477
476
  if is_pseudo_3d:
478
477
  nodes = np.squeeze(nodes) # Convert to 2D for processing
@@ -481,7 +480,7 @@ def compute_distance_transform_GPU(nodes, return_dists = False):
481
480
  nodes_cp = cp.asarray(nodes)
482
481
 
483
482
  # Compute the distance transform on the GPU
484
- dists, nearest_label_indices = cpx.distance_transform_edt(nodes_cp, return_indices=True)
483
+ dists, nearest_label_indices = cpx.distance_transform_edt(nodes_cp, return_indices=True, sampling = sampling)
485
484
 
486
485
  # Convert results back to numpy arrays
487
486
  nearest_label_indices_np = cp.asnumpy(nearest_label_indices)
@@ -504,12 +503,12 @@ def compute_distance_transform_GPU(nodes, return_dists = False):
504
503
  return dists, nearest_label_indices_np
505
504
 
506
505
 
507
- def compute_distance_transform(nodes, return_dists = False):
506
+ def compute_distance_transform(nodes, return_dists = False, sampling = [1, 1, 1]):
508
507
  is_pseudo_3d = nodes.shape[0] == 1
509
508
  if is_pseudo_3d:
510
509
  nodes = np.squeeze(nodes) # Convert to 2D for processing
511
510
 
512
- dists, nearest_label_indices = distance_transform_edt(nodes, return_indices=True)
511
+ dists, nearest_label_indices = distance_transform_edt(nodes, return_indices=True, sampling = sampling)
513
512
 
514
513
  if is_pseudo_3d:
515
514
  # For 2D input, we get (2, H, W) but need (3, 1, H, W)
@@ -529,7 +528,7 @@ def compute_distance_transform(nodes, return_dists = False):
529
528
 
530
529
 
531
530
 
532
- def compute_distance_transform_distance_GPU(nodes):
531
+ def compute_distance_transform_distance_GPU(nodes, sampling = [1, 1, 1]):
533
532
 
534
533
  is_pseudo_3d = nodes.shape[0] == 1
535
534
  if is_pseudo_3d:
@@ -539,7 +538,7 @@ def compute_distance_transform_distance_GPU(nodes):
539
538
  nodes_cp = cp.asarray(nodes)
540
539
 
541
540
  # Compute the distance transform on the GPU
542
- distance = cpx.distance_transform_edt(nodes_cp)
541
+ distance = cpx.distance_transform_edt(nodes_cp, sampling = sampling)
543
542
 
544
543
  # Convert results back to numpy arrays
545
544
  distance = cp.asnumpy(distance)
@@ -550,14 +549,14 @@ def compute_distance_transform_distance_GPU(nodes):
550
549
  return distance
551
550
 
552
551
 
553
- def compute_distance_transform_distance(nodes):
552
+ def compute_distance_transform_distance(nodes, sampling = [1, 1, 1]):
554
553
 
555
554
  is_pseudo_3d = nodes.shape[0] == 1
556
555
  if is_pseudo_3d:
557
556
  nodes = np.squeeze(nodes) # Convert to 2D for processing
558
557
 
559
558
  # Fallback to CPU if there's an issue with GPU computation
560
- distance = distance_transform_edt(nodes)
559
+ distance = distance_transform_edt(nodes, sampling = sampling)
561
560
  if is_pseudo_3d:
562
561
  np.expand_dims(distance, axis = 0)
563
562
  return distance
@@ -1,14 +1,15 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nettracer3d
3
- Version: 0.6.7
3
+ Version: 0.6.9
4
4
  Summary: Scripts for intializing and analyzing networks from segmentations of three dimensional images.
5
- Author-email: Liam McLaughlin <mclaughlinliam99@gmail.com>
6
- Project-URL: User_Tutorial, https://www.youtube.com/watch?v=cRatn5VTWDY
5
+ Author-email: Liam McLaughlin <liamm@wustl.edu>
6
+ Project-URL: Documentation, https://nettracer3d.readthedocs.io/en/latest/
7
+ Project-URL: Video_Tutorial, https://www.youtube.com/watch?v=cRatn5VTWDY
7
8
  Project-URL: Reference_Citation_For_Use, https://doi.org/10.1101/2024.07.29.605633
8
9
  Classifier: Programming Language :: Python :: 3
9
10
  Classifier: License :: Other/Proprietary License
10
11
  Classifier: Operating System :: OS Independent
11
- Requires-Python: >=3.8
12
+ Requires-Python: ==3.11
12
13
  Description-Content-Type: text/markdown
13
14
  License-File: LICENSE
14
15
  Requires-Dist: numpy==1.26.4
@@ -38,20 +39,46 @@ Dynamic: license-file
38
39
 
39
40
  NetTracer3D is a python package developed for both 2D and 3D analysis of microscopic images in the .tif file format. It supports generation of 3D networks showing the relationships between objects (or nodes) in three dimensional space, either based on their own proximity or connectivity via connecting objects such as nerves or blood vessels. In addition to these functionalities are several advanced 3D data processing algorithms, such as labeling of branched structures or abstraction of branched structures into networks. Note that nettracer3d uses segmented data, which can be segmented from other softwares such as ImageJ and imported into NetTracer3D, although it does offer its own segmentation via intensity and volumetric thresholding, or random forest machine learning segmentation. NetTracer3D currently has a fully functional GUI. To use the GUI, after installing the nettracer3d package via pip, enter the command 'nettracer3d' in your command prompt:
40
41
 
42
+ --- Documentation ---
41
43
 
42
- This gui is built from the PyQt6 package and therefore may not function on dockers or virtual envs that are unable to support PyQt6 displays. More advanced documentation is coming down the line, but for now please see: https://www.youtube.com/watch?v=cRatn5VTWDY
43
- for a video tutorial on using the GUI.
44
+ Please see: https://nettracer3d.readthedocs.io/en/latest/
45
+
46
+ --- Installation ---
47
+
48
+ To install nettracer3d, simply install Python and use this command in your command terminal:
49
+
50
+ pip install nettracer3d
51
+
52
+ I recommend installing the program as an Anaconda package to ensure its modules are work together on your specific system:
53
+ (Install anaconda at the link below, set up a new python env for nettracer3d, then use the same pip command).
54
+
55
+ https://www.anaconda.com/download?utm_source=anacondadocs&utm_medium=documentation&utm_campaign=download&utm_content=installwindows
56
+
57
+ nettracer3d mostly utilizes the CPU for processing and visualization, although it does have a few GPU-aided options. If you would like to use the GPU for these, you will need an NVIDIA GPU and a corresponding CUDA toolkit which can be installed here:
58
+ https://developer.nvidia.com/cuda-toolkit
59
+
60
+ To install nettracer3d with associated GPU-supporting packages, please use:
61
+
62
+ If your CUDA toolkit is version 11: pip install nettracer3d[CUDA11]
63
+ If your CUDA toolkit is version 12: pip install nettracer3d[CUDA12]
64
+ If you just want the entire cupy library: pip install nettracer3d[cupy]
65
+
66
+
67
+ This gui is built from the PyQt6 package and therefore may not function on dockers or virtual envs that are unable to support PyQt6 displays.
68
+
69
+
70
+ For a (slightly outdated) video tutorial on using the GUI: https://www.youtube.com/watch?v=cRatn5VTWDY
44
71
 
45
72
  NetTracer3D is free to use/fork for academic/nonprofit use so long as citation is provided, and is available for commercial use at a fee (see license file for information).
46
73
 
47
74
  NetTracer3D was developed by Liam McLaughlin while working under Dr. Sanjay Jain at Washington University School of Medicine.
48
75
 
49
- -- Version 0.6.7 updates --
76
+ -- Version 0.6.9 updates --
50
77
 
51
- 1. Updated all methods to use dilation to allow the user to select between perfect distance transform based dilation (which can be slower but allows for perfect searching - and is designed to account for scaling differences), or the current pseudo-3d kernel method.
78
+ 1. Adjusted all distance transform-based dilation/radius calculating methods to simply use the already supported scipy.ndimage.distance_transform_edt() sampling parameter to account for differentially scaled axis (previously the image was being resampled but now it no longer will need to do that).
52
79
 
53
- 1.5. The dt dilator accounts for scaling by stretching (upsampling) images to equivalent scales before dilating with the distance transform. It will not attempt to downsample. This admittedly will ask for greater memory and some more processing. To give the user the option to use the dt dilator without dealing with this, I added two new options to the resize method. You can now have it upsample your image until its equivalently scaled, or, if you don't need the fidelity, downsample your image until it's equivalently scaled. When the scaling is equivalent, the dt dilator will always just use the regular distance transform without attempting to resize the array.
80
+ 2. Added new right click option to extract highlighted regions and implant their data onto a separate image or into a new empty image.
54
81
 
55
- 2. Fixed radius finding method to also account for scaling correctly. Previous method scaled wrong. New method predictably accounts for differing scaling in xy vs z dims as well.
82
+ 3. General bug fixes and improvements.
56
83
 
57
- 3. Bug fixes.
84
+ 4. Now specifies python 3.11.
@@ -0,0 +1,20 @@
1
+ nettracer3d/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ nettracer3d/community_extractor.py,sha256=5v9SCCLX3P1RX0fjPVKH5NHMFkMolZ5BTe0bR_a67xg,24479
3
+ nettracer3d/modularity.py,sha256=FH3GpTHorRNkdQULe-2DWgFE3i0_u__hrao7Nx_6Ge4,30249
4
+ nettracer3d/morphology.py,sha256=y6OXLvyRmIBFpF3snC7ZirOW3Hg9jsHE11wbe0HrzQM,19692
5
+ nettracer3d/nettracer.py,sha256=muv5Z33KOLKzzzbnNLDad_z1LYCKbuQUuKQLFQ0HAPY,211734
6
+ nettracer3d/nettracer_gui.py,sha256=UCls6Z8O3SaXJUyxzdJlPDxIug7w290VbrojSWQDKs8,417722
7
+ nettracer3d/network_analysis.py,sha256=q1q7lxtA3lebxitfC_jfiT9cnpYXJw4q0Oy2_-Aj8qE,48068
8
+ nettracer3d/network_draw.py,sha256=F7fw6Pcf4qWOhdKwLmhwqWdschbDlHzwCVolQC9imeU,14117
9
+ nettracer3d/node_draw.py,sha256=k3sCTfUCJs3aH1C1q1gTNxDz9EAQbBd1hsUIJajxRx8,9823
10
+ nettracer3d/proximity.py,sha256=-HoJseoD2O2Q1eLDBMMmM_UYPqM1vZg7bpG4_9Ime-o,12516
11
+ nettracer3d/run.py,sha256=xYeaAc8FCx8MuzTGyL3NR3mK7WZzffAYAH23bNRZYO4,127
12
+ nettracer3d/segmenter.py,sha256=GnQTVisQUKhackgjFxoldMlbArHEwHGiZPwv-sgPTj0,85072
13
+ nettracer3d/simple_network.py,sha256=fP1gkDdtQcHruEZpUdasKdZeVacoLOxKhR3bY0L1CAQ,15426
14
+ nettracer3d/smart_dilate.py,sha256=SKm5OSu7jcnA7eUKz58_LscadV-lCvY2ZzdVzCvTmkY,25796
15
+ nettracer3d-0.6.9.dist-info/licenses/LICENSE,sha256=gM207DhJjWrxLuEWXl0Qz5ISbtWDmADfjHp3yC2XISs,888
16
+ nettracer3d-0.6.9.dist-info/METADATA,sha256=5JFlDK6cwwRKV25onj8KGX6ylD4vFXMaoZM1lzZCGaw,4755
17
+ nettracer3d-0.6.9.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
18
+ nettracer3d-0.6.9.dist-info/entry_points.txt,sha256=Nx1rr_0QhJXDBHAQg2vcqCzLMKBzSHfwy3xwGkueVyc,53
19
+ nettracer3d-0.6.9.dist-info/top_level.txt,sha256=zsYy9rZwirfCEOubolhee4TyzqBAL5gSUeFMzhFTX8c,12
20
+ nettracer3d-0.6.9.dist-info/RECORD,,
@@ -1,20 +0,0 @@
1
- nettracer3d/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- nettracer3d/community_extractor.py,sha256=5v9SCCLX3P1RX0fjPVKH5NHMFkMolZ5BTe0bR_a67xg,24479
3
- nettracer3d/modularity.py,sha256=V1f3s_vGd8EuVz27mzq6ycIGr0BWIpH7c7NU4QjgAHU,30247
4
- nettracer3d/morphology.py,sha256=P7hH9qpDBs0JtMSd95NmrvqoyD8BVq3AjAYv-MWoS_Y,19498
5
- nettracer3d/nettracer.py,sha256=HDU7z9UOpc2rK1tp-gV7vum27NBNVe8CmfZEeJ7lDBc,209469
6
- nettracer3d/nettracer_gui.py,sha256=ba_Kx84iu6qfdYKLjhwrS7cXvQQL0_YxrxM9PdIp6kk,401549
7
- nettracer3d/network_analysis.py,sha256=q1q7lxtA3lebxitfC_jfiT9cnpYXJw4q0Oy2_-Aj8qE,48068
8
- nettracer3d/network_draw.py,sha256=F7fw6Pcf4qWOhdKwLmhwqWdschbDlHzwCVolQC9imeU,14117
9
- nettracer3d/node_draw.py,sha256=k3sCTfUCJs3aH1C1q1gTNxDz9EAQbBd1hsUIJajxRx8,9823
10
- nettracer3d/proximity.py,sha256=mHgU24GZy5GGrR6RETB7QACfOURxgiyUze2dxMfs_3o,10917
11
- nettracer3d/run.py,sha256=xYeaAc8FCx8MuzTGyL3NR3mK7WZzffAYAH23bNRZYO4,127
12
- nettracer3d/segmenter.py,sha256=NcNeLSfg3ox-CfnUajT1E2iDqDkv5H6zSJOK_L5N4YI,85020
13
- nettracer3d/simple_network.py,sha256=fP1gkDdtQcHruEZpUdasKdZeVacoLOxKhR3bY0L1CAQ,15426
14
- nettracer3d/smart_dilate.py,sha256=ISZR6v52zf-MwhGx-JTfTOP8uo7pNGt-GJj7ydeuMAo,25587
15
- nettracer3d-0.6.7.dist-info/licenses/LICENSE,sha256=gM207DhJjWrxLuEWXl0Qz5ISbtWDmADfjHp3yC2XISs,888
16
- nettracer3d-0.6.7.dist-info/METADATA,sha256=jAjlCQhz-wFDiHbqF-nbVpEKu95n77H8CZNLP2cRnGI,4172
17
- nettracer3d-0.6.7.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
18
- nettracer3d-0.6.7.dist-info/entry_points.txt,sha256=Nx1rr_0QhJXDBHAQg2vcqCzLMKBzSHfwy3xwGkueVyc,53
19
- nettracer3d-0.6.7.dist-info/top_level.txt,sha256=zsYy9rZwirfCEOubolhee4TyzqBAL5gSUeFMzhFTX8c,12
20
- nettracer3d-0.6.7.dist-info/RECORD,,