nettracer3d 0.6.8__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/modularity.py +23 -24
- nettracer3d/morphology.py +12 -9
- nettracer3d/nettracer.py +95 -44
- nettracer3d/nettracer_gui.py +264 -59
- nettracer3d/proximity.py +49 -13
- nettracer3d/segmenter.py +1 -1
- nettracer3d/smart_dilate.py +19 -20
- {nettracer3d-0.6.8.dist-info → nettracer3d-0.6.9.dist-info}/METADATA +40 -9
- nettracer3d-0.6.9.dist-info/RECORD +20 -0
- nettracer3d-0.6.8.dist-info/RECORD +0 -20
- {nettracer3d-0.6.8.dist-info → nettracer3d-0.6.9.dist-info}/WHEEL +0 -0
- {nettracer3d-0.6.8.dist-info → nettracer3d-0.6.9.dist-info}/entry_points.txt +0 -0
- {nettracer3d-0.6.8.dist-info → nettracer3d-0.6.9.dist-info}/licenses/LICENSE +0 -0
- {nettracer3d-0.6.8.dist-info → nettracer3d-0.6.9.dist-info}/top_level.txt +0 -0
nettracer3d/nettracer_gui.py
CHANGED
|
@@ -25,7 +25,7 @@ import multiprocessing as mp
|
|
|
25
25
|
from concurrent.futures import ThreadPoolExecutor
|
|
26
26
|
from functools import partial
|
|
27
27
|
from nettracer3d import segmenter
|
|
28
|
-
#from nettracer3d import segmenter_GPU
|
|
28
|
+
#from nettracer3d import segmenter_GPU <--- couldn't get this faster than CPU ¯\_(ツ)_/¯
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
|
|
@@ -818,6 +818,8 @@ class ImageViewerWindow(QMainWindow):
|
|
|
818
818
|
link_nodes.triggered.connect(self.handle_link)
|
|
819
819
|
delink_nodes = highlight_menu.addAction("Split Nodes")
|
|
820
820
|
delink_nodes.triggered.connect(self.handle_split)
|
|
821
|
+
override_obj = highlight_menu.addAction("Override Channel with Selection")
|
|
822
|
+
override_obj.triggered.connect(self.handle_override)
|
|
821
823
|
context_menu.addMenu(highlight_menu)
|
|
822
824
|
|
|
823
825
|
# Create measure menu
|
|
@@ -1662,7 +1664,9 @@ class ImageViewerWindow(QMainWindow):
|
|
|
1662
1664
|
print(f"An error has occurred: {e}")
|
|
1663
1665
|
|
|
1664
1666
|
|
|
1665
|
-
|
|
1667
|
+
def handle_override(self):
|
|
1668
|
+
dialog = OverrideDialog(self)
|
|
1669
|
+
dialog.exec()
|
|
1666
1670
|
|
|
1667
1671
|
|
|
1668
1672
|
|
|
@@ -1970,6 +1974,28 @@ class ImageViewerWindow(QMainWindow):
|
|
|
1970
1974
|
points.append((x, y))
|
|
1971
1975
|
return points
|
|
1972
1976
|
|
|
1977
|
+
def get_current_mouse_position(self):
|
|
1978
|
+
# Get the main application's current mouse position
|
|
1979
|
+
cursor_pos = QCursor.pos()
|
|
1980
|
+
|
|
1981
|
+
# Convert global screen coordinates to canvas widget coordinates
|
|
1982
|
+
canvas_pos = self.canvas.mapFromGlobal(cursor_pos)
|
|
1983
|
+
|
|
1984
|
+
# Check if the position is within the canvas bounds
|
|
1985
|
+
if not (0 <= canvas_pos.x() < self.canvas.width() and
|
|
1986
|
+
0 <= canvas_pos.y() < self.canvas.height()):
|
|
1987
|
+
return 0, 0 # Mouse is outside of the matplotlib canvas
|
|
1988
|
+
|
|
1989
|
+
# Convert from canvas widget coordinates to matplotlib data coordinates
|
|
1990
|
+
x = canvas_pos.x()
|
|
1991
|
+
y = canvas_pos.y()
|
|
1992
|
+
|
|
1993
|
+
# Transform display coordinates to data coordinates
|
|
1994
|
+
inv = self.ax.transData.inverted()
|
|
1995
|
+
data_coords = inv.transform((x, y))
|
|
1996
|
+
|
|
1997
|
+
return data_coords[0], data_coords[1]
|
|
1998
|
+
|
|
1973
1999
|
def on_mouse_press(self, event):
|
|
1974
2000
|
"""Handle mouse press events."""
|
|
1975
2001
|
if event.inaxes != self.ax:
|
|
@@ -2958,8 +2984,11 @@ class ImageViewerWindow(QMainWindow):
|
|
|
2958
2984
|
|
|
2959
2985
|
def show_type_dialog(self):
|
|
2960
2986
|
"""Show the type dialog"""
|
|
2961
|
-
|
|
2962
|
-
|
|
2987
|
+
try:
|
|
2988
|
+
dialog = TypeDialog(self)
|
|
2989
|
+
dialog.exec()
|
|
2990
|
+
except:
|
|
2991
|
+
pass
|
|
2963
2992
|
|
|
2964
2993
|
def show_skeletonize_dialog(self):
|
|
2965
2994
|
"""show the skeletonize dialog"""
|
|
@@ -4908,10 +4937,10 @@ class PropertiesDialog(QDialog):
|
|
|
4908
4937
|
self.id_overlay.setChecked(self.check_checked(my_network.id_overlay))
|
|
4909
4938
|
layout.addRow("Overlay 2 Status", self.id_overlay)
|
|
4910
4939
|
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
|
|
4914
|
-
|
|
4940
|
+
self.search_region = QPushButton("search region")
|
|
4941
|
+
self.search_region.setCheckable(True)
|
|
4942
|
+
self.search_region.setChecked(self.check_checked(my_network.search_region))
|
|
4943
|
+
layout.addRow("Node Search Region Status", self.search_region)
|
|
4915
4944
|
|
|
4916
4945
|
self.network = QPushButton("Network")
|
|
4917
4946
|
self.network.setCheckable(True)
|
|
@@ -4950,10 +4979,10 @@ class PropertiesDialog(QDialog):
|
|
|
4950
4979
|
edges = not self.edges.isChecked()
|
|
4951
4980
|
network_overlay = not self.network_overlay.isChecked()
|
|
4952
4981
|
id_overlay = not self.id_overlay.isChecked()
|
|
4953
|
-
|
|
4982
|
+
search_region = not self.search_region.isChecked()
|
|
4954
4983
|
network = not self.network.isChecked()
|
|
4955
4984
|
|
|
4956
|
-
self.parent().reset(nodes = nodes, edges = edges, network_overlay = network_overlay, id_overlay = id_overlay, network = network, xy_scale = xy_scale, z_scale = z_scale)
|
|
4985
|
+
self.parent().reset(nodes = nodes, edges = edges, search_region = search_region, network_overlay = network_overlay, id_overlay = id_overlay, network = network, xy_scale = xy_scale, z_scale = z_scale)
|
|
4957
4986
|
|
|
4958
4987
|
self.accept()
|
|
4959
4988
|
|
|
@@ -5957,7 +5986,7 @@ class RandomDialog(QDialog):
|
|
|
5957
5986
|
def __init__(self, parent=None):
|
|
5958
5987
|
|
|
5959
5988
|
super().__init__(parent)
|
|
5960
|
-
self.setWindowTitle("
|
|
5989
|
+
self.setWindowTitle("Random Parameters")
|
|
5961
5990
|
self.setModal(True)
|
|
5962
5991
|
|
|
5963
5992
|
layout = QFormLayout(self)
|
|
@@ -6001,10 +6030,10 @@ class RadDialog(QDialog):
|
|
|
6001
6030
|
layout = QFormLayout(self)
|
|
6002
6031
|
|
|
6003
6032
|
# GPU checkbox (default False)
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
|
|
6007
|
-
|
|
6033
|
+
self.GPU = QPushButton("GPU")
|
|
6034
|
+
self.GPU.setCheckable(True)
|
|
6035
|
+
self.GPU.setChecked(False)
|
|
6036
|
+
layout.addRow("Use GPU:", self.GPU)
|
|
6008
6037
|
|
|
6009
6038
|
|
|
6010
6039
|
# Add Run button
|
|
@@ -6015,7 +6044,7 @@ class RadDialog(QDialog):
|
|
|
6015
6044
|
def rads(self):
|
|
6016
6045
|
|
|
6017
6046
|
try:
|
|
6018
|
-
|
|
6047
|
+
GPU = self.GPU.isChecked() # <- I can never get these to be faster than parallel CPU *shrugs*
|
|
6019
6048
|
|
|
6020
6049
|
active_data = self.parent().channel_data[self.parent().active_channel]
|
|
6021
6050
|
|
|
@@ -6042,7 +6071,7 @@ class InteractionDialog(QDialog):
|
|
|
6042
6071
|
def __init__(self, parent=None):
|
|
6043
6072
|
|
|
6044
6073
|
super().__init__(parent)
|
|
6045
|
-
self.setWindowTitle("
|
|
6074
|
+
self.setWindowTitle("Interaction Parameters")
|
|
6046
6075
|
self.setModal(True)
|
|
6047
6076
|
|
|
6048
6077
|
layout = QFormLayout(self)
|
|
@@ -6062,7 +6091,7 @@ class InteractionDialog(QDialog):
|
|
|
6062
6091
|
self.fastdil = QPushButton("Fast Dilate")
|
|
6063
6092
|
self.fastdil.setCheckable(True)
|
|
6064
6093
|
self.fastdil.setChecked(False)
|
|
6065
|
-
layout.addRow("
|
|
6094
|
+
layout.addRow("Use Fast Dilation (Higher speed, less accurate with search regions much larger than nodes):", self.fastdil)
|
|
6066
6095
|
|
|
6067
6096
|
# Add Run button
|
|
6068
6097
|
run_button = QPushButton("Calculate")
|
|
@@ -6117,7 +6146,7 @@ class DegreeDialog(QDialog):
|
|
|
6117
6146
|
layout.addRow("Execution Mode:", self.mode_selector)
|
|
6118
6147
|
|
|
6119
6148
|
self.mask_limiter = QLineEdit("1")
|
|
6120
|
-
layout.addRow("
|
|
6149
|
+
layout.addRow("Proportion of high degree nodes to keep (ignore if only returning degrees)", self.mask_limiter)
|
|
6121
6150
|
|
|
6122
6151
|
self.down_factor = QLineEdit("1")
|
|
6123
6152
|
layout.addRow("down_factor (for speeding up overlay generation - ignore if only returning degrees:", self.down_factor)
|
|
@@ -6662,6 +6691,116 @@ class ResizeDialog(QDialog):
|
|
|
6662
6691
|
QMessageBox.critical(self, "Error", f"Failed to resize: {str(e)}")
|
|
6663
6692
|
|
|
6664
6693
|
|
|
6694
|
+
class OverrideDialog(QDialog):
|
|
6695
|
+
def __init__(self, parent=None):
|
|
6696
|
+
super().__init__(parent)
|
|
6697
|
+
self.setWindowTitle("Override Parameters")
|
|
6698
|
+
self.setModal(True)
|
|
6699
|
+
|
|
6700
|
+
layout = QFormLayout(self)
|
|
6701
|
+
|
|
6702
|
+
layout.addRow(QLabel("Use Highlight Overlay to Place Data From: "))
|
|
6703
|
+
|
|
6704
|
+
# Add mode selection dropdown
|
|
6705
|
+
self.mode_selector = QComboBox()
|
|
6706
|
+
self.mode_selector.addItems(["Nodes", "Edges"])
|
|
6707
|
+
self.mode_selector.setCurrentIndex(0) # Default to Mode 1
|
|
6708
|
+
layout.addRow("Overrider:", self.mode_selector)
|
|
6709
|
+
|
|
6710
|
+
layout.addRow(QLabel("To Override Corresponding Data In: "))
|
|
6711
|
+
|
|
6712
|
+
# Add mode selection dropdown
|
|
6713
|
+
self.target_selector = QComboBox()
|
|
6714
|
+
self.target_selector.addItems(["Nodes", "Edges", "Overlay 1", "Overlay 2"])
|
|
6715
|
+
self.target_selector.setCurrentIndex(0) # Default to Mode 1
|
|
6716
|
+
layout.addRow("To be overwritten:", self.target_selector)
|
|
6717
|
+
|
|
6718
|
+
layout.addRow(QLabel("Place output in: "))
|
|
6719
|
+
|
|
6720
|
+
# Add mode selection dropdown
|
|
6721
|
+
self.output_selector = QComboBox()
|
|
6722
|
+
self.output_selector.addItems(["Nodes", "Edges", "Overlay 1", "Overlay 2", "Highlight Overlay"])
|
|
6723
|
+
self.output_selector.setCurrentIndex(0) # Default to Mode 1
|
|
6724
|
+
layout.addRow("Output Location:", self.output_selector)
|
|
6725
|
+
|
|
6726
|
+
# Add Run button
|
|
6727
|
+
run_button = QPushButton("Override")
|
|
6728
|
+
run_button.clicked.connect(self.override)
|
|
6729
|
+
layout.addWidget(run_button)
|
|
6730
|
+
|
|
6731
|
+
def override(self):
|
|
6732
|
+
|
|
6733
|
+
try:
|
|
6734
|
+
|
|
6735
|
+
accepted_mode = self.mode_selector.currentIndex()
|
|
6736
|
+
accepted_target = self.target_selector.currentIndex()
|
|
6737
|
+
output_target = self.output_selector.currentIndex()
|
|
6738
|
+
|
|
6739
|
+
if accepted_mode == accepted_target:
|
|
6740
|
+
return
|
|
6741
|
+
|
|
6742
|
+
active_data = self.parent().channel_data[accepted_mode]
|
|
6743
|
+
|
|
6744
|
+
if accepted_mode == 0:
|
|
6745
|
+
self.parent().create_highlight_overlay(node_indices=self.parent().clicked_values['nodes'])
|
|
6746
|
+
else:
|
|
6747
|
+
self.parent().create_highlight_overlay(edge_indices=self.parent().clicked_values['edges'])
|
|
6748
|
+
|
|
6749
|
+
target_data = self.parent().channel_data[accepted_target]
|
|
6750
|
+
|
|
6751
|
+
if target_data is None:
|
|
6752
|
+
target_data = np.zeros_like(active_data)
|
|
6753
|
+
|
|
6754
|
+
|
|
6755
|
+
|
|
6756
|
+
try:
|
|
6757
|
+
|
|
6758
|
+
self.parent().highlight_overlay = self.parent().highlight_overlay > 0 #What we want in override image
|
|
6759
|
+
inv = n3d.invert_boolean(self.parent().highlight_overlay) #what we want to keep in target image
|
|
6760
|
+
|
|
6761
|
+
target_data = target_data * inv #Cut out what we don't want in target image
|
|
6762
|
+
max_val = np.max(target_data) #Ensure non-val overlap
|
|
6763
|
+
other_max = np.max(active_data)
|
|
6764
|
+
true_max = max_val + other_max
|
|
6765
|
+
if true_max < 256:
|
|
6766
|
+
dtype = np.uint8
|
|
6767
|
+
elif true_max < 65536:
|
|
6768
|
+
dtype = np.uint16
|
|
6769
|
+
else:
|
|
6770
|
+
dtype = np.uint32
|
|
6771
|
+
|
|
6772
|
+
active_data = active_data.astype(dtype)
|
|
6773
|
+
|
|
6774
|
+
active_data = active_data + max_val #Transpose override image
|
|
6775
|
+
|
|
6776
|
+
active_data = self.parent().highlight_overlay * active_data #Cut out what we want from old image image
|
|
6777
|
+
|
|
6778
|
+
target_data = target_data.astype(dtype)
|
|
6779
|
+
|
|
6780
|
+
target_data = target_data + active_data #Insert new selection
|
|
6781
|
+
|
|
6782
|
+
if output_target == 4:
|
|
6783
|
+
|
|
6784
|
+
self.parent().highlight_overlay = result
|
|
6785
|
+
|
|
6786
|
+
else:
|
|
6787
|
+
|
|
6788
|
+
|
|
6789
|
+
# Update both the display data and the network object
|
|
6790
|
+
self.parent().load_channel(output_target, channel_data = target_data, data = True)
|
|
6791
|
+
|
|
6792
|
+
self.parent().update_display()
|
|
6793
|
+
|
|
6794
|
+
self.accept()
|
|
6795
|
+
|
|
6796
|
+
except Exception as e:
|
|
6797
|
+
print(f"Error overriding: {e}")
|
|
6798
|
+
|
|
6799
|
+
except Exception as e:
|
|
6800
|
+
print(f"Error overriding: {e}")
|
|
6801
|
+
|
|
6802
|
+
|
|
6803
|
+
|
|
6665
6804
|
class BinarizeDialog(QDialog):
|
|
6666
6805
|
def __init__(self, parent=None):
|
|
6667
6806
|
super().__init__(parent)
|
|
@@ -6923,7 +7062,7 @@ class ThresholdDialog(QDialog):
|
|
|
6923
7062
|
try:
|
|
6924
7063
|
import cupy as cp
|
|
6925
7064
|
except:
|
|
6926
|
-
print("Cupy import failed, using CPU version")
|
|
7065
|
+
#print("Cupy import failed, using CPU version")
|
|
6927
7066
|
GPU = False
|
|
6928
7067
|
|
|
6929
7068
|
if self.parent().mini_overlay_data is not None:
|
|
@@ -6983,8 +7122,12 @@ class MachineWindow(QMainWindow):
|
|
|
6983
7122
|
active_data = self.parent().channel_data[1]
|
|
6984
7123
|
act_channel = 1
|
|
6985
7124
|
|
|
7125
|
+
try:
|
|
7126
|
+
array1 = np.zeros_like(active_data).astype(np.uint8)
|
|
7127
|
+
except:
|
|
7128
|
+
print("No data in nodes channel")
|
|
7129
|
+
return
|
|
6986
7130
|
|
|
6987
|
-
array1 = np.zeros_like(active_data).astype(np.uint8)
|
|
6988
7131
|
array3 = np.zeros_like(active_data).astype(np.uint8)
|
|
6989
7132
|
self.parent().highlight_overlay = array3 #Clear this out for the segmenter to use
|
|
6990
7133
|
|
|
@@ -7227,6 +7370,7 @@ class MachineWindow(QMainWindow):
|
|
|
7227
7370
|
)
|
|
7228
7371
|
|
|
7229
7372
|
|
|
7373
|
+
|
|
7230
7374
|
def start_segmentation(self):
|
|
7231
7375
|
|
|
7232
7376
|
self.kill_segmentation()
|
|
@@ -7255,7 +7399,11 @@ class MachineWindow(QMainWindow):
|
|
|
7255
7399
|
self.segmentation_worker.finished.connect(self.segmentation_finished)
|
|
7256
7400
|
current_xlim = self.parent().ax.get_xlim()
|
|
7257
7401
|
current_ylim = self.parent().ax.get_ylim()
|
|
7258
|
-
|
|
7402
|
+
try:
|
|
7403
|
+
x, y = self.parent().get_current_mouse_position()
|
|
7404
|
+
except:
|
|
7405
|
+
x, y = 0, 0
|
|
7406
|
+
self.segmenter.update_position(self.parent().current_slice, x, y)
|
|
7259
7407
|
self.segmentation_worker.start()
|
|
7260
7408
|
|
|
7261
7409
|
def confirm_seg_dialog(self):
|
|
@@ -7321,7 +7469,12 @@ class MachineWindow(QMainWindow):
|
|
|
7321
7469
|
current_xlim = self.parent().ax.get_xlim()
|
|
7322
7470
|
current_ylim = self.parent().ax.get_ylim()
|
|
7323
7471
|
|
|
7324
|
-
|
|
7472
|
+
try:
|
|
7473
|
+
x, y = self.parent().get_current_mouse_position()
|
|
7474
|
+
except:
|
|
7475
|
+
x, y = 0, 0
|
|
7476
|
+
self.segmenter.update_position(self.parent().current_slice, x, y)
|
|
7477
|
+
|
|
7325
7478
|
if not self.parent().painting:
|
|
7326
7479
|
# Only update if view limits are valid
|
|
7327
7480
|
self.parent().update_display(preserve_zoom=(current_xlim, current_ylim))
|
|
@@ -7616,6 +7769,8 @@ class ThresholdWindow(QMainWindow):
|
|
|
7616
7769
|
self.bounds = True
|
|
7617
7770
|
self.parent().bounds = True
|
|
7618
7771
|
|
|
7772
|
+
self.chan = self.parent().active_channel
|
|
7773
|
+
|
|
7619
7774
|
|
|
7620
7775
|
# Create matplotlib figure
|
|
7621
7776
|
fig = Figure(figsize=(5, 4))
|
|
@@ -7684,6 +7839,45 @@ class ThresholdWindow(QMainWindow):
|
|
|
7684
7839
|
self.parent().preview = False
|
|
7685
7840
|
self.parent().targs = None
|
|
7686
7841
|
self.parent().bounds = False
|
|
7842
|
+
try: # could probably be refactored but this just handles keeping the highlight elements if the user presses X
|
|
7843
|
+
if self.chan == 0:
|
|
7844
|
+
if not self.bounds:
|
|
7845
|
+
self.parent().clicked_values['nodes'] = self.get_values_in_range_all_vols(self.chan, float(self.min.text()), float(self.max.text()))
|
|
7846
|
+
else:
|
|
7847
|
+
vals = np.unique(self.parent().channel_data[self.chan])
|
|
7848
|
+
self.parent().clicked_values['nodes'] = (vals[(vals >= float(self.min.text())) & (vals <= float(self.max.text()))]).tolist()
|
|
7849
|
+
|
|
7850
|
+
if self.parent().channel_data[0].shape[0] * self.parent().channel_data[0].shape[1] * self.parent().channel_data[0].shape[2] > self.parent().mini_thresh:
|
|
7851
|
+
self.parent().mini_overlay = True
|
|
7852
|
+
self.parent().create_mini_overlay(node_indices = self.parent().clicked_values['nodes'])
|
|
7853
|
+
else:
|
|
7854
|
+
self.parent().create_highlight_overlay(
|
|
7855
|
+
node_indices=self.parent().clicked_values['nodes']
|
|
7856
|
+
)
|
|
7857
|
+
elif self.chan == 1:
|
|
7858
|
+
if not self.bounds:
|
|
7859
|
+
self.parent().clicked_values['edges'] = self.get_values_in_range_all_vols(self.chan, float(self.min.text()), float(self.max.text()))
|
|
7860
|
+
else:
|
|
7861
|
+
vals = np.unique(self.parent().channel_data[self.chan])
|
|
7862
|
+
self.parent().clicked_values['edges'] = (vals[(vals >= float(self.min.text())) & (vals <= float(self.max.text()))]).tolist()
|
|
7863
|
+
|
|
7864
|
+
if self.parent().channel_data[1].shape[0] * self.parent().channel_data[1].shape[1] * self.parent().channel_data[1].shape[2] > self.parent().mini_thresh:
|
|
7865
|
+
self.parent().mini_overlay = True
|
|
7866
|
+
self.parent().create_mini_overlay(edge_indices = self.parent().clicked_values['edges'])
|
|
7867
|
+
else:
|
|
7868
|
+
self.parent().create_highlight_overlay(
|
|
7869
|
+
node_indices=self.parent().clicked_values['edges']
|
|
7870
|
+
)
|
|
7871
|
+
except:
|
|
7872
|
+
pass
|
|
7873
|
+
|
|
7874
|
+
|
|
7875
|
+
def get_values_in_range_all_vols(self, chan, min_val, max_val):
|
|
7876
|
+
output = []
|
|
7877
|
+
for node, vol in self.parent().volume_dict[chan].items():
|
|
7878
|
+
if min_val <= vol <= max_val:
|
|
7879
|
+
output.append(node)
|
|
7880
|
+
return output
|
|
7687
7881
|
|
|
7688
7882
|
def get_values_in_range(self, lst, min_val, max_val):
|
|
7689
7883
|
values = [x for x in lst if min_val <= x <= max_val]
|
|
@@ -7882,10 +8076,10 @@ class SmartDilateDialog(QDialog):
|
|
|
7882
8076
|
layout.addRow("Use GPU:", self.GPU)
|
|
7883
8077
|
|
|
7884
8078
|
# dt checkbox (default False)
|
|
7885
|
-
self.predt = QPushButton("
|
|
8079
|
+
self.predt = QPushButton("Fast Dilation")
|
|
7886
8080
|
self.predt.setCheckable(True)
|
|
7887
8081
|
self.predt.setChecked(False)
|
|
7888
|
-
layout.addRow("Use
|
|
8082
|
+
layout.addRow("Use Fast Dilation (Higher speed, less accurate with search regions much larger than nodes):", self.predt)
|
|
7889
8083
|
|
|
7890
8084
|
self.down_factor = QLineEdit("")
|
|
7891
8085
|
layout.addRow("Internal Downsample for GPU (if needed):", self.down_factor)
|
|
@@ -7901,7 +8095,7 @@ class SmartDilateDialog(QDialog):
|
|
|
7901
8095
|
|
|
7902
8096
|
GPU = self.GPU.isChecked()
|
|
7903
8097
|
down_factor = float(self.down_factor.text()) if self.down_factor.text().strip() else None
|
|
7904
|
-
predt =
|
|
8098
|
+
predt = self.predt.isChecked()
|
|
7905
8099
|
active_data, amount, xy_scale, z_scale = self.params
|
|
7906
8100
|
|
|
7907
8101
|
dilate_xy, dilate_z = n3d.dilation_length_to_pixels(xy_scale, z_scale, amount, amount)
|
|
@@ -8000,7 +8194,8 @@ class DilateDialog(QDialog):
|
|
|
8000
8194
|
active_data,
|
|
8001
8195
|
amount,
|
|
8002
8196
|
xy_scale = xy_scale,
|
|
8003
|
-
z_scale = z_scale
|
|
8197
|
+
z_scale = z_scale,
|
|
8198
|
+
fast_dil = True)
|
|
8004
8199
|
|
|
8005
8200
|
result = result * 255
|
|
8006
8201
|
|
|
@@ -8250,6 +8445,7 @@ class MaskDialog(QDialog):
|
|
|
8250
8445
|
print(f"Error masking: {e}")
|
|
8251
8446
|
|
|
8252
8447
|
|
|
8448
|
+
|
|
8253
8449
|
class TypeDialog(QDialog):
|
|
8254
8450
|
|
|
8255
8451
|
def __init__(self, parent=None):
|
|
@@ -8268,7 +8464,7 @@ class TypeDialog(QDialog):
|
|
|
8268
8464
|
|
|
8269
8465
|
# Add mode selection dropdown
|
|
8270
8466
|
self.mode_selector = QComboBox()
|
|
8271
|
-
self.mode_selector.addItems(["8bit
|
|
8467
|
+
self.mode_selector.addItems(["8bit uint", "16bit uint", "32bit uint", "32bit float", "64bit float"])
|
|
8272
8468
|
self.mode_selector.setCurrentIndex(0) # Default to Mode 1
|
|
8273
8469
|
layout.addRow("Change to?:", self.mode_selector)
|
|
8274
8470
|
|
|
@@ -8279,33 +8475,38 @@ class TypeDialog(QDialog):
|
|
|
8279
8475
|
|
|
8280
8476
|
def run_type(self, active_data):
|
|
8281
8477
|
|
|
8282
|
-
|
|
8478
|
+
try:
|
|
8283
8479
|
|
|
8284
|
-
|
|
8480
|
+
mode = self.mode_selector.currentIndex()
|
|
8285
8481
|
|
|
8286
|
-
|
|
8482
|
+
if mode == 0:
|
|
8287
8483
|
|
|
8288
|
-
|
|
8484
|
+
active_data = active_data.astype(np.uint8)
|
|
8289
8485
|
|
|
8290
|
-
|
|
8486
|
+
elif mode == 1:
|
|
8291
8487
|
|
|
8292
|
-
|
|
8488
|
+
active_data = active_data.astype(np.uint16)
|
|
8293
8489
|
|
|
8294
|
-
|
|
8490
|
+
elif mode == 2:
|
|
8295
8491
|
|
|
8296
|
-
|
|
8492
|
+
active_data = active_data.astype(np.uint32)
|
|
8297
8493
|
|
|
8298
|
-
|
|
8494
|
+
elif mode == 3:
|
|
8299
8495
|
|
|
8300
|
-
|
|
8496
|
+
active_data = active_data.astype(np.float32)
|
|
8301
8497
|
|
|
8302
|
-
|
|
8498
|
+
elif mode == 4:
|
|
8303
8499
|
|
|
8304
|
-
|
|
8500
|
+
active_data = active_data.astype(np.float64)
|
|
8305
8501
|
|
|
8502
|
+
self.parent().load_channel(self.active_chan, active_data, True)
|
|
8306
8503
|
|
|
8307
|
-
|
|
8308
|
-
|
|
8504
|
+
|
|
8505
|
+
print(f"Channel {self.active_chan}) dtype now: {self.parent().channel_data[self.active_chan].dtype}")
|
|
8506
|
+
self.accept()
|
|
8507
|
+
|
|
8508
|
+
except Exception as E:
|
|
8509
|
+
print(f"Error: {e}")
|
|
8309
8510
|
|
|
8310
8511
|
|
|
8311
8512
|
|
|
@@ -8423,7 +8624,7 @@ class WatershedDialog(QDialog):
|
|
|
8423
8624
|
# Predownsample (empty by default)
|
|
8424
8625
|
self.predownsample = QLineEdit()
|
|
8425
8626
|
self.predownsample.setPlaceholderText("Leave empty for None")
|
|
8426
|
-
layout.addRow("
|
|
8627
|
+
layout.addRow("Kernel Obtainment GPU Downsample:", self.predownsample)
|
|
8427
8628
|
|
|
8428
8629
|
# Predownsample2 (empty by default)
|
|
8429
8630
|
self.predownsample2 = QLineEdit()
|
|
@@ -8658,9 +8859,9 @@ class GenNodesDialog(QDialog):
|
|
|
8658
8859
|
layout = QFormLayout(self)
|
|
8659
8860
|
self.called = called
|
|
8660
8861
|
|
|
8661
|
-
self.directory = QLineEdit()
|
|
8662
|
-
self.directory.setPlaceholderText("Leave empty to save in active dir")
|
|
8663
|
-
layout.addRow("Output Directory:", self.directory)
|
|
8862
|
+
#self.directory = QLineEdit()
|
|
8863
|
+
#self.directory.setPlaceholderText("Leave empty to save in active dir")
|
|
8864
|
+
#layout.addRow("Output Directory:", self.directory)
|
|
8664
8865
|
|
|
8665
8866
|
if not down_factor:
|
|
8666
8867
|
down_factor = None
|
|
@@ -8670,7 +8871,7 @@ class GenNodesDialog(QDialog):
|
|
|
8670
8871
|
self.cubic = QPushButton("Cubic Downsample")
|
|
8671
8872
|
self.cubic.setCheckable(True)
|
|
8672
8873
|
self.cubic.setChecked(False)
|
|
8673
|
-
layout.addRow("(if downsampling): Use cubic
|
|
8874
|
+
layout.addRow("(if downsampling): Use cubic downsample? (Slower but can preserve structure better)", self.cubic)
|
|
8674
8875
|
else:
|
|
8675
8876
|
self.down_factor = down_factor[0]
|
|
8676
8877
|
self.cubic = down_factor[1]
|
|
@@ -8714,7 +8915,7 @@ class GenNodesDialog(QDialog):
|
|
|
8714
8915
|
|
|
8715
8916
|
try:
|
|
8716
8917
|
# Get directory (None if empty)
|
|
8717
|
-
directory = self.directory.text() if self.directory.text() else None
|
|
8918
|
+
#directory = self.directory.text() if self.directory.text() else None
|
|
8718
8919
|
|
|
8719
8920
|
# Get branch_removal
|
|
8720
8921
|
try:
|
|
@@ -8860,7 +9061,7 @@ class BranchDialog(QDialog):
|
|
|
8860
9061
|
self.cubic = QPushButton("Cubic Downsample")
|
|
8861
9062
|
self.cubic.setCheckable(True)
|
|
8862
9063
|
self.cubic.setChecked(False)
|
|
8863
|
-
layout.addRow("(if downsampling): Use cubic
|
|
9064
|
+
layout.addRow("(if downsampling): Use cubic downsample? (Slower but can preserve structure better)", self.cubic)
|
|
8864
9065
|
|
|
8865
9066
|
# Add Run button
|
|
8866
9067
|
run_button = QPushButton("Run Branch Label")
|
|
@@ -9283,20 +9484,23 @@ class CentroidDialog(QDialog):
|
|
|
9283
9484
|
my_network.calculate_node_centroids(
|
|
9284
9485
|
down_factor = downsample
|
|
9285
9486
|
)
|
|
9286
|
-
|
|
9487
|
+
if directory:
|
|
9488
|
+
my_network.save_node_centroids(directory = directory)
|
|
9287
9489
|
|
|
9288
9490
|
elif chan == 2:
|
|
9289
9491
|
my_network.calculate_edge_centroids(
|
|
9290
9492
|
down_factor = downsample
|
|
9291
9493
|
)
|
|
9292
|
-
|
|
9494
|
+
if directory:
|
|
9495
|
+
my_network.save_edge_centroids(directory = directory)
|
|
9293
9496
|
|
|
9294
9497
|
elif chan == 0:
|
|
9295
9498
|
try:
|
|
9296
9499
|
my_network.calculate_node_centroids(
|
|
9297
9500
|
down_factor = downsample
|
|
9298
9501
|
)
|
|
9299
|
-
|
|
9502
|
+
if directory:
|
|
9503
|
+
my_network.save_node_centroids(directory = directory)
|
|
9300
9504
|
except:
|
|
9301
9505
|
pass
|
|
9302
9506
|
|
|
@@ -9305,7 +9509,8 @@ class CentroidDialog(QDialog):
|
|
|
9305
9509
|
my_network.calculate_edge_centroids(
|
|
9306
9510
|
down_factor = downsample
|
|
9307
9511
|
)
|
|
9308
|
-
|
|
9512
|
+
if directory:
|
|
9513
|
+
my_network.save_edge_centroids(directory = directory)
|
|
9309
9514
|
|
|
9310
9515
|
except:
|
|
9311
9516
|
pass
|
|
@@ -9346,7 +9551,7 @@ class CalcAllDialog(QDialog):
|
|
|
9346
9551
|
prev_GPU_downsample = ""
|
|
9347
9552
|
prev_other_nodes = ""
|
|
9348
9553
|
prev_remove_trunk = ""
|
|
9349
|
-
prev_gpu =
|
|
9554
|
+
prev_gpu = False
|
|
9350
9555
|
prev_label_nodes = True
|
|
9351
9556
|
prev_inners = True
|
|
9352
9557
|
prev_fastdil = False
|
|
@@ -9378,7 +9583,7 @@ class CalcAllDialog(QDialog):
|
|
|
9378
9583
|
|
|
9379
9584
|
self.diledge = QLineEdit(self.prev_diledge)
|
|
9380
9585
|
self.diledge.setPlaceholderText("Leave empty for None")
|
|
9381
|
-
layout.addRow("Edge Reconnection Distance (
|
|
9586
|
+
layout.addRow("Edge Reconnection Distance (float):", self.diledge)
|
|
9382
9587
|
|
|
9383
9588
|
self.down_factor = QLineEdit(self.prev_down_factor)
|
|
9384
9589
|
self.down_factor.setPlaceholderText("Leave empty for None")
|
|
@@ -9405,7 +9610,7 @@ class CalcAllDialog(QDialog):
|
|
|
9405
9610
|
self.label_nodes = QPushButton("Label")
|
|
9406
9611
|
self.label_nodes.setCheckable(True)
|
|
9407
9612
|
self.label_nodes.setChecked(self.prev_label_nodes)
|
|
9408
|
-
layout.addRow("Label Nodes:", self.label_nodes)
|
|
9613
|
+
layout.addRow("Re-Label Nodes (WARNING - OVERRIDES ANY CURRENT LABELS):", self.label_nodes)
|
|
9409
9614
|
|
|
9410
9615
|
self.inners = QPushButton("Inner Edges")
|
|
9411
9616
|
self.inners.setCheckable(True)
|
|
@@ -9744,13 +9949,13 @@ class ProxDialog(QDialog):
|
|
|
9744
9949
|
return
|
|
9745
9950
|
|
|
9746
9951
|
if populate:
|
|
9747
|
-
my_network.nodes = my_network.kd_network(distance = search, targets = targets)
|
|
9952
|
+
my_network.nodes = my_network.kd_network(distance = search, targets = targets, make_array = True)
|
|
9748
9953
|
self.parent().load_channel(0, channel_data = my_network.nodes, data = True)
|
|
9749
9954
|
else:
|
|
9750
9955
|
my_network.kd_network(distance = search, targets = targets)
|
|
9751
9956
|
|
|
9752
|
-
|
|
9753
|
-
|
|
9957
|
+
if directory is not None:
|
|
9958
|
+
my_network.dump(directory = directory)
|
|
9754
9959
|
|
|
9755
9960
|
|
|
9756
9961
|
# Then handle overlays
|