nettracer3d 0.6.8__tar.gz → 0.7.0__tar.gz

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.
Files changed (27) hide show
  1. {nettracer3d-0.6.8/src/nettracer3d.egg-info → nettracer3d-0.7.0}/PKG-INFO +42 -9
  2. nettracer3d-0.7.0/README.md +47 -0
  3. {nettracer3d-0.6.8 → nettracer3d-0.7.0}/pyproject.toml +5 -4
  4. {nettracer3d-0.6.8 → nettracer3d-0.7.0}/src/nettracer3d/modularity.py +23 -24
  5. {nettracer3d-0.6.8 → nettracer3d-0.7.0}/src/nettracer3d/morphology.py +14 -9
  6. {nettracer3d-0.6.8 → nettracer3d-0.7.0}/src/nettracer3d/nettracer.py +271 -44
  7. {nettracer3d-0.6.8 → nettracer3d-0.7.0}/src/nettracer3d/nettracer_gui.py +502 -64
  8. nettracer3d-0.7.0/src/nettracer3d/proximity.py +649 -0
  9. {nettracer3d-0.6.8 → nettracer3d-0.7.0}/src/nettracer3d/segmenter.py +87 -4
  10. {nettracer3d-0.6.8 → nettracer3d-0.7.0}/src/nettracer3d/smart_dilate.py +23 -24
  11. {nettracer3d-0.6.8 → nettracer3d-0.7.0/src/nettracer3d.egg-info}/PKG-INFO +42 -9
  12. nettracer3d-0.6.8/README.md +0 -15
  13. nettracer3d-0.6.8/src/nettracer3d/proximity.py +0 -289
  14. {nettracer3d-0.6.8 → nettracer3d-0.7.0}/LICENSE +0 -0
  15. {nettracer3d-0.6.8 → nettracer3d-0.7.0}/setup.cfg +0 -0
  16. {nettracer3d-0.6.8 → nettracer3d-0.7.0}/src/nettracer3d/__init__.py +0 -0
  17. {nettracer3d-0.6.8 → nettracer3d-0.7.0}/src/nettracer3d/community_extractor.py +0 -0
  18. {nettracer3d-0.6.8 → nettracer3d-0.7.0}/src/nettracer3d/network_analysis.py +0 -0
  19. {nettracer3d-0.6.8 → nettracer3d-0.7.0}/src/nettracer3d/network_draw.py +0 -0
  20. {nettracer3d-0.6.8 → nettracer3d-0.7.0}/src/nettracer3d/node_draw.py +0 -0
  21. {nettracer3d-0.6.8 → nettracer3d-0.7.0}/src/nettracer3d/run.py +0 -0
  22. {nettracer3d-0.6.8 → nettracer3d-0.7.0}/src/nettracer3d/simple_network.py +0 -0
  23. {nettracer3d-0.6.8 → nettracer3d-0.7.0}/src/nettracer3d.egg-info/SOURCES.txt +0 -0
  24. {nettracer3d-0.6.8 → nettracer3d-0.7.0}/src/nettracer3d.egg-info/dependency_links.txt +0 -0
  25. {nettracer3d-0.6.8 → nettracer3d-0.7.0}/src/nettracer3d.egg-info/entry_points.txt +0 -0
  26. {nettracer3d-0.6.8 → nettracer3d-0.7.0}/src/nettracer3d.egg-info/requires.txt +0 -0
  27. {nettracer3d-0.6.8 → nettracer3d-0.7.0}/src/nettracer3d.egg-info/top_level.txt +0 -0
@@ -1,14 +1,15 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nettracer3d
3
- Version: 0.6.8
3
+ Version: 0.7.0
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,16 +39,48 @@ 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.8 updates --
76
+ -- Version 0.7.0 Updates --
77
+
78
+ 1. Added new function in 'Analyze -> Stats -> Cluster Analysis'
79
+ * This function allows the user to create a ripley's K or H function to compare the relative clustering of two types of nodes, or of one type of node vs itself.
50
80
 
