nettracer3d 1.2.3__py3-none-any.whl → 1.2.4__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.

Potentially problematic release.


This version of nettracer3d might be problematic. Click here for more details.

nettracer3d/filaments.py CHANGED
@@ -93,16 +93,24 @@ class VesselDenoiser:
93
93
  # A voxel contributes to surface area if any neighbor is different
94
94
  for axis in range(3):
95
95
  for direction in [-1, 1]:
96
- # Shift array to compare with neighbors
97
- shifted = np.roll(labeled, direction, axis=axis)
96
+ # Pad with zeros only on the axis we're checking
97
+ pad_width = [(1, 1) if i == axis else (0, 0) for i in range(3)]
98
+ padded = np.pad(labeled, pad_width, mode='constant', constant_values=0)
98
99
 
99
- # Find faces exposed to different label (including background)
100
- exposed_faces = (labeled != shifted) & (labeled > 0)
100
+ # Roll the padded array
101
+ shifted = np.roll(padded, direction, axis=axis)
102
+
103
+ # Extract the center region (original size) from shifted
104
+ slices = [slice(1, -1) if i == axis else slice(None) for i in range(3)]
105
+ shifted_cropped = shifted[tuple(slices)]
106
+
107
+ # Find exposed faces
108
+ exposed_faces = (labeled != shifted_cropped) & (labeled > 0)
101
109
 
102
- # Count exposed faces per label
103
110
  face_counts = np.bincount(labeled[exposed_faces],
104
111
  minlength=num_features + 1)
105
112
  surface_areas += face_counts
113
+ del padded
106
114
 
107
115
  # Calculate sphericity for each component
108
116
  # Sphericity = (surface area of sphere with same volume) / (actual surface area)
