nettracer3d 0.5.7__tar.gz → 0.5.9__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.
- {nettracer3d-0.5.7/src/nettracer3d.egg-info → nettracer3d-0.5.9}/PKG-INFO +3 -3
- {nettracer3d-0.5.7 → nettracer3d-0.5.9}/README.md +2 -2
- {nettracer3d-0.5.7 → nettracer3d-0.5.9}/pyproject.toml +1 -1
- {nettracer3d-0.5.7 → nettracer3d-0.5.9}/src/nettracer3d/nettracer_gui.py +8 -4
- {nettracer3d-0.5.7 → nettracer3d-0.5.9}/src/nettracer3d/segmenter.py +107 -54
- {nettracer3d-0.5.7 → nettracer3d-0.5.9/src/nettracer3d.egg-info}/PKG-INFO +3 -3
- {nettracer3d-0.5.7 → nettracer3d-0.5.9}/LICENSE +0 -0
- {nettracer3d-0.5.7 → nettracer3d-0.5.9}/setup.cfg +0 -0
- {nettracer3d-0.5.7 → nettracer3d-0.5.9}/src/nettracer3d/__init__.py +0 -0
- {nettracer3d-0.5.7 → nettracer3d-0.5.9}/src/nettracer3d/community_extractor.py +0 -0
- {nettracer3d-0.5.7 → nettracer3d-0.5.9}/src/nettracer3d/hub_getter.py +0 -0
- {nettracer3d-0.5.7 → nettracer3d-0.5.9}/src/nettracer3d/modularity.py +0 -0
- {nettracer3d-0.5.7 → nettracer3d-0.5.9}/src/nettracer3d/morphology.py +0 -0
- {nettracer3d-0.5.7 → nettracer3d-0.5.9}/src/nettracer3d/nettracer.py +0 -0
- {nettracer3d-0.5.7 → nettracer3d-0.5.9}/src/nettracer3d/network_analysis.py +0 -0
- {nettracer3d-0.5.7 → nettracer3d-0.5.9}/src/nettracer3d/network_draw.py +0 -0
- {nettracer3d-0.5.7 → nettracer3d-0.5.9}/src/nettracer3d/node_draw.py +0 -0
- {nettracer3d-0.5.7 → nettracer3d-0.5.9}/src/nettracer3d/proximity.py +0 -0
- {nettracer3d-0.5.7 → nettracer3d-0.5.9}/src/nettracer3d/run.py +0 -0
- {nettracer3d-0.5.7 → nettracer3d-0.5.9}/src/nettracer3d/simple_network.py +0 -0
- {nettracer3d-0.5.7 → nettracer3d-0.5.9}/src/nettracer3d/smart_dilate.py +0 -0
- {nettracer3d-0.5.7 → nettracer3d-0.5.9}/src/nettracer3d.egg-info/SOURCES.txt +0 -0
- {nettracer3d-0.5.7 → nettracer3d-0.5.9}/src/nettracer3d.egg-info/dependency_links.txt +0 -0
- {nettracer3d-0.5.7 → nettracer3d-0.5.9}/src/nettracer3d.egg-info/entry_points.txt +0 -0
- {nettracer3d-0.5.7 → nettracer3d-0.5.9}/src/nettracer3d.egg-info/requires.txt +0 -0
- {nettracer3d-0.5.7 → nettracer3d-0.5.9}/src/nettracer3d.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: nettracer3d
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.9
|
|
4
4
|
Summary: Scripts for intializing and analyzing networks from segmentations of three dimensional images.
|
|
5
5
|
Author-email: Liam McLaughlin <mclaughlinliam99@gmail.com>
|
|
6
6
|
Project-URL: User_Tutorial, https://www.youtube.com/watch?v=cRatn5VTWDY
|
|
@@ -44,6 +44,6 @@ NetTracer3D is free to use/fork for academic/nonprofit use so long as citation i
|
|
|
44
44
|
|
|
45
45
|
NetTracer3D was developed by Liam McLaughlin while working under Dr. Sanjay Jain at Washington University School of Medicine.
|
|
46
46
|
|
|
47
|
-
-- Version 0.5.
|
|
47
|
+
-- Version 0.5.9 updates --
|
|
48
48
|
|
|
49
|
-
1.
|
|
49
|
+
1. Bug fixes
|
|
@@ -8,6 +8,6 @@ NetTracer3D is free to use/fork for academic/nonprofit use so long as citation i
|
|
|
8
8
|
|
|
9
9
|
NetTracer3D was developed by Liam McLaughlin while working under Dr. Sanjay Jain at Washington University School of Medicine.
|
|
10
10
|
|
|
11
|
-
-- Version 0.5.
|
|
11
|
+
-- Version 0.5.9 updates --
|
|
12
12
|
|
|
13
|
-
1.
|
|
13
|
+
1. Bug fixes
|
|
@@ -6546,9 +6546,10 @@ class MachineWindow(QMainWindow):
|
|
|
6546
6546
|
# Reset any processing flags in the segmenter
|
|
6547
6547
|
if hasattr(self.segmenter, '_currently_processing'):
|
|
6548
6548
|
self.segmenter._currently_processing = None
|
|
6549
|
-
|
|
6550
|
-
|
|
6551
|
-
|
|
6549
|
+
|
|
6550
|
+
if 0 in self.parent().highlight_overlay[current_z, :, :]:
|
|
6551
|
+
# Create a new worker after a brief delay
|
|
6552
|
+
QTimer.singleShot(500, self.start_segmentation)
|
|
6552
6553
|
|
|
6553
6554
|
|
|
6554
6555
|
|
|
@@ -6665,7 +6666,7 @@ class SegmentationWorker(QThread):
|
|
|
6665
6666
|
self._stop = True
|
|
6666
6667
|
|
|
6667
6668
|
def get_poked(self):
|
|
6668
|
-
self.
|
|
6669
|
+
self.machine_window.poke_segmenter()
|
|
6669
6670
|
|
|
6670
6671
|
def run(self):
|
|
6671
6672
|
try:
|
|
@@ -6680,6 +6681,9 @@ class SegmentationWorker(QThread):
|
|
|
6680
6681
|
|
|
6681
6682
|
# Process the slice with chunked generator
|
|
6682
6683
|
for foreground, background in self.segmenter.segment_slice_chunked(current_z):
|
|
6684
|
+
if foreground == None and background == None:
|
|
6685
|
+
self.get_poked()
|
|
6686
|
+
|
|
6683
6687
|
if self._stop:
|
|
6684
6688
|
break
|
|
6685
6689
|
|
|
@@ -18,6 +18,7 @@ from concurrent.futures import ThreadPoolExecutor
|
|
|
18
18
|
import threading
|
|
19
19
|
from scipy import ndimage
|
|
20
20
|
import multiprocessing
|
|
21
|
+
from collections import defaultdict
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
class InteractiveSegmenter:
|
|
@@ -98,24 +99,41 @@ class InteractiveSegmenter:
|
|
|
98
99
|
# First attempt to get the feature map
|
|
99
100
|
feature_map = None
|
|
100
101
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
102
|
+
try:
|
|
103
|
+
if slice_z in self.feature_cache:
|
|
104
|
+
feature_map = self.feature_cache[slice_z]
|
|
105
|
+
elif hasattr(self, 'map_slice') and self.map_slice is not None and slice_z == self.current_z:
|
|
106
|
+
feature_map = self.map_slice
|
|
107
|
+
else:
|
|
108
|
+
# Generate new feature map
|
|
109
|
+
try:
|
|
110
|
+
feature_map = self.get_feature_map_slice(slice_z, self.current_speed, False)
|
|
111
|
+
self.map_slice = feature_map
|
|
112
|
+
# Cache the feature map for future use
|
|
113
|
+
#if not hasattr(self, 'feature_cache'):
|
|
114
|
+
#self.feature_cache = {}
|
|
115
|
+
#self.feature_cache[slice_z] = feature_map
|
|
116
|
+
except Exception as e:
|
|
117
|
+
print(f"Error generating feature map: {e}")
|
|
118
|
+
import traceback
|
|
119
|
+
traceback.print_exc()
|
|
120
|
+
return # Exit if we can't generate the feature map
|
|
121
|
+
except:
|
|
106
122
|
# Generate new feature map
|
|
123
|
+
#self.feature_cache = {}
|
|
107
124
|
try:
|
|
108
125
|
feature_map = self.get_feature_map_slice(slice_z, self.current_speed, False)
|
|
109
126
|
self.map_slice = feature_map
|
|
110
127
|
# Cache the feature map for future use
|
|
111
|
-
if not hasattr(self, 'feature_cache'):
|
|
112
|
-
self.feature_cache = {}
|
|
113
|
-
self.feature_cache[slice_z] = feature_map
|
|
128
|
+
#if not hasattr(self, 'feature_cache'):
|
|
129
|
+
#self.feature_cache = {}
|
|
130
|
+
#self.feature_cache[slice_z] = feature_map
|
|
114
131
|
except Exception as e:
|
|
115
132
|
print(f"Error generating feature map: {e}")
|
|
116
133
|
import traceback
|
|
117
134
|
traceback.print_exc()
|
|
118
135
|
return # Exit if we can't generate the feature map
|
|
136
|
+
|
|
119
137
|
|
|
120
138
|
# Check that we have a valid feature map
|
|
121
139
|
if feature_map is None:
|
|
@@ -152,7 +170,12 @@ class InteractiveSegmenter:
|
|
|
152
170
|
|
|
153
171
|
# Predict
|
|
154
172
|
try:
|
|
155
|
-
|
|
173
|
+
try:
|
|
174
|
+
predictions = self.model.predict(features)
|
|
175
|
+
except ValueError:
|
|
176
|
+
self.feature_cache = None
|
|
177
|
+
self.map_slice = None
|
|
178
|
+
return None, None
|
|
156
179
|
|
|
157
180
|
# Split results
|
|
158
181
|
foreground = set()
|
|
@@ -692,18 +715,12 @@ class InteractiveSegmenter:
|
|
|
692
715
|
Returns:
|
|
693
716
|
Dictionary with z-values as keys and lists of corresponding [y, x] coordinates as values
|
|
694
717
|
"""
|
|
695
|
-
z_dict =
|
|
718
|
+
z_dict = defaultdict(list)
|
|
696
719
|
|
|
697
|
-
for
|
|
698
|
-
z
|
|
699
|
-
|
|
700
|
-
# Add the y, x coordinate to the appropriate z-value group
|
|
701
|
-
if z not in z_dict:
|
|
702
|
-
z_dict[z] = []
|
|
703
|
-
|
|
704
|
-
z_dict[z].append((y, x)) # Store as tuple, not list, so it's hashable
|
|
720
|
+
for z, y, x in coordinates:
|
|
721
|
+
z_dict[z].append((y, x))
|
|
705
722
|
|
|
706
|
-
return z_dict
|
|
723
|
+
return dict(z_dict) # Convert back to regular dict
|
|
707
724
|
|
|
708
725
|
def process_chunk(self, chunk_coords):
|
|
709
726
|
"""Process a chunk of coordinates"""
|
|
@@ -727,10 +744,13 @@ class InteractiveSegmenter:
|
|
|
727
744
|
chunk_by_z = self.organize_by_z(chunk_coords)
|
|
728
745
|
for z, coords in chunk_by_z.items():
|
|
729
746
|
|
|
730
|
-
if
|
|
747
|
+
if self.feature_cache is None:
|
|
748
|
+
features = self.get_feature_map_slice(z, self.speed, self.cur_gpu)
|
|
749
|
+
features = [features[y, x] for y, x in coords]
|
|
750
|
+
elif z not in self.feature_cache and not self.previewing:
|
|
731
751
|
features = self.get_feature_map_slice(z, self.speed, self.cur_gpu)
|
|
732
752
|
features = [features[y, x] for y, x in coords]
|
|
733
|
-
elif z not in self.feature_cache and self.previewing:
|
|
753
|
+
elif z not in self.feature_cache or self.feature_cache is None and self.previewing:
|
|
734
754
|
features = self.map_slice
|
|
735
755
|
try:
|
|
736
756
|
features = [features[y, x] for y, x in coords]
|
|
@@ -850,6 +870,7 @@ class InteractiveSegmenter:
|
|
|
850
870
|
chunks.append(list(map(tuple, coords)))
|
|
851
871
|
else:
|
|
852
872
|
chunks = create_2d_chunks()
|
|
873
|
+
self.feature_cache = None #Decided this should not maintain training data for segmenting 2D
|
|
853
874
|
|
|
854
875
|
foreground_coords = set()
|
|
855
876
|
background_coords = set()
|
|
@@ -904,8 +925,9 @@ class InteractiveSegmenter:
|
|
|
904
925
|
# Only clear map_slice if z changes and we're not already generating a new one
|
|
905
926
|
if self.current_z != self.prev_z:
|
|
906
927
|
# Instead of setting to None, check if we already have it in the cache
|
|
907
|
-
if hasattr(self, 'feature_cache') and self.
|
|
908
|
-
self.
|
|
928
|
+
if hasattr(self, 'feature_cache') and self.feature_cache is not None:
|
|
929
|
+
if self.current_z not in self.feature_cache:
|
|
930
|
+
self.map_slice = None
|
|
909
931
|
self._currently_segmenting = None
|
|
910
932
|
|
|
911
933
|
# Update previous z
|
|
@@ -1077,8 +1099,11 @@ class InteractiveSegmenter:
|
|
|
1077
1099
|
def cleanup(self):
|
|
1078
1100
|
"""Clean up GPU memory"""
|
|
1079
1101
|
if self.use_gpu:
|
|
1080
|
-
|
|
1081
|
-
|
|
1102
|
+
try:
|
|
1103
|
+
cp.get_default_memory_pool().free_all_blocks()
|
|
1104
|
+
torch.cuda.empty_cache()
|
|
1105
|
+
except:
|
|
1106
|
+
pass
|
|
1082
1107
|
|
|
1083
1108
|
def train_batch(self, foreground_array, speed = True, use_gpu = False, use_two = False):
|
|
1084
1109
|
"""Train directly on foreground and background arrays"""
|
|
@@ -1088,60 +1113,88 @@ class InteractiveSegmenter:
|
|
|
1088
1113
|
|
|
1089
1114
|
if self.current_speed != speed:
|
|
1090
1115
|
self.feature_cache = None
|
|
1116
|
+
if use_gpu:
|
|
1117
|
+
try:
|
|
1118
|
+
self.model = cuRandomForestClassifier(
|
|
1119
|
+
n_estimators=100,
|
|
1120
|
+
max_depth=None
|
|
1121
|
+
)
|
|
1122
|
+
except:
|
|
1123
|
+
self.model = RandomForestClassifier(
|
|
1124
|
+
n_estimators=100,
|
|
1125
|
+
n_jobs=-1,
|
|
1126
|
+
max_depth=None
|
|
1127
|
+
)
|
|
1128
|
+
else:
|
|
1129
|
+
self.model = RandomForestClassifier(
|
|
1130
|
+
n_estimators=100,
|
|
1131
|
+
n_jobs=-1,
|
|
1132
|
+
max_depth=None
|
|
1133
|
+
)
|
|
1134
|
+
|
|
1091
1135
|
|
|
1092
1136
|
if use_two:
|
|
1093
1137
|
|
|
1094
|
-
changed = [] #Track which slices need feature maps
|
|
1138
|
+
#changed = [] #Track which slices need feature maps
|
|
1095
1139
|
|
|
1096
1140
|
if not self.use_two: #Clarifies if we need to redo feature cache for 2D
|
|
1097
1141
|
self.feature_cache = None
|
|
1098
1142
|
self.use_two = True
|
|
1099
1143
|
|
|
1144
|
+
self.feature_cache = None #Decided this should reset, can remove this line to have it retain prev feature maps
|
|
1145
|
+
self.two_slices = []
|
|
1146
|
+
|
|
1100
1147
|
if self.feature_cache == None:
|
|
1101
1148
|
self.feature_cache = {}
|
|
1102
1149
|
|
|
1103
1150
|
# Get foreground coordinates and features
|
|
1104
1151
|
z_fore, y_fore, x_fore = np.where(foreground_array == 1)
|
|
1152
|
+
|
|
1153
|
+
|
|
1154
|
+
fore_coords = list(zip(z_fore, y_fore, x_fore))
|
|
1105
1155
|
|
|
1106
1156
|
# Get background coordinates and features
|
|
1107
1157
|
z_back, y_back, x_back = np.where(foreground_array == 2)
|
|
1108
1158
|
|
|
1109
|
-
|
|
1159
|
+
back_coords = list(zip(z_back, y_back, x_back))
|
|
1110
1160
|
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1161
|
+
|
|
1162
|
+
#slices = set(list(z_back) + list(z_fore))
|
|
1163
|
+
|
|
1164
|
+
#for z in slices:
|
|
1165
|
+
#if z not in self.two_slices:
|
|
1166
|
+
#changed.append(z)
|
|
1167
|
+
#self.two_slices.append(z) #Tracks assigning coords to feature map slices
|
|
1115
1168
|
|
|
1116
1169
|
foreground_features = []
|
|
1117
1170
|
background_features = []
|
|
1118
1171
|
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
self.feature_cache[z] = new_map
|
|
1123
|
-
changed.remove(z)
|
|
1124
|
-
|
|
1125
|
-
current_map = self.feature_cache[z]
|
|
1126
|
-
|
|
1127
|
-
# Get the feature vector for this foreground point
|
|
1128
|
-
feature_vector = current_map[y_fore[i], x_fore[i]]
|
|
1129
|
-
|
|
1130
|
-
# Add to our collection
|
|
1131
|
-
foreground_features.append(feature_vector)
|
|
1172
|
+
z_fores = self.organize_by_z(fore_coords)
|
|
1173
|
+
z_backs = self.organize_by_z(back_coords)
|
|
1174
|
+
slices = set(list(z_fores.keys()) + list(z_backs.keys()))
|
|
1132
1175
|
|
|
1133
|
-
for
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1176
|
+
for z in slices:
|
|
1177
|
+
|
|
1178
|
+
|
|
1179
|
+
current_map = self.get_feature_map_slice(z, speed, use_gpu)
|
|
1180
|
+
|
|
1181
|
+
if z in z_fores:
|
|
1139
1182
|
|
|
1140
|
-
|
|
1141
|
-
|
|
1183
|
+
for y, x in z_fores[z]:
|
|
1184
|
+
# Get the feature vector for this foreground point
|
|
1185
|
+
feature_vector = current_map[y, x]
|
|
1186
|
+
|
|
1187
|
+
# Add to our collection
|
|
1188
|
+
foreground_features.append(feature_vector)
|
|
1189
|
+
|
|
1190
|
+
if z in z_backs:
|
|
1142
1191
|
|
|
1143
|
-
|
|
1144
|
-
|
|
1192
|
+
for y, x in z_backs[z]:
|
|
1193
|
+
# Get the feature vector for this foreground point
|
|
1194
|
+
feature_vector = current_map[y, x]
|
|
1195
|
+
|
|
1196
|
+
# Add to our collection
|
|
1197
|
+
background_features.append(feature_vector)
|
|
1145
1198
|
|
|
1146
1199
|
|
|
1147
1200
|
else:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: nettracer3d
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.9
|
|
4
4
|
Summary: Scripts for intializing and analyzing networks from segmentations of three dimensional images.
|
|
5
5
|
Author-email: Liam McLaughlin <mclaughlinliam99@gmail.com>
|
|
6
6
|
Project-URL: User_Tutorial, https://www.youtube.com/watch?v=cRatn5VTWDY
|
|
@@ -44,6 +44,6 @@ NetTracer3D is free to use/fork for academic/nonprofit use so long as citation i
|
|
|
44
44
|
|
|
45
45
|
NetTracer3D was developed by Liam McLaughlin while working under Dr. Sanjay Jain at Washington University School of Medicine.
|
|
46
46
|
|
|
47
|
-
-- Version 0.5.
|
|
47
|
+
-- Version 0.5.9 updates --
|
|
48
48
|
|
|
49
|
-
1.
|
|
49
|
+
1. Bug fixes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|