51
- 1. Added new fill-can and 3D-brush functionalities to the brush mode (press f in brush mode to toggle the fill can. Press d while in brush mode to use the 3D painting tools. Standard Mouse wheel scrolling in the 3D painter will change how many frames you paint on - ie. 5 lets you paint 2 above and 2 below).
81
+ 2. Added new function in 'Analyze -> Randomize -> Scramble Nodes'
82
+ * This function randomly rearranges the node (centroids) for comparison with other centroid-using methods, as a possible way to demonstrate non-random behavior.
83
+ * The randomize menu is likewise new and the 'Generate Equivalent Random Network' method was moved there.
52
84
 
53
- 1.5. Added single-use ctrl-z functionality to the fill can only because of how easily it can mess up. (Leaving the fill can mode will garbage collect the backup image though).
85
+ 3. Bug fixes.
86
+ * Importantly fixed a bug with dt-based dilation not working in 2D, which I had accidentally introduced recently.
@@ -0,0 +1,47 @@
1
+ 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:
2
+
3
+ --- Documentation ---
4
+
5
+ Please see: https://nettracer3d.readthedocs.io/en/latest/
6
+
7
+ --- Installation ---
8
+
9
+ To install nettracer3d, simply install Python and use this command in your command terminal:
10
+
11
+ pip install nettracer3d
12
+
13
+ I recommend installing the program as an Anaconda package to ensure its modules are work together on your specific system:
14
+ (Install anaconda at the link below, set up a new python env for nettracer3d, then use the same pip command).
15
+
16
+ https://www.anaconda.com/download?utm_source=anacondadocs&utm_medium=documentation&utm_campaign=download&utm_content=installwindows
17
+
18
+ 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:
19
+ https://developer.nvidia.com/cuda-toolkit
20
+
21
+ To install nettracer3d with associated GPU-supporting packages, please use:
22
+
23
+ If your CUDA toolkit is version 11: pip install nettracer3d[CUDA11]
24
+ If your CUDA toolkit is version 12: pip install nettracer3d[CUDA12]
25
+ If you just want the entire cupy library: pip install nettracer3d[cupy]
26
+
27
+
28
+ 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.
29
+
30
+
31
+ For a (slightly outdated) video tutorial on using the GUI: https://www.youtube.com/watch?v=cRatn5VTWDY
32
+
33
+ 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).
34
+
35
+ NetTracer3D was developed by Liam McLaughlin while working under Dr. Sanjay Jain at Washington University School of Medicine.
36
+
37
+ -- Version 0.7.0 Updates --
38
+
39
+ 1. Added new function in 'Analyze -> Stats -> Cluster Analysis'
40
+ * This function allows the user to create a ripley's K or H function to compare the relative clustering of two types of nodes, or of one type of node vs itself.
41
+
42
+ 2. Added new function in 'Analyze -> Randomize -> Scramble Nodes'
43
+ * This function randomly rearranges the node (centroids) for comparison with other centroid-using methods, as a possible way to demonstrate non-random behavior.
44
+ * The randomize menu is likewise new and the 'Generate Equivalent Random Network' method was moved there.
45
+
46
+ 3. Bug fixes.
47
+ * Importantly fixed a bug with dt-based dilation not working in 2D, which I had accidentally introduced recently.
@@ -1,8 +1,8 @@
1
1
  [project]
2
2
  name = "nettracer3d"
3
- version = "0.6.8"
3
+ version = "0.7.0"
4
4
  authors = [
5
- { name="Liam McLaughlin", email="mclaughlinliam99@gmail.com" },
5
+ { name="Liam McLaughlin", email="liamm@wustl.edu" },
6
6
  ]
7
7
  description = "Scripts for intializing and analyzing networks from segmentations of three dimensional images."
8
8
 
@@ -27,7 +27,7 @@ dependencies = [
27
27
  ]
28
28
 
29
29
  readme = "README.md"
