nettracer3d 0.6.2__py3-none-any.whl → 0.6.3__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/nettracer_gui.py +190 -8
- nettracer3d/segmenter.py +5 -1
- {nettracer3d-0.6.2.dist-info → nettracer3d-0.6.3.dist-info}/METADATA +8 -5
- {nettracer3d-0.6.2.dist-info → nettracer3d-0.6.3.dist-info}/RECORD +8 -8
- {nettracer3d-0.6.2.dist-info → nettracer3d-0.6.3.dist-info}/WHEEL +1 -1
- {nettracer3d-0.6.2.dist-info → nettracer3d-0.6.3.dist-info}/entry_points.txt +0 -0
- {nettracer3d-0.6.2.dist-info → nettracer3d-0.6.3.dist-info/licenses}/LICENSE +0 -0
- {nettracer3d-0.6.2.dist-info → nettracer3d-0.6.3.dist-info}/top_level.txt +0 -0
nettracer3d/nettracer_gui.py
CHANGED
|
@@ -2429,10 +2429,14 @@ class ImageViewerWindow(QMainWindow):
|
|
|
2429
2429
|
binarize_action.triggered.connect(self.show_binarize_dialog)
|
|
2430
2430
|
label_action = image_menu.addAction("Label Objects")
|
|
2431
2431
|
label_action.triggered.connect(self.show_label_dialog)
|
|
2432
|
+
slabel_action = image_menu.addAction("Neighborhood Labels")
|
|
2433
|
+
slabel_action.triggered.connect(self.show_slabel_dialog)
|
|
2432
2434
|
thresh_action = image_menu.addAction("Threshold/Segment")
|
|
2433
2435
|
thresh_action.triggered.connect(self.show_thresh_dialog)
|
|
2434
2436
|
mask_action = image_menu.addAction("Mask Channel")
|
|
2435
2437
|
mask_action.triggered.connect(self.show_mask_dialog)
|
|
2438
|
+
type_action = image_menu.addAction("Channel dtype")
|
|
2439
|
+
type_action.triggered.connect(self.show_type_dialog)
|
|
2436
2440
|
skeletonize_action = image_menu.addAction("Skeletonize")
|
|
2437
2441
|
skeletonize_action.triggered.connect(self.show_skeletonize_dialog)
|
|
2438
2442
|
watershed_action = image_menu.addAction("Watershed")
|
|
@@ -2657,6 +2661,11 @@ class ImageViewerWindow(QMainWindow):
|
|
|
2657
2661
|
dialog = LabelDialog(self)
|
|
2658
2662
|
dialog.exec()
|
|
2659
2663
|
|
|
2664
|
+
def show_slabel_dialog(self):
|
|
2665
|
+
"""Show the slabel dialog"""
|
|
2666
|
+
dialog = SLabelDialog(self)
|
|
2667
|
+
dialog.exec()
|
|
2668
|
+
|
|
2660
2669
|
def show_thresh_dialog(self):
|
|
2661
2670
|
"""Show threshold dialog"""
|
|
2662
2671
|
if self.machine_window is not None:
|
|
@@ -2671,6 +2680,11 @@ class ImageViewerWindow(QMainWindow):
|
|
|
2671
2680
|
dialog = MaskDialog(self)
|
|
2672
2681
|
dialog.exec()
|
|
2673
2682
|
|
|
2683
|
+
def show_type_dialog(self):
|
|
2684
|
+
"""Show the type dialog"""
|
|
2685
|
+
dialog = TypeDialog(self)
|
|
2686
|
+
dialog.exec()
|
|
2687
|
+
|
|
2674
2688
|
def show_skeletonize_dialog(self):
|
|
2675
2689
|
"""show the skeletonize dialog"""
|
|
2676
2690
|
dialog = SkeletonizeDialog(self)
|
|
@@ -3066,6 +3080,7 @@ class ImageViewerWindow(QMainWindow):
|
|
|
3066
3080
|
def set_active_channel(self, index):
|
|
3067
3081
|
"""Set the active channel and update UI accordingly."""
|
|
3068
3082
|
self.active_channel = index
|
|
3083
|
+
self.active_channel_combo.setCurrentIndex(index)
|
|
3069
3084
|
# Update button appearances to show active channel
|
|
3070
3085
|
for i, btn in enumerate(self.channel_buttons):
|
|
3071
3086
|
if i == index and btn.isEnabled():
|
|
@@ -6261,6 +6276,91 @@ class LabelDialog(QDialog):
|
|
|
6261
6276
|
f"Error running label: {str(e)}"
|
|
6262
6277
|
)
|
|
6263
6278
|
|
|
6279
|
+
|
|
6280
|
+
class SLabelDialog(QDialog):
|
|
6281
|
+
def __init__(self, parent=None):
|
|
6282
|
+
super().__init__(parent)
|
|
6283
|
+
self.setWindowTitle("Smart Label (Use label array to assign label neighborhoods to binary array)?")
|
|
6284
|
+
self.setModal(True)
|
|
6285
|
+
|
|
6286
|
+
layout = QFormLayout(self)
|
|
6287
|
+
|
|
6288
|
+
|
|
6289
|
+
# Add mode selection dropdown
|
|
6290
|
+
self.mode_selector = QComboBox()
|
|
6291
|
+
self.mode_selector.addItems(["Nodes", "Edges", "Overlay 1", "Overlay 2"])
|
|
6292
|
+
self.mode_selector.setCurrentIndex(0) # Default to Mode 1
|
|
6293
|
+
layout.addRow("Prelabeled Array:", self.mode_selector)
|
|
6294
|
+
|
|
6295
|
+
layout.addRow(QLabel("Will Label Neighborhoods in: "))
|
|
6296
|
+
|
|
6297
|
+
# Add mode selection dropdown
|
|
6298
|
+
self.target_selector = QComboBox()
|
|
6299
|
+
self.target_selector.addItems(["Nodes", "Edges", "Overlay 1", "Overlay 2"])
|
|
6300
|
+
self.target_selector.setCurrentIndex(1) # Default to Mode 1
|
|
6301
|
+
layout.addRow("Binary Array:", self.target_selector)
|
|
6302
|
+
|
|
6303
|
+
# GPU checkbox (default True)
|
|
6304
|
+
self.GPU = QPushButton("GPU")
|
|
6305
|
+
self.GPU.setCheckable(True)
|
|
6306
|
+
self.GPU.setChecked(True)
|
|
6307
|
+
layout.addRow("Use GPU:", self.GPU)
|
|
6308
|
+
|
|
6309
|
+
self.down_factor = QLineEdit("")
|
|
6310
|
+
layout.addRow("Internal Downsample for GPU (if needed):", self.down_factor)
|
|
6311
|
+
|
|
6312
|
+
# Add Run button
|
|
6313
|
+
run_button = QPushButton("Run Smart Label")
|
|
6314
|
+
run_button.clicked.connect(self.run_slabel)
|
|
6315
|
+
layout.addRow(run_button)
|
|
6316
|
+
|
|
6317
|
+
def run_slabel(self):
|
|
6318
|
+
|
|
6319
|
+
try:
|
|
6320
|
+
|
|
6321
|
+
accepted_source = self.mode_selector.currentIndex()
|
|
6322
|
+
accepted_target = self.target_selector.currentIndex()
|
|
6323
|
+
GPU = self.GPU.isChecked()
|
|
6324
|
+
|
|
6325
|
+
|
|
6326
|
+
if accepted_source == accepted_target:
|
|
6327
|
+
return
|
|
6328
|
+
|
|
6329
|
+
binary_array = self.parent().channel_data[accepted_target]
|
|
6330
|
+
|
|
6331
|
+
label_array = self.parent().channel_data[accepted_source]
|
|
6332
|
+
|
|
6333
|
+
down_factor = float(self.down_factor.text()) if self.down_factor.text().strip() else None
|
|
6334
|
+
|
|
6335
|
+
|
|
6336
|
+
try:
|
|
6337
|
+
|
|
6338
|
+
# Update both the display data and the network object
|
|
6339
|
+
binary_array = sdl.smart_label(binary_array, label_array, directory = None, GPU = GPU, predownsample = down_factor)
|
|
6340
|
+
|
|
6341
|
+
label_array = sdl.invert_array(label_array)
|
|
6342
|
+
|
|
6343
|
+
binary_array = binary_array * label_array
|
|
6344
|
+
|
|
6345
|
+
self.parent().load_channel(accepted_target, binary_array, True)
|
|
6346
|
+
|
|
6347
|
+
self.accept()
|
|
6348
|
+
|
|
6349
|
+
except Exception as e:
|
|
6350
|
+
QMessageBox.critical(
|
|
6351
|
+
self,
|
|
6352
|
+
"Error",
|
|
6353
|
+
f"Error running smart label: {str(e)}"
|
|
6354
|
+
)
|
|
6355
|
+
|
|
6356
|
+
except Exception as e:
|
|
6357
|
+
QMessageBox.critical(
|
|
6358
|
+
self,
|
|
6359
|
+
"Error",
|
|
6360
|
+
f"Error running smart label: {str(e)}"
|
|
6361
|
+
)
|
|
6362
|
+
|
|
6363
|
+
|
|
6264
6364
|
class ThresholdDialog(QDialog):
|
|
6265
6365
|
def __init__(self, parent=None):
|
|
6266
6366
|
super().__init__(parent)
|
|
@@ -6380,9 +6480,8 @@ class MachineWindow(QMainWindow):
|
|
|
6380
6480
|
act_channel = 1
|
|
6381
6481
|
|
|
6382
6482
|
|
|
6383
|
-
array1 = np.zeros_like(active_data)
|
|
6384
|
-
|
|
6385
|
-
array3 = np.zeros_like(active_data)
|
|
6483
|
+
array1 = np.zeros_like(active_data).astype(np.uint8)
|
|
6484
|
+
array3 = np.zeros_like(active_data).astype(np.uint8)
|
|
6386
6485
|
self.parent().highlight_overlay = array3 #Clear this out for the segmenter to use
|
|
6387
6486
|
|
|
6388
6487
|
self.parent().load_channel(2, array1, True)
|
|
@@ -6460,7 +6559,7 @@ class MachineWindow(QMainWindow):
|
|
|
6460
6559
|
|
|
6461
6560
|
# Group 3: Training Options
|
|
6462
6561
|
training_group = QGroupBox("Training")
|
|
6463
|
-
training_layout =
|
|
6562
|
+
training_layout = QHBoxLayout()
|
|
6464
6563
|
train_quick = QPushButton("Train Quick Model")
|
|
6465
6564
|
train_quick.clicked.connect(lambda: self.train_model(speed=True))
|
|
6466
6565
|
train_detailed = QPushButton("Train More Detailed Model")
|
|
@@ -6471,11 +6570,13 @@ class MachineWindow(QMainWindow):
|
|
|
6471
6570
|
|
|
6472
6571
|
# Group 4: Segmentation Options
|
|
6473
6572
|
segmentation_group = QGroupBox("Segmentation")
|
|
6474
|
-
segmentation_layout =
|
|
6573
|
+
segmentation_layout = QHBoxLayout()
|
|
6475
6574
|
seg_button = QPushButton("Preview Segment")
|
|
6476
6575
|
self.seg_button = seg_button
|
|
6477
6576
|
seg_button.clicked.connect(self.start_segmentation)
|
|
6478
|
-
self.
|
|
6577
|
+
self.pause_button = QPushButton("▶/⏸️")
|
|
6578
|
+
self.pause_button.clicked.connect(self.pause)
|
|
6579
|
+
self.lock_button = QPushButton("🔒 Memory lock - (Prioritize RAM)")
|
|
6479
6580
|
self.lock_button.setCheckable(True)
|
|
6480
6581
|
self.lock_button.setChecked(True)
|
|
6481
6582
|
self.lock_button.clicked.connect(self.toggle_lock)
|
|
@@ -6483,6 +6584,7 @@ class MachineWindow(QMainWindow):
|
|
|
6483
6584
|
full_button = QPushButton("Segment All")
|
|
6484
6585
|
full_button.clicked.connect(self.segment)
|
|
6485
6586
|
segmentation_layout.addWidget(seg_button)
|
|
6587
|
+
#segmentation_layout.addWidget(self.pause_button) # <--- for some reason the segmenter preview is still running even when killed, may be regenerating itself somewhere. May or may not actually try to resolve this because this feature isnt that necessary.
|
|
6486
6588
|
segmentation_layout.addWidget(self.lock_button)
|
|
6487
6589
|
segmentation_layout.addWidget(full_button)
|
|
6488
6590
|
segmentation_group.setLayout(segmentation_layout)
|
|
@@ -6507,6 +6609,27 @@ class MachineWindow(QMainWindow):
|
|
|
6507
6609
|
|
|
6508
6610
|
self.mem_lock = self.lock_button.isChecked()
|
|
6509
6611
|
|
|
6612
|
+
def pause(self):
|
|
6613
|
+
|
|
6614
|
+
if self.segmentation_worker is not None:
|
|
6615
|
+
try:
|
|
6616
|
+
print("Pausing segmenter")
|
|
6617
|
+
self.previewing = False
|
|
6618
|
+
self.segmentation_finished
|
|
6619
|
+
del self.segmentation_worker
|
|
6620
|
+
self.segmentation_worker = None
|
|
6621
|
+
except:
|
|
6622
|
+
pass
|
|
6623
|
+
|
|
6624
|
+
else:
|
|
6625
|
+
try:
|
|
6626
|
+
print("Restarting segmenter")
|
|
6627
|
+
self.previewing = True
|
|
6628
|
+
self.start_segmentation
|
|
6629
|
+
except:
|
|
6630
|
+
pass
|
|
6631
|
+
|
|
6632
|
+
|
|
6510
6633
|
|
|
6511
6634
|
def toggle_GPU(self):
|
|
6512
6635
|
|
|
@@ -6615,7 +6738,7 @@ class MachineWindow(QMainWindow):
|
|
|
6615
6738
|
else:
|
|
6616
6739
|
active_data = self.parent().channel_data[1]
|
|
6617
6740
|
|
|
6618
|
-
array3 = np.zeros_like(active_data)
|
|
6741
|
+
array3 = np.zeros_like(active_data).astype(np.uint8)
|
|
6619
6742
|
self.parent().highlight_overlay = array3 #Clear this out for the segmenter to use
|
|
6620
6743
|
|
|
6621
6744
|
if not self.trained:
|
|
@@ -6801,7 +6924,7 @@ class MachineWindow(QMainWindow):
|
|
|
6801
6924
|
else:
|
|
6802
6925
|
active_data = self.parent().channel_data[1]
|
|
6803
6926
|
|
|
6804
|
-
array3 = np.zeros_like(active_data)
|
|
6927
|
+
array3 = np.zeros_like(active_data).astype(np.uint8)
|
|
6805
6928
|
self.parent().highlight_overlay = array3 #Clear this out for the segmenter to use
|
|
6806
6929
|
|
|
6807
6930
|
print("Segmenting entire volume with model...")
|
|
@@ -7589,6 +7712,65 @@ class MaskDialog(QDialog):
|
|
|
7589
7712
|
print(f"Error masking: {e}")
|
|
7590
7713
|
|
|
7591
7714
|
|
|
7715
|
+
class TypeDialog(QDialog):
|
|
7716
|
+
|
|
7717
|
+
def __init__(self, parent=None):
|
|
7718
|
+
|
|
7719
|
+
super().__init__(parent)
|
|
7720
|
+
self.setWindowTitle("Active Channel dtype")
|
|
7721
|
+
self.setModal(True)
|
|
7722
|
+
|
|
7723
|
+
layout = QFormLayout(self)
|
|
7724
|
+
|
|
7725
|
+
self.active_chan = self.parent().active_channel
|
|
7726
|
+
|
|
7727
|
+
active_data = self.parent().channel_data[self.active_chan]
|
|
7728
|
+
|
|
7729
|
+
layout.addRow("Info:", QLabel(f"Active dtype (Channel {self.active_chan}): {active_data.dtype}"))
|
|
7730
|
+
|
|
7731
|
+
# Add mode selection dropdown
|
|
7732
|
+
self.mode_selector = QComboBox()
|
|
7733
|
+
self.mode_selector.addItems(["8bit int", "16bit int", "32bit int", "32bit float", "64bit float"])
|
|
7734
|
+
self.mode_selector.setCurrentIndex(0) # Default to Mode 1
|
|
7735
|
+
layout.addRow("Change to?:", self.mode_selector)
|
|
7736
|
+
|
|
7737
|
+
# Add Run button
|
|
7738
|
+
run_button = QPushButton("Run")
|
|
7739
|
+
run_button.clicked.connect(lambda: self.run_type(active_data))
|
|
7740
|
+
layout.addRow(run_button)
|
|
7741
|
+
|
|
7742
|
+
def run_type(self, active_data):
|
|
7743
|
+
|
|
7744
|
+
mode = self.mode_selector.currentIndex()
|
|
7745
|
+
|
|
7746
|
+
if mode == 0:
|
|
7747
|
+
|
|
7748
|
+
active_data = active_data.astype(np.uint8)
|
|
7749
|
+
|
|
7750
|
+
elif mode == 1:
|
|
7751
|
+
|
|
7752
|
+
active_data = active_data.astype(np.uint16)
|
|
7753
|
+
|
|
7754
|
+
elif mode == 2:
|
|
7755
|
+
|
|
7756
|
+
active_data = active_data.astype(np.uint32)
|
|
7757
|
+
|
|
7758
|
+
elif mode == 3:
|
|
7759
|
+
|
|
7760
|
+
active_data = active_data.astype(np.float32)
|
|
7761
|
+
|
|
7762
|
+
elif mode == 4:
|
|
7763
|
+
|
|
7764
|
+
active_data = active_data.astype(np.float64)
|
|
7765
|
+
|
|
7766
|
+
self.parent().load_channel(self.active_chan, active_data, True)
|
|
7767
|
+
|
|
7768
|
+
|
|
7769
|
+
print(f"Channel {self.active_chan}) dtype now: {self.parent().channel_data[self.active_chan].dtype}")
|
|
7770
|
+
self.accept()
|
|
7771
|
+
|
|
7772
|
+
|
|
7773
|
+
|
|
7592
7774
|
|
|
7593
7775
|
class SkeletonizeDialog(QDialog):
|
|
7594
7776
|
def __init__(self, parent=None):
|
nettracer3d/segmenter.py
CHANGED
|
@@ -1289,6 +1289,9 @@ class InteractiveSegmenter:
|
|
|
1289
1289
|
"""Segment volume using parallel processing of chunks with vectorized chunk creation"""
|
|
1290
1290
|
#Change the above chunk size to None to have it auto-compute largest chunks (not sure which is faster, 64 seems reasonable in test cases)
|
|
1291
1291
|
|
|
1292
|
+
self.realtimechunks = None # Presumably no longer need this.
|
|
1293
|
+
self.map_slice = None
|
|
1294
|
+
|
|
1292
1295
|
if self.mem_lock:
|
|
1293
1296
|
chunk_size = 32 #memory efficient chunk
|
|
1294
1297
|
|
|
@@ -1302,7 +1305,7 @@ class InteractiveSegmenter:
|
|
|
1302
1305
|
Returns:
|
|
1303
1306
|
List of chunks, where each chunk contains the coordinates for one z-slice or subchunk
|
|
1304
1307
|
"""
|
|
1305
|
-
MAX_CHUNK_SIZE =
|
|
1308
|
+
MAX_CHUNK_SIZE = 32768
|
|
1306
1309
|
chunks = []
|
|
1307
1310
|
|
|
1308
1311
|
for z in range(self.image_3d.shape[0]):
|
|
@@ -1690,6 +1693,7 @@ class InteractiveSegmenter:
|
|
|
1690
1693
|
def train_batch(self, foreground_array, speed = True, use_gpu = False, use_two = False, mem_lock = False):
|
|
1691
1694
|
"""Train directly on foreground and background arrays"""
|
|
1692
1695
|
|
|
1696
|
+
print("Training model...")
|
|
1693
1697
|
self.speed = speed
|
|
1694
1698
|
self.cur_gpu = use_gpu
|
|
1695
1699
|
if mem_lock != self.mem_lock:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: nettracer3d
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.3
|
|
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
|
|
@@ -33,6 +33,7 @@ Provides-Extra: cuda12
|
|
|
33
33
|
Requires-Dist: cupy-cuda12x; extra == "cuda12"
|
|
34
34
|
Provides-Extra: cupy
|
|
35
35
|
Requires-Dist: cupy; extra == "cupy"
|
|
36
|
+
Dynamic: license-file
|
|
36
37
|
|
|
37
38
|
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:
|
|
38
39
|
|
|
@@ -44,8 +45,10 @@ NetTracer3D is free to use/fork for academic/nonprofit use so long as citation i
|
|
|
44
45
|
|
|
45
46
|
NetTracer3D was developed by Liam McLaughlin while working under Dr. Sanjay Jain at Washington University School of Medicine.
|
|
46
47
|
|
|
47
|
-
-- Version 0.6.
|
|
48
|
+
-- Version 0.6.3 updates --
|
|
48
49
|
|
|
49
|
-
1. Fixed bug with
|
|
50
|
+
1. Fixed bug with the active channel indicator on the GUI not always updating when the active channel was changed by internal loading.
|
|
50
51
|
|
|
51
|
-
2. Updated ram_lock mode in the segmenter to
|
|
52
|
+
2. Updated ram_lock mode in the segmenter to garbage collect better... again.
|
|
53
|
+
|
|
54
|
+
3. Added new function (Label neighborhoods). Find it in process -> image -> label neighborhoods. Allows a 3d labeled array to act as a kernel and extend its labels along a secondary binary array. This can be useful in evaluating nearest neighbors en-masse. The method behind this (smart label) was previously used internally for some methods (ie watershedding) but I thought I'd include it as an actual function since it has some more general uses.
|
|
@@ -3,18 +3,18 @@ nettracer3d/community_extractor.py,sha256=Zq8ZM595CTzeR6zLEZ4I6KvhkNfCPUReWvAKxT
|
|
|
3
3
|
nettracer3d/modularity.py,sha256=V1f3s_vGd8EuVz27mzq6ycIGr0BWIpH7c7NU4QjgAHU,30247
|
|
4
4
|
nettracer3d/morphology.py,sha256=yQ0GuieMVXOQpaohZlPnkEXEuCUjf8Fg352axyK8nbM,10755
|
|
5
5
|
nettracer3d/nettracer.py,sha256=AS3r7Wg3MWv-FARApRCrzyuzb0l0_h944EfXFI75lng,207912
|
|
6
|
-
nettracer3d/nettracer_gui.py,sha256=
|
|
6
|
+
nettracer3d/nettracer_gui.py,sha256=bTVauxgJXEF1Ufay3gXCqjy5J5DAHMnt5MlviSRzn2A,383537
|
|
7
7
|
nettracer3d/network_analysis.py,sha256=MJBBjslA1k_R8ymid77U-qGSgzxFVfzGVQhE0IdhnbE,48046
|
|
8
8
|
nettracer3d/network_draw.py,sha256=F7fw6Pcf4qWOhdKwLmhwqWdschbDlHzwCVolQC9imeU,14117
|
|
9
9
|
nettracer3d/node_draw.py,sha256=k3sCTfUCJs3aH1C1q1gTNxDz9EAQbBd1hsUIJajxRx8,9823
|
|
10
10
|
nettracer3d/proximity.py,sha256=FnIiI_AzfXd22HwCIFIyQRZxKYJ8YscIDdPnIv-wsO4,10560
|
|
11
11
|
nettracer3d/run.py,sha256=xYeaAc8FCx8MuzTGyL3NR3mK7WZzffAYAH23bNRZYO4,127
|
|
12
|
-
nettracer3d/segmenter.py,sha256=
|
|
12
|
+
nettracer3d/segmenter.py,sha256=oKQEKQpo3o6cqfN6Z_IAgx8V-HXpegQNjfWFz3Bdu04,83449
|
|
13
13
|
nettracer3d/simple_network.py,sha256=fP1gkDdtQcHruEZpUdasKdZeVacoLOxKhR3bY0L1CAQ,15426
|
|
14
14
|
nettracer3d/smart_dilate.py,sha256=6m03KHtRMv0zfJ2aHc1Om4Fhh2abPy-IqDzRCmIEHCY,24588
|
|
15
|
-
nettracer3d-0.6.
|
|
16
|
-
nettracer3d-0.6.
|
|
17
|
-
nettracer3d-0.6.
|
|
18
|
-
nettracer3d-0.6.
|
|
19
|
-
nettracer3d-0.6.
|
|
20
|
-
nettracer3d-0.6.
|
|
15
|
+
nettracer3d-0.6.3.dist-info/licenses/LICENSE,sha256=gM207DhJjWrxLuEWXl0Qz5ISbtWDmADfjHp3yC2XISs,888
|
|
16
|
+
nettracer3d-0.6.3.dist-info/METADATA,sha256=qTU9_FA2xsowZID-6_tB7kMJ2cQH8EkAipAKaEu0VzU,3668
|
|
17
|
+
nettracer3d-0.6.3.dist-info/WHEEL,sha256=tTnHoFhvKQHCh4jz3yCn0WPTYIy7wXx3CJtJ7SJGV7c,91
|
|
18
|
+
nettracer3d-0.6.3.dist-info/entry_points.txt,sha256=Nx1rr_0QhJXDBHAQg2vcqCzLMKBzSHfwy3xwGkueVyc,53
|
|
19
|
+
nettracer3d-0.6.3.dist-info/top_level.txt,sha256=zsYy9rZwirfCEOubolhee4TyzqBAL5gSUeFMzhFTX8c,12
|
|
20
|
+
nettracer3d-0.6.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|