nettracer3d/nettracer.py CHANGED
@@ -750,35 +750,37 @@ def estimate_object_radii(labeled_array, gpu=False, n_jobs=None, xy_scale = 1, z
750
750
 
751
751
  def get_surface_areas(labeled, xy_scale=1, z_scale=1):
752
752
  labels = np.unique(labeled)
753
- labels = labels[labels > 0] # Remove background label
753
+ labels = labels[labels > 0]
754
754
  max_label = int(np.max(labeled))
755
755
 
756
- # Size array to accommodate highest label value
757
756
  surface_areas = np.zeros(max_label + 1, dtype=np.float64)
758
757
 
759
- # Check each of 6 face directions (±x, ±y, ±z)
760
758
  for axis in range(3):
761
- # Determine face area based on axis (anisotropic scaling)
762
- if axis == 2: # z-axis: face is in xy plane
759
+ if axis == 2:
763
760
  face_area = xy_scale * xy_scale
764
- else: # x or y axis: face is perpendicular to xy plane
761
+ else:
765
762
  face_area = xy_scale * z_scale
766
763
 
767
764
  for direction in [-1, 1]:
768
- # Shift array to compare with neighbors
769
- shifted = np.roll(labeled, direction, axis=axis)
765
+ # Pad with zeros only on the axis we're checking
766
+ pad_width = [(1, 1) if i == axis else (0, 0) for i in range(3)]
767
+ padded = np.pad(labeled, pad_width, mode='constant', constant_values=0)
768
+
769
+ # Roll the padded array
770
+ shifted = np.roll(padded, direction, axis=axis)
770
771
 
771
- # Find faces exposed to different label (including background)
772
- exposed_faces = (labeled != shifted) & (labeled > 0)
772
+ # Extract the center region (original size) from shifted
773
+ slices = [slice(1, -1) if i == axis else slice(None) for i in range(3)]
774
+ shifted_cropped = shifted[tuple(slices)]
775
+
776
+ # Find exposed faces
777
+ exposed_faces = (labeled != shifted_cropped) & (labeled > 0)
773
778
 
774
- # Count exposed faces per label
775
779
  face_counts = np.bincount(labeled[exposed_faces],
776
780
  minlength=max_label + 1)
777
781
  surface_areas += face_counts * face_area
778
782
 
779
- # Create dictionary mapping label to surface area
780
783
  result = {int(label): float(surface_areas[label]) for label in labels}
781
-
782
784
  return result
783
785
 
784
786
  def break_and_label_skeleton(skeleton, peaks = 1, branch_removal = 0, comp_dil = 0, max_vol = 0, directory = None, return_skele = False, nodes = None, compute = True, unify = False, xy_scale = 1, z_scale = 1):
@@ -5560,14 +5562,14 @@ class Network_3D:
5560
5562
  except:
5561
5563
  pass
5562
5564
 
5563
- title1 = f'Neighborhood Distribution of Nodes in Network from Nodes: {root}'
5564
- title2 = f'Neighborhood Distribution of Nodes in Network from Nodes {root} as a proportion of total nodes of that ID'
5565
+ title1 = f'Neighborhood Distribution of Nodes in Network from Node Type: {root}'
5566
+ title2 = f'Neighborhood Distribution of Nodes in Network from Node Type {root} as a Proportion (# neighbors with ID x / Total # ID x)'
5565
5567
 
5566
5568
 
5567
5569
  elif mode == 1: #Search neighborhoods morphologically, obtain densities
5568
5570
  neighborhood_dict, total_dict, densities = morphology.search_neighbor_ids(self._nodes, targets, node_identities, neighborhood_dict, total_dict, search, self._xy_scale, self._z_scale, root, fastdil = fastdil)
5569
- title1 = f'Volumetric Neighborhood Distribution of Nodes in image that are {search} from nodes: {root}'
5570
- title2 = f'Density Distribution of Nodes in image that are {search} from Nodes {root} as a proportion of total node volume of that ID'
5571
+ title1 = f'Volumetric Neighborhood Distribution of Nodes in image that are {search} from Node Type: {root}'
5572
+ title2 = f'Density Distribution of Nodes in image that are {search} from Node Type {root} as a proportion (Vol neighors with ID x / Total vol ID x)'
5571
5573
 
5572
5574
 
5573
5575
  for identity in neighborhood_dict:
@@ -5578,7 +5580,7 @@ class Network_3D:
5578
5580
  network_analysis.create_bar_graph(proportion_dict, title2, "Node Identity", "Proportion", directory=directory)
5579
5581
 
5580
5582
  try:
5581
- network_analysis.create_bar_graph(densities, f'Relative Density of Node Identities with {search} from nodes {root}', "Node Identity", "Density Search/Density Total", directory=directory)
5583
+ network_analysis.create_bar_graph(densities, f'Relative Density of Node Identities with {search} from Node Type {root}', "Node Identity", "Density within search region/Density within entire image", directory=directory)
5582
5584
  except:
5583
5585
  densities = None
5584
5586
 
@@ -6233,14 +6235,14 @@ class Network_3D:
6233
6235
  if proportional:
6234
6236
 
6235
6237
  identities2, id_set2 = self.community_id_info_per_com(proportional = True)
6236
- output = neighborhoods.plot_dict_heatmap(identities2, id_set2, title = "Neighborhood Heatmap by Proportional Composition of Nodes in Neighborhood vs All Nodes")
6238
+ output = neighborhoods.plot_dict_heatmap(identities2, id_set2, title = "Neighborhood Heatmap by Proportional Composition of Nodes in Neighborhood vs All Nodes in Image")
6237
6239
  matrixes.append(output)
6238
6240
 
6239
6241
  identities3 = {}
6240
6242
  for iden in identities2:
6241
6243
  identities3[iden] = identities2[iden]/len_dict[iden][1]
6242
6244
 
6243
- output = neighborhoods.plot_dict_heatmap(identities3, id_set2, title = "Neighborhood Heatmap by Proportional Composition of Nodes in Neighborhood vs All Nodes Divided by Neighborhood Total Proportion of All Nodes (val < 1 = underrepresented, val > 1 = overrepresented)", center_at_one = True)
6245
+ output = neighborhoods.plot_dict_heatmap(identities3, id_set2, title = "Over/Underrepresentation of Node Identities per Neighborhood (val < 1 = underrepresented, val > 1 = overrepresented)", center_at_one = True)
6244
6246
  matrixes.append(output)
6245
6247
 
6246
6248
  return len_dict, matrixes, id_set
@@ -10090,7 +10090,7 @@ class NeighborIdentityDialog(QDialog):
10090
10090
  self.root = None
10091
10091
 
10092
10092
  self.mode = QComboBox()
10093
- self.mode.addItems(["From Network - Based on Absolute Connectivity", "Use Labeled Nodes - Based on Morphological Neighborhood Densities"])
10093
+ self.mode.addItems(["From Network - Quantifies Neighbors Based on Adjacent Network Connections", "Use Labeled Nodes - Quantifies Neighbors Volume of Neighbor Within Search Region"])
10094
10094
  self.mode.setCurrentIndex(0)
10095
10095
  layout.addRow("Mode", self.mode)
10096
10096
 
@@ -1,10 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nettracer3d
3
- Version: 1.2.3
3
+ Version: 1.2.4
4
4
  Summary: Scripts for intializing and analyzing networks from segmentations of three dimensional images.
5
5
  Author-email: Liam McLaughlin <liamm@wustl.edu>
6
6
  Project-URL: Documentation, https://nettracer3d.readthedocs.io/en/latest/
7
- Project-URL: Video_Tutorial, https://www.youtube.com/watch?v=cRatn5VTWDY
8
7
  Project-URL: Reference_Citation_For_Use, https://doi.org/10.1101/2024.07.29.605633
9
8
  Classifier: Programming Language :: Python :: 3
10
9
  Classifier: License :: Other/Proprietary License
@@ -101,8 +100,6 @@ While not related to NetTracer3D, if you want to use Cellpose3 (for which GPU-us
101
100
  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.
102
101
 
103
102
 
104
- For a (slightly outdated) video tutorial on using the GUI: https://www.youtube.com/watch?v=cRatn5VTWDY
105
-
106
103
  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).
107
104
  The current citation is here:
108
105
 
@@ -110,8 +107,9 @@ McLaughlin, L., Zhang, B., Sharma, S. et al. Three dimensional multiscalar neuro
110
107
 
111
108
  NetTracer3D was developed by Liam McLaughlin while working under Dr. Sanjay Jain at Washington University School of Medicine.
112
109
 
113
- -- Version 1.2.3 Updates --
110
+ -- Version 1.2.4 Updates --
114
111
 
115
- * Tweaked the 'branch unification params' - now hard rejects any sharp forks in the branches so branches will mostly be straight.
112
+ * Fixed bug for calculating surface area when the surface was on the edge of the image.
113
+ * Removed video tutorial from youtube for being outdated. May add new one later.
116
114
 
117
115
 
@@ -3,12 +3,12 @@ nettracer3d/branch_stitcher.py,sha256=gyDVPUnApS2jmlIglJoRVEVY8WXLqwpr0_8rNdvy9u
3
3
  nettracer3d/cellpose_manager.py,sha256=NfRqW6Zl7yRU4qHCS_KjmR0R6QANSSgCO0_dr-eivxg,6694
4
4
  nettracer3d/community_extractor.py,sha256=rPXXWwMX05mfD_ogULEouLy8CST-aOaoSw45NhloKVg,31754
5
5
  nettracer3d/excelotron.py,sha256=aNof6k-DgMxVyFgsl3ltSCxG4vZW49cuvCBzfzhYhUY,75072
6
- nettracer3d/filaments.py,sha256=-gUoiXg4n5qTHhGvzh1gkLeDjStECRGbaGpau_NGVRM,43280
6
+ nettracer3d/filaments.py,sha256=ks3-ThdHRKu5hPk04R_YHAmVpwCqXraR0LWW0VRlAts,43693
7
7
  nettracer3d/modularity.py,sha256=pborVcDBvICB2-g8lNoSVZbIReIBlfeBmjFbPYmtq7Y,22443
8
8
  nettracer3d/morphology.py,sha256=QlBPsJAswBoinjZuouNwEfGEGwclvenlZ1Vmo288QLo,23287
9
9
  nettracer3d/neighborhoods.py,sha256=Bje77gWzXRIYyXkDlnFQnbUALnIt8dheLXHVFQsAKuc,53156
10
- nettracer3d/nettracer.py,sha256=JaoNXP67vLzaw6HUQ6mtB7qye1U92wZDJYI3vEpsDS4,294237
11
- nettracer3d/nettracer_gui.py,sha256=AKXT_4M-wuuijPzj6XfMV6fYKQ0WJYW0A_YdcO7kfYc,741978
10
+ nettracer3d/nettracer.py,sha256=9iQ51fvYUNsHA90lZd4cEVz_4AZZToTy22SjJoZNPHY,294254
11
+ nettracer3d/nettracer_gui.py,sha256=oStQZCqzi_nDFq8NKjMA1n0cuMv77gKekOd6XQFO5H4,742021
12
12
  nettracer3d/network_analysis.py,sha256=kBzsVaq4dZkMe0k-VGvQIUvM-tK0ZZ8bvb-wtsugZRQ,46150
13
13
  nettracer3d/network_draw.py,sha256=Uw0w1MoFiYMirkdM_XDAfy_m5_MoVaZkkGpoYzN9_-c,14259
14
14
  nettracer3d/node_draw.py,sha256=LeSftKJiNGkC7cpBJuf8Y9JeTUaUjcD6I2byclmZCb4,10484
@@ -21,9 +21,9 @@ nettracer3d/simple_network.py,sha256=dkG4jpc4zzdeuoaQobgGfL3PNo6N8dGKQ5hEEubFIvA
21
21
  nettracer3d/smart_dilate.py,sha256=gtL7hxzae93PJQsGLnUrwQ6Wb0evnHHREh0rHyUh_48,28644
22
22
  nettracer3d/stats.py,sha256=0YwrVLeEvll3PlbL5-0_9dstldr48PvxJrQm-PiC8jY,36607
23
23
  nettracer3d/tutorial.py,sha256=cUxiBf5RaBTtr9uJ2qoxZjRkcAY8mrvS9_LEqiwoxLc,153564
24
- nettracer3d-1.2.3.dist-info/licenses/LICENSE,sha256=jnNT-yBeIAKAHpYthPvLeqCzJ6nSurgnKmloVnfsjCI,764
25
- nettracer3d-1.2.3.dist-info/METADATA,sha256=rVv3ho6njj9VWX6XrKz0ri1mHYBwo_zO8Mb7d7XHBaM,7110
26
- nettracer3d-1.2.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
- nettracer3d-1.2.3.dist-info/entry_points.txt,sha256=Nx1rr_0QhJXDBHAQg2vcqCzLMKBzSHfwy3xwGkueVyc,53
28
- nettracer3d-1.2.3.dist-info/top_level.txt,sha256=zsYy9rZwirfCEOubolhee4TyzqBAL5gSUeFMzhFTX8c,12
29
- nettracer3d-1.2.3.dist-info/RECORD,,
24
+ nettracer3d-1.2.4.dist-info/licenses/LICENSE,sha256=jnNT-yBeIAKAHpYthPvLeqCzJ6nSurgnKmloVnfsjCI,764
25
+ nettracer3d-1.2.4.dist-info/METADATA,sha256=snQxa9urY2-QGfYTHg0cpeUfNuCa2qhfRum9aMD1otk,6971
26
+ nettracer3d-1.2.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
+ nettracer3d-1.2.4.dist-info/entry_points.txt,sha256=Nx1rr_0QhJXDBHAQg2vcqCzLMKBzSHfwy3xwGkueVyc,53
28
+ nettracer3d-1.2.4.dist-info/top_level.txt,sha256=zsYy9rZwirfCEOubolhee4TyzqBAL5gSUeFMzhFTX8c,12
29
+ nettracer3d-1.2.4.dist-info/RECORD,,