30
- requires-python = ">=3.8"
30
+ requires-python = "==3.11"
31
31
  classifiers = [
32
32
  "Programming Language :: Python :: 3",
33
33
  "License :: Other/Proprietary License",
@@ -49,5 +49,6 @@ cupy = [
49
49
  nettracer3d = "nettracer3d.run:main"
50
50
 
51
51
  [project.urls]
52
- User_Tutorial = "https://www.youtube.com/watch?v=cRatn5VTWDY"
52
+ Documentation = "https://nettracer3d.readthedocs.io/en/latest/"
53
+ Video_Tutorial = "https://www.youtube.com/watch?v=cRatn5VTWDY"
53
54
  Reference_Citation_For_Use = "https://doi.org/10.1101/2024.07.29.605633"
@@ -446,31 +446,11 @@ def community_partition(master_list, weighted = False, style = 0, dostats = True
446
446
  except:
447
447
  pass
448
448
 
449
- try:
450
- # Per-community statistics
451
- for i, com in enumerate(communities):
452
- subgraph = G.subgraph(com)
453
-
454
- # Basic community metrics
455
- stats[f'Community {i+1} Density'] = nx.density(subgraph)
456
- stats[f'Community {i+1} Conductance'] = nx.conductance(G, com)
457
- stats[f'Community {i+1} Avg Clustering'] = nx.average_clustering(subgraph)
458
-
459
- # Degree centrality
460
- degree_cent = nx.degree_centrality(subgraph)
461
- stats[f'Community {i+1} Avg Degree Centrality'] = np.mean(list(degree_cent.values()))
462
-
463
- # Average path length (only for connected subgraphs)
464
- if nx.is_connected(subgraph):
465
- stats[f'Community {i+1} Avg Path Length'] = nx.average_shortest_path_length(subgraph)
466
- except:
467
- pass
468
-
469
- try:
449
+ #try:
470
450
  # Add some Louvain-specific statistics
471
- stats['Partition Resolution'] = 1.0 # Default resolution parameter
472
- except:
473
- pass
451
+ #stats['Partition Resolution'] = 1.0 # Default resolution parameter
452
+ #except:
453
+ #pass
474
454
  try:
475
455
  stats['Number of Iterations'] = len(set(partition.values()))
476
456
  except:
@@ -514,6 +494,25 @@ def community_partition(master_list, weighted = False, style = 0, dostats = True
514
494
  except:
515
495
  pass
516
496
 
497
+ try:
498
+ # Per-community statistics
499
+ for i, com in enumerate(communities):
500
+ subgraph = G.subgraph(com)
501
+
502
+ # Basic community metrics
503
+ stats[f'Community {i+1} Density'] = nx.density(subgraph)
504
+ stats[f'Community {i+1} Conductance'] = nx.conductance(G, com)
505
+ stats[f'Community {i+1} Avg Clustering'] = nx.average_clustering(subgraph)
506
+
507
+ # Degree centrality
508
+ degree_cent = nx.degree_centrality(subgraph)
509
+ stats[f'Community {i+1} Avg Degree Centrality'] = np.mean(list(degree_cent.values()))
510
+
511
+ # Average path length (only for connected subgraphs)
512
+ if nx.is_connected(subgraph):
513
+ stats[f'Community {i+1} Avg Path Length'] = nx.average_shortest_path_length(subgraph)
514
+ except:
515
+ pass
517
516
 
518
517
  return stats
519
518
 
@@ -354,6 +354,7 @@ def process_object_cpu(label, objects, labeled_array, xy_scale = 1, z_scale = 1)
354
354
  mask = (subarray == label)
355
355
 
356
356
 
357
+ """
357
358
  # Determine which dimension needs resampling
358
359
  if (z_scale > xy_scale) and mask.shape[0] != 1:
359
360
  # Z dimension needs to be stretched
@@ -371,13 +372,13 @@ def process_object_cpu(label, objects, labeled_array, xy_scale = 1, z_scale = 1)
371
372
  # Resample the mask if needed
372
373
  if zoom_factor:
373
374
  mask = ndimage.zoom(mask, zoom_factor, order=0) # Use order=0 for binary masks
374
-
375
+ """
375
376
 
376
377
  # Compute distance transform on the smaller mask
377
- dist_transform = compute_distance_transform_distance(mask)
378
+ dist_transform = compute_distance_transform_distance(mask, sampling = [z_scale, xy_scale, xy_scale])
378
379
 
379
380
  # Filter out small values near the edge to focus on more central regions
380
- radius = np.max(dist_transform) * cardinal
381
+ radius = np.max(dist_transform)
381
382
 
382
383
  return label, radius
383
384
 
@@ -474,6 +475,7 @@ def estimate_object_radii_gpu(labeled_array, xy_scale = 1, z_scale = 1):
474
475
  # Create binary mask for this object (directly on GPU)
475
476
  mask_gpu = (labeled_array_gpu[tuple(padded_slices)] == label)
476
477
 
478
+ """
477
479
  # Determine which dimension needs resampling
478
480
  if (z_scale > xy_scale) and mask_gpu.shape[0] != 1:
479
481
  # Z dimension needs to be stretched
@@ -491,11 +493,12 @@ def estimate_object_radii_gpu(labeled_array, xy_scale = 1, z_scale = 1):
491
493
  # Resample the mask if needed
492
494
  if zoom_factor:
493
495
  mask_gpu = cpx.zoom(mask_gpu, zoom_factor, order=0) # Use order=0 for binary masks
496
+ """
494
497
 
495
498
  # Compute distance transform on GPU
496
- dist_transform_gpu = compute_distance_transform_distance_GPU(mask_gpu)
499
+ dist_transform_gpu = compute_distance_transform_distance_GPU(mask_gpu, sampling = [z_scale, xy_scale, xy_scale])
497
500
 
498
- radius = float(cp.max(dist_transform_gpu).get()) * cardinal
501
+ radius = float(cp.max(dist_transform_gpu).get())
499
502
 
500
503
 
501
504
  # Store the radius and the scaled radius
@@ -510,14 +513,15 @@ def estimate_object_radii_gpu(labeled_array, xy_scale = 1, z_scale = 1):
510
513
  print(f"GPU calculation failed, trying CPU instead -> {e}")
511
514
  return estimate_object_radii_cpu(labeled_array)
512
515
 
513
- def compute_distance_transform_distance_GPU(nodes):
516
+ def compute_distance_transform_distance_GPU(nodes, sampling = [1,1,1]):
514
517
 
515
518
  is_pseudo_3d = nodes.shape[0] == 1
516
519
  if is_pseudo_3d:
517
520
  nodes = cp.squeeze(nodes) # Convert to 2D for processing
521
+ del sampling[0]
518
522
 
519
523
  # Compute the distance transform on the GPU
520
- distance = cpx.distance_transform_edt(nodes)
524
+ distance = cpx.distance_transform_edt(nodes, sampling = sampling)
521
525
 
522
526
  if is_pseudo_3d:
523
527
  cp.expand_dims(distance, axis = 0)
@@ -525,14 +529,15 @@ def compute_distance_transform_distance_GPU(nodes):
525
529
  return distance
526
530
 
527
531
 
528
- def compute_distance_transform_distance(nodes):
532
+ def compute_distance_transform_distance(nodes, sampling = [1,1,1]):
529
533
 
530
534
  is_pseudo_3d = nodes.shape[0] == 1
531
535
  if is_pseudo_3d:
532
536
  nodes = np.squeeze(nodes) # Convert to 2D for processing
537
+ del sampling[0]
533
538
 
534
539
  # Fallback to CPU if there's an issue with GPU computation
535
- distance = ndimage.distance_transform_edt(nodes)
540
+ distance = ndimage.distance_transform_edt(nodes, sampling = sampling)
536
541
  if is_pseudo_3d:
537
542
  np.expand_dims(distance, axis = 0)
538
543
  return distance