From d036619c794b40e0a1c26154f7b11ade1a8203a3 Mon Sep 17 00:00:00 2001 From: Cayla <26422897+caylamiller@users.noreply.github.com> Date: Thu, 31 Oct 2024 12:39:33 -0700 Subject: [PATCH] refactor _widget.py for clarity --- src/napari_cochlea_synapse_seg/_widget.py | 448 ++++++++++------------ 1 file changed, 197 insertions(+), 251 deletions(-) diff --git a/src/napari_cochlea_synapse_seg/_widget.py b/src/napari_cochlea_synapse_seg/_widget.py index 4c8b460..bc2fdb9 100644 --- a/src/napari_cochlea_synapse_seg/_widget.py +++ b/src/napari_cochlea_synapse_seg/_widget.py @@ -1,32 +1,46 @@ """ -This module contains two napari widgets: - -- 1. Point loader widget, with functionality related to - loading points (convert to real pixel units, Python function flagged with `autogenerate: true` - in the plugin manifest. Type annotations are used by - magicgui to generate widgets for each parameter. Best - suited for simple processing tasks - usually taking - in and/or returning a layer. -- a `magic_factory` decorated function. The `magic_factory` - decorator allows us to customize aspects of the resulting - GUI, including the widgets associated with each parameter. - Best used when you have a very simple processing task, - but want some control over the autogenerated widgets. If you - find yourself needing to define lots of nested functions to achieve - your functionality, maybe look at the `Container` widget! -- a `magicgui.widgets.Container` subclass. This provides lots - of flexibility and customization options while still supporting - `magicgui` widgets and convenience methods for creating widgets - from type annotations. If you want to customize your widgets and - connect callbacks, this is the best widget option for you. -- a `QWidget` subclass. This provides maximal flexibility but requires - full specification of widget layouts, callbacks, events, etc. - -References: -- Widget specification: https://napari.org/stable/plugins/guides.html?#widgets -- magicgui docs: https://pyapp-kit.github.io/magicgui/ - -Replace code below according to your needs. +This module provides a set of widgets for generating and refining synapse ground truth data in the Napari viewer. +Classes: + GTWidget: A QWidget for managing ground truth data, including image, points, and labels tools. +Functions: + _setup_spin: Helper function to configure QSpinBox and QDoubleSpinBox widgets. + _update_attr: Helper function to update attributes of a class. + _update_combos: Helper function to update QComboBox items based on Napari layers. +GTWidget: + Methods: + __init__: Initializes the GTWidget with the Napari viewer and sets up the UI. + init_ui: Sets up the main layout and calls setup methods for different toolboxes. + setup_image_box: Sets up the image tools box with controls for image resolution and channel splitting. + setup_points_box: Sets up the points tools box with controls for point scaling, conversion, and snapping. + setup_labels_box: Sets up the labels tools box with controls for label editing, merging, and conversion. + setup_save_box: Sets up the save box with controls for specifying file paths and saving Zarr files. + _path_from_raw_source: Sets the file path and name based on the raw image source. + _browse_for_path: Opens a file dialog to select a directory. + _browse_for_zarr: Opens a file dialog to select a Zarr directory. + _ensure_zarr_extension: Ensures the file name ends with ".zarr". + _update_completer: Updates the file name completer based on the selected directory. + _save_zarr: Saves the image and labels to a Zarr file. + _set_active_label: Converts active label layer to a numpy array if editable. + _convert_dask: Converts a Dask array to a numpy array. + _set_editable: Sets the labels layer to be editable. + _new_pts: Adds a new points layer to the viewer. + _convert_ch2z: Converts channel coordinates to z coordinates. + _split_channels: Splits the image channels into separate layers. + _scale_points: Scales the points coordinates based on image resolution. + _read_res: Reads the image resolution from the file metadata. + _read_tiff_voxel_size: Reads the voxel size from a TIFF file. + _rxy: Rotates the camera to the xy plane. + _auto_z: Automatically adjusts the z coordinates of points based on image intensity. + _change_z: Changes the z coordinates of selected points. + _set_max_label: Sets the maximum label value in the labels layer. + _remove_label: Removes a specified label from the labels layer. + _merge_labels: Merges two labels layers. + _labels2points: Converts labels to points based on their center of mass. + _points2labels: Converts points to labels using watershed segmentation. + _snap_to_max: Snaps points to the local maximum intensity. + _get_slices: Gets the slices for a given radius and location. + _dist_watershed_sep: Separates objects using distance transform and watershed segmentation. + """ from typing import TYPE_CHECKING @@ -46,68 +60,6 @@ if TYPE_CHECKING: import napari - -from napari_builtins.io._read import magic_imread - - -class ZarrWidget(QWidget): - def __init__(self, viewer: "napari.viewer.Viewer"): - super().__init__() - self.file_path = '' - # Data loader box - zarrbtn = QPushButton("Load zarr") - - savebox = QGroupBox('Save zarr') - - save3Dbtn = QPushButton("Save 3D only") - save23Dbtn = QPushButton("Save 2D and 3D") - - zarrbtn.clicked.connect(self._choose_zarr) - save3Dbtn.clicked.connect(lambda: self._save_zarr(threeD=True, twoD=False)) - save23Dbtn.clicked.connect(lambda: self._save_zarr(threeD=True, twoD=True)) - savebox.setLayout(QHBoxLayout()) - savebox.layout().addWidget(save3Dbtn) - savebox.layout().addWidget(save23Dbtn) - - self.layout().addWidget(zarrbtn) - - self.layout().addWidget(savebox) - - def _choose_zarr(self): - self.file_path = QFileDialog.getExistingDirectory( - self, - caption="Choose .zarr with 3d/raw and 3d/labeled inside", - ) - image = magic_imread(os.path.join(self.file_path,'3d/raw')) - labels = magic_imread(os.path.join(self.file_path,'3d/labeled')) - - self.viewer.dims.ndisplay = 3 - n = len(self.viewer.layers) - self.viewer.add_layer(image) - self.viewer.layers[n].reset_contrast_limits() - self.viewer.add_layer(labels) - self.viewer.layers[n+1].brush_size=4 - - def _save_zarr(self, threeD=True, twoD=False): - self.file_path = QFileDialog.getExistingDirectory( - self, - caption="Choose .zarr with 3d/raw and 3d/labeled inside", - ) - - def _save_in_place(self): - zarrfi = zarr.open(self.file_path) - - ## make edits - labels = self.viewer.layers[self.active_label].data - zarrfi[os.path.join('3d','labeled')] = labels - zarrfi[os.path.join('3d','labeled')].attrs['offset'] = [0,]*3 - zarrfi[os.path.join('3d','labeled')].attrs['resolution'] = [1,]*3 - - for z in range(labels.shape[0]): - zarrfi[os.path.join('2d','labeled', str(z))] = np.expand_dims(labels[z], axis=0) - zarrfi[os.path.join('2d','labeled', str(z))].attrs['offset'] = [0,]*2 - zarrfi[os.path.join('2d','labeled', str(z))].attrs['resolution'] = [1,]*2 - class GTWidget(QWidget): # your QWidget.__init__ can optionally request the napari viewer instance @@ -115,66 +67,40 @@ class GTWidget(QWidget): def __init__(self, viewer: "napari.viewer.Viewer"): super().__init__() self.viewer = viewer + self.init_ui() + + def init_ui(self): self.setLayout(QVBoxLayout()) - self.file_path = '' - self.labels_editable = False + self.setup_image_box() + self.setup_points_box() + self.setup_labels_box() + self.setup_save_box() + + def setup_image_box(self): self.xyres = 1 self.zres = 1 - # Active layers box ############################################################## - #box1 = QGroupBox('Active layers') - imgcombo = QComboBox() - labcombo = QComboBox() - ptscombo = QComboBox() - + self.active_image = QComboBox() img_refreshbtn = QPushButton("\u27F3"); img_refreshbtn.setToolTip("Refresh") - lab_refreshbtn = QPushButton("\u27F3"); lab_refreshbtn.setToolTip("Refresh") - pts_refreshbtn = QPushButton("\u27F3"); pts_refreshbtn.setToolTip("Refresh") - - self.labcheck = QCheckBox("Make labels editable") - self.labcheck.setTristate(False); self.labcheck.setCheckState(self.labels_editable) - - imgcombo.currentTextChanged.connect(lambda name: _update_attr(self, name, 'active_image')) - labcombo.currentTextChanged.connect(self._set_active_label) - ptscombo.currentTextChanged.connect(lambda name: _update_attr(self, name, 'active_points')) - - self.labcheck.stateChanged.connect(self._set_editable) - img_refreshbtn.clicked.connect(lambda: _update_combos(self, imgcombo, 'Image')) - lab_refreshbtn.clicked.connect(lambda: _update_combos(self, labcombo, 'Labels')) - pts_refreshbtn.clicked.connect(lambda: _update_combos(self, ptscombo, 'Points')) - _update_combos(self, imgcombo, 'Image', set_index=-1) - _update_combos(self, ptscombo, 'Points', set_index=-1) - _update_combos(self, labcombo, 'Labels', set_index=-1) - - # set layout: - # layers_gbox = QGridLayout() - # layers_gbox.addWidget(QLabel('image layer:'), 1, 0) ; layers_gbox.addWidget(imgcombo, 1, 1) - # layers_gbox.addWidget(img_refreshbtn, 1, 2) - # layers_gbox.addWidget(QLabel('points layer:'), 2, 0) ; layers_gbox.addWidget(ptscombo, 2, 1) - # layers_gbox.addWidget(pts_refreshbtn, 2, 2) - # - # layers_gbox.addWidget(QLabel('labels layer:'), 3, 0) ; layers_gbox.addWidget(labcombo, 3, 1) - # layers_gbox.addWidget(lab_refreshbtn, 3, 2) - # layers_gbox.addWidget(self.labcheck, 4, 0) - - # box1.setLayout(layers_gbox) + #self.active_image.currentTextChanged.connect(lambda name: _update_attr(self, name, 'active_image')) + img_refreshbtn.clicked.connect(lambda: _update_combos(self, self.active_image, 'Image')) + _update_combos(self, self.active_image, 'Image', set_index=-1) - # Image tools box ################################################################ box2 = QGroupBox('Image tools') xyresbox = QDoubleSpinBox() zresbox = QDoubleSpinBox() splitbtn = QPushButton('Split channels') - splitbtn.clicked.connect(self._split_channels); splitbtn.clicked.connect(lambda: _update_combos(self, imgcombo, 'Image')) + splitbtn.clicked.connect(self._split_channels); splitbtn.clicked.connect(lambda: _update_combos(self, active_image, 'Image')) _setup_spin(self, xyresbox, minval=0, val=self.xyres, step=0.05, attrname='xyres', dec=4, dtype=float) _setup_spin(self, zresbox, minval=0, val=self.zres, step=0.05, attrname='zres', dec=4, dtype=float) - imgcombo.currentTextChanged.connect(lambda: self._read_res()) - imgcombo.currentTextChanged.connect(lambda: xyresbox.setValue(self.xyres)) - imgcombo.currentTextChanged.connect(lambda: zresbox.setValue(self.zres)) + self.active_image.currentTextChanged.connect(lambda: self._read_res()) + self.active_image.currentTextChanged.connect(lambda: xyresbox.setValue(self.xyres)) + self.active_image.currentTextChanged.connect(lambda: zresbox.setValue(self.zres)) image_gbox = QGridLayout() - image_gbox.addWidget(QLabel('image layer:'), 0, 0) ; image_gbox.addWidget(imgcombo, 0, 1) + image_gbox.addWidget(QLabel('image layer:'), 0, 0) ; image_gbox.addWidget(self.active_image, 0, 1) image_gbox.addWidget(img_refreshbtn, 0, 2) image_gbox.addWidget(QLabel('xy res:'), 1, 0) image_gbox.addWidget(xyresbox, 1, 1) @@ -184,7 +110,15 @@ def __init__(self, viewer: "napari.viewer.Viewer"): box2.setLayout(image_gbox) + self.layout().addWidget(box2) + + def setup_points_box(self): # Point tools box ################################################################ + self.active_points = QComboBox() + pts_refreshbtn = QPushButton("\u27F3"); pts_refreshbtn.setToolTip("Refresh") + pts_refreshbtn.clicked.connect(lambda: _update_combos(self, self.active_points, 'Points')) + _update_combos(self, self.active_points, 'Points', set_index=-1) + box3 = QGroupBox('Points tools') scalepts = QPushButton('real -> pixel units') chbox = QSpinBox(); self.nch=1; @@ -195,53 +129,13 @@ def __init__(self, viewer: "napari.viewer.Viewer"): scalepts.clicked.connect(self._scale_points) points_gbox = QGridLayout() - points_gbox.addWidget(QLabel('points layer:'), 0, 0) ; points_gbox.addWidget(ptscombo, 0, 1) + points_gbox.addWidget(QLabel('points layer:'), 0, 0) ; points_gbox.addWidget(self.active_points, 0, 1) points_gbox.addWidget(pts_refreshbtn, 0, 2) points_gbox.addWidget(scalepts, 1, 0, 1, 2) points_gbox.addWidget(chbox, 2, 0) points_gbox.addWidget(ch2zbtn, 2, 1) box3.setLayout(points_gbox) - # Label tools box ################################################################ - box4 = QGroupBox('Labels tools') - self.labelbox = QSpinBox(); self.rem_label = 1 - removebtn = QPushButton("Remove label") - self.maxlab = QLabel("max label: ") - labn_refreshbtn = QPushButton("\u27F3"); labn_refreshbtn.setToolTip("Refresh") - labn_refreshbtn.clicked.connect(self._set_max_label) - labcombo.currentTextChanged.connect(self._set_max_label) - - lab2combo = QComboBox(); - lab2_refreshbtn = QPushButton("\u27F3"); lab2_refreshbtn.setToolTip("Refresh") - mlsbtn = QPushButton("Merge labels") - l2pbtn = QPushButton("Labels to points") - - lab2combo.currentTextChanged.connect(lambda name: _update_attr(self, name, 'active_label2')) - lab2_refreshbtn.clicked.connect(lambda: _update_combos(self,lab2combo, 'Labels')) - mlsbtn.clicked.connect(self._merge_labels) - mlsbtn.clicked.connect(lambda: _update_combos(self,lab2combo, 'Labels', set_index=-1)) - mlsbtn.clicked.connect(self._set_max_label) - removebtn.clicked.connect(self._remove_label) - l2pbtn.clicked.connect(self._labels2points) - l2pbtn.clicked.connect(lambda: _update_combos(self, ptscombo, 'Points')) - _setup_spin(self, self.labelbox, minval=1, maxval=1000, val=self.rem_label, attrname='rem_label') - - labels_gbox = QGridLayout() - labels_gbox.addWidget(QLabel('labels layer:'), 0, 0) ; labels_gbox.addWidget(labcombo, 0, 1) - labels_gbox.addWidget(lab_refreshbtn, 0, 2) - labels_gbox.addWidget(self.labcheck, 1, 0) - labels_gbox.addWidget(self.labelbox, 2, 0) - labels_gbox.addWidget(removebtn, 2, 1) - labels_gbox.addWidget(self.maxlab, 3, 0) - labels_gbox.addWidget(labn_refreshbtn, 3, 2) - labels_gbox.addWidget(QLabel('merge labels:'), 4, 0); - labels_gbox.addWidget(lab2combo, 4, 1); - labels_gbox.addWidget(lab2_refreshbtn, 5, 2) - labels_gbox.addWidget(mlsbtn, 5, 0, 1, 2) - labels_gbox.addWidget(l2pbtn, 6, 0, 1, 2) - - box4.setLayout(labels_gbox) - # Points2labels box ############################################################## box5 = QGroupBox('Points to labels') @@ -292,23 +186,20 @@ def __init__(self, viewer: "napari.viewer.Viewer"): wshedcombo.currentTextChanged.connect(lambda name: _update_attr(self, name, 'wshed_type')) ptsbtn.clicked.connect(self._new_pts) - ptsbtn.clicked.connect(lambda: _update_combos(self, ptscombo,'Points', set_index=-1)) + ptsbtn.clicked.connect(lambda: _update_combos(self, self.active_points,'Points', set_index=-1)) p2mbtn.clicked.connect(self._auto_z) rxybtn.clicked.connect(self._rxy) zbox.valueChanged[int].connect(self._change_z) zbox.valueChanged[int].connect(lambda: zbox.setValue(0)) snapbtn.clicked.connect(self._snap_to_max) p2lbtn.clicked.connect(self._points2labels) - p2lbtn.clicked.connect(lambda: _update_combos(self,labcombo, 'Labels')) - p2lbtn.clicked.connect(lambda: _update_combos(self,lab2combo, 'Labels', set_index=-1)) + p2lbtn.clicked.connect(lambda: _update_combos(self,self.active_label, 'Labels')) + p2lbtn.clicked.connect(lambda: _update_combos(self,self.active_merge_label, 'Labels', set_index=-1)) box5b.setVisible(False) advbtn.toggled.connect(box5b.setVisible) - _update_combos(self, imgcombo, 'Image') - _update_combos(self, labcombo, 'Labels') - _update_combos(self, ptscombo, 'Points') - _update_combos(self, lab2combo,'Labels') + _update_combos(self, self.active_points, 'Points') gbox5b = QGridLayout() gbox5b.addWidget(QLabel('threshold xy rad:'), 0, 0); gbox5b.addWidget(radxybox, 0, 1) @@ -324,8 +215,6 @@ def __init__(self, viewer: "napari.viewer.Viewer"): p2l_gbox = QGridLayout() p2l_gbox.addWidget(ptsbtn, 0, 0, 1, 2) - # gbox2.addWidget(QLabel('points layer:'), 1, 0) ; gbox2.addWidget(ptscombo, 1, 1) - # gbox2.addWidget(pts_refreshbtn, 1, 2) p2l_gbox.addWidget(rxybtn, 1, 0) p2l_gbox.addWidget(p2mbtn, 1, 1) p2l_gbox.addWidget(QLabel('manually edit z:'), 2, 0) @@ -336,7 +225,68 @@ def __init__(self, viewer: "napari.viewer.Viewer"): p2l_gbox.addWidget(box5b, 6, 0, 1, 2) box5.setLayout(p2l_gbox) + + self.layout().addWidget(box3) + self.layout().addWidget(box5) + + def setup_labels_box(self): + self.labels_editable = False + self.active_label = QComboBox() + lab_refreshbtn = QPushButton("\u27F3"); lab_refreshbtn.setToolTip("Refresh") + self.active_label.currentTextChanged.connect(self._set_active_label) + lab_refreshbtn.clicked.connect(lambda: _update_combos(self, self.active_label, 'Labels')) + _update_combos(self, self.active_label, 'Labels', set_index=-1) + + # Label tools box ################################################################ + self.labcheck = QCheckBox("Make labels editable") + self.labcheck.setTristate(False); self.labcheck.setCheckState(self.labels_editable) + self.labcheck.stateChanged.connect(self._set_editable) + + box4 = QGroupBox('Labels tools') + self.labelbox = QSpinBox(); self.rem_label = 1 + removebtn = QPushButton("Remove label") + self.maxlab = QLabel("max label: ") + labn_refreshbtn = QPushButton("\u27F3"); labn_refreshbtn.setToolTip("Refresh") + labn_refreshbtn.clicked.connect(self._set_max_label) + self.active_label.currentTextChanged.connect(self._set_max_label) + + self.active_merge_label = QComboBox(); + lab2_refreshbtn = QPushButton("\u27F3"); lab2_refreshbtn.setToolTip("Refresh") + mlsbtn = QPushButton("Merge labels") + l2pbtn = QPushButton("Labels to points") + + lab2_refreshbtn.clicked.connect(lambda: _update_combos(self,self.active_merge_label, 'Labels')) + mlsbtn.clicked.connect(self._merge_labels) + mlsbtn.clicked.connect(lambda: _update_combos(self,self.active_merge_label, 'Labels', set_index=-1)) + mlsbtn.clicked.connect(self._set_max_label) + removebtn.clicked.connect(self._remove_label) + l2pbtn.clicked.connect(self._labels2points) + l2pbtn.clicked.connect(lambda: _update_combos(self, self.active_points, 'Points')) + _setup_spin(self, self.labelbox, minval=1, maxval=1000, val=self.rem_label, attrname='rem_label') + + labels_gbox = QGridLayout() + labels_gbox.addWidget(QLabel('labels layer:'), 0, 0) ; labels_gbox.addWidget(self.active_label, 0, 1) + labels_gbox.addWidget(lab_refreshbtn, 0, 2) + labels_gbox.addWidget(self.labcheck, 1, 0) + labels_gbox.addWidget(self.labelbox, 2, 0) + labels_gbox.addWidget(removebtn, 2, 1) + labels_gbox.addWidget(self.maxlab, 3, 0) + labels_gbox.addWidget(labn_refreshbtn, 3, 2) + labels_gbox.addWidget(QLabel('merge labels:'), 4, 0); + labels_gbox.addWidget(self.active_merge_label, 4, 1); + labels_gbox.addWidget(lab2_refreshbtn, 5, 2) + labels_gbox.addWidget(mlsbtn, 5, 0, 1, 2) + labels_gbox.addWidget(l2pbtn, 6, 0, 1, 2) + box4.setLayout(labels_gbox) + + _update_combos(self, self.active_label, 'Labels') + _update_combos(self, self.active_merge_label,'Labels') + + self.layout().addWidget(box4) + + + def setup_save_box(self): box6 = QGroupBox('Save zarr') save3Dbtn = QPushButton("Save 3D only") save23Dbtn = QPushButton("Save 2D and 3D") @@ -369,14 +319,10 @@ def __init__(self, viewer: "napari.viewer.Viewer"): box6.layout().addWidget(save23Dbtn, 3, 1, 1, 1) #self.layout().addWidget(box1) - self.layout().addWidget(box2) - self.layout().addWidget(box3) - self.layout().addWidget(box5) - self.layout().addWidget(box4) self.layout().addWidget(box6) def _path_from_raw_source(self): - raw_path = self.viewer.layers[self.active_image].source.path + raw_path = self.viewer.layers[self.active_image.currentText()].source.path if raw_path.rfind('.zarr')>0: raw_path = raw_path[0:raw_path.rfind('.zarr')+5] @@ -423,8 +369,8 @@ def _save_zarr(self, threeD=True, twoD=False): zarrfi = zarr.open(fileName) - raw = self.viewer.layers[self.active_image].data - labels = self.viewer.layers[self.active_label].data + raw = self.viewer.layers[self.active_image.currentText()].data + labels = self.viewer.layers[self.active_label.currentText()].data for (name, data) in (('raw', raw), ('labeled', labels)): is_dask=True @@ -451,9 +397,8 @@ def _save_zarr(self, threeD=True, twoD=False): zarrfi[os.path.join('2d',f'{name}', str(z))].attrs['resolution'] = [1,]*2 def _set_active_label(self, name): - self.active_label = name if self.labels_editable: - self._convert_dask(name) + self._convert_dask(self.active_label.currentText()) def _convert_dask(self, layer_name): try: @@ -470,10 +415,10 @@ def _set_editable(self, state): self.labels_editable = bool(state) if self.labels_editable: try: - label = self.active_label - except AttributeError: + label = self.active_label.currentText() + except: return - self._convert_dask(self.active_label) + self._convert_dask(self.active_label.currentText()) def _new_pts(self): self.viewer.add_points( @@ -487,8 +432,8 @@ def _new_pts(self): def _convert_ch2z(self): try: - pts = self.viewer.layers[self.active_points] - except AttributeError: + pts = self.viewer.layers[self.active_points.currentText()] + except: print("Points layer not defined.") return @@ -497,8 +442,8 @@ def _convert_ch2z(self): def _split_channels(self): try: - img = self.viewer.layers[self.active_image] - except AttributeError: + img = self.viewer.layers[self.active_image.currentText()] + except: print("Points layer not defined.") return @@ -510,8 +455,8 @@ def _split_channels(self): def _scale_points(self): try: - pts = self.viewer.layers[self.active_points] - except AttributeError: + pts = self.viewer.layers[self.active_points.currentText()] + except: print("Points layer not defined.") return @@ -523,7 +468,7 @@ def _scale_points(self): def _read_res(self): try: - img = self.viewer.layers[self.active_image] + img = self.viewer.layers[self.active_image.currentText()] except: return imgpath = img.source.path @@ -568,19 +513,19 @@ def _rxy(self): def _auto_z(self): should_break=False try: - pts = self.viewer.layers[self.active_points] - except AttributeError: + pts = self.viewer.layers[self.active_points.currentText()] + except: print("Points layer not defined.") should_break=True try: - img = self.viewer.layers[self.active_image] - except AttributeError: + img = self.viewer.layers[self.active_image.currentText()] + except: print("Image layer not defined.") should_break=True if not should_break: - pts = self.viewer.layers[self.active_points] - img = self.viewer.layers[self.active_image] + pts = self.viewer.layers[self.active_points.currentText()] + img = self.viewer.layers[self.active_image.currentText()] # if len(pts.selected_data)>0: # pt_list = pts.selected_data # else: @@ -594,42 +539,42 @@ def _auto_z(self): def _change_z(self, z): should_break=False try: - self.viewer.layers[self.active_points] - except AttributeError: + self.viewer.layers[self.active_points.currentText()] + except: print("Points layer not defined.") should_break=True if not should_break: - for pt in self.viewer.layers[self.active_points].selected_data: - self.viewer.layers[self.active_points].data[pt, 0] = self.viewer.layers[self.active_points].data[pt, 0]+z + for pt in self.viewer.layers[self.active_points.currentText()].selected_data: + self.viewer.layers[self.active_points.currentText()].data[pt, 0] = self.viewer.layers[self.active_points.currentText()].data[pt, 0]+z - self.viewer.layers[self.active_points].refresh() + self.viewer.layers[self.active_points.currentText()].refresh() def _set_max_label(self): should_break=False try: - self.viewer.layers[self.active_label] + self.viewer.layers[self.active_label.currentText()] except: # AttributeError: should_break=True if not should_break: try: #check if dask - maxL = self.viewer.layers[self.active_label].data.max().compute() + maxL = self.viewer.layers[self.active_label.currentText()].data.max().compute() except: #if not dask - maxL = self.viewer.layers[self.active_label].data.max() - #maxL = self.viewer.layers[self.active_label].data.max() + maxL = self.viewer.layers[self.active_label.currentText()].data.max() + #maxL = self.viewer.layers[self.active_label.currentText()].data.max() self.labelbox.setMaximum(maxL) self.maxlab.setText("max label: "+str(maxL)) def _remove_label(self): should_break=False try: - labels = self.viewer.layers[self.active_label] - except AttributeError: + labels = self.viewer.layers[self.active_label.currentText()] + except: print("Labels layer not defined.") should_break = True if should_break: return - self._convert_dask(self.active_label) + self._convert_dask(self.active_label.currentText()) mask = labels.data == self.rem_label labels.data[mask] = 0 @@ -638,15 +583,15 @@ def _remove_label(self): def _merge_labels(self): should_break=False try: - labels = self.viewer.layers[self.active_label] - self._convert_dask(self.active_label) - except AttributeError: + labels = self.viewer.layers[self.active_label.currentText()] + self._convert_dask(self.active_label.currentText()) + except: print("Labels layer not defined.") should_break = True try: - labels2 = self.viewer.layers[self.active_label2] - self._convert_dask(self.active_label2) - except AttributeError: + labels2 = self.viewer.layers[self.active_merge_label.currentText()] + self._convert_dask(self.active_merge_label.currentText()) + except: print("Merge labels layer not defined.") should_break = True if should_break: @@ -660,26 +605,26 @@ def _merge_labels(self): labels2.data[mask] = labels2.data[mask]+const labels.data[mask] = labels2.data[mask][:] labels.refresh() - self.viewer.layers.remove(self.active_label2) - del self.active_label2 + self.viewer.layers.remove(self.active_merge_label.currentText()) + self.active_merge_label.setCurrentIndex(-1) try: - n = self.viewer.layers[self.active_points].data.shape[0] - self.viewer.layers[self.active_points].selected_data = [i for i in range(n)] - self.viewer.layers[self.active_points].remove_selected() - #self.viewer.layers.remove(self.active_points) - #del self.active_points + n = self.viewer.layers[self.active_points.currentText()].data.shape[0] + self.viewer.layers[self.active_points.currentText()].selected_data = [i for i in range(n)] + self.viewer.layers[self.active_points.currentText()].remove_selected() + #self.viewer.layers.remove(self.active_points.currentText()) + #del self.active_points.currentText() except: print("Points layer doesn't exist") def _labels2points(self): try: - labels = self.viewer.layers[self.active_label].data - except AttributeError: + labels = self.viewer.layers[self.active_label.currentText()].data + except: print("Labels layer not defined. Labels to points function exited.") return # cannot operate on dask... - self._convert_dask(self.active_label) - labels = self.viewer.layers[self.active_label].data + self._convert_dask(self.active_label.currentText()) + labels = self.viewer.layers[self.active_label.currentText()].data mask = labels>0 com = center_of_mass(mask, labels=labels, index=np.unique(labels[mask])) @@ -691,30 +636,30 @@ def _labels2points(self): out_of_slice_display=True, opacity=0.7, symbol='x', - name='points from '+self.active_label) + name='points from '+self.active_label.currentText()) def _points2labels(self): # TODO: add in auto-update of combos if points2labels function breaks due to missing layer information should_break=False try: - pts = self.viewer.layers[self.active_points].data - except AttributeError: + pts = self.viewer.layers[self.active_points.currentText()].data + except: print("Points layer not defined.") should_break=True try: - img = self.viewer.layers[self.active_image].data - except AttributeError: + img = self.viewer.layers[self.active_image.currentText()].data + except: print("Image layer not defined.") should_break=True try: - labels = self.viewer.layers[self.active_label].data + labels = self.viewer.layers[self.active_label.currentText()].data # check if dask: try: curr_n = labels.max().compute() except: curr_n = labels.max() - except AttributeError: + except: curr_n = 0 if should_break: @@ -795,18 +740,18 @@ def _points2labels(self): else: print('invalid watershed type') return - self.viewer.add_labels(outlabels, name='labels from '+self.active_points) + self.viewer.add_labels(outlabels, name='labels from '+self.active_points.currentText()) def _snap_to_max(self): should_break=False try: - pts = self.viewer.layers[self.active_points].data - except AttributeError: + pts = self.viewer.layers[self.active_points.currentText()].data + except: print("Points layer not defined.") should_break=True try: - img = self.viewer.layers[self.active_image].data - except AttributeError: + img = self.viewer.layers[self.active_image.currentText()].data + except: print("Image layer not defined.") should_break=True if self.snap_rad<=0: @@ -831,7 +776,7 @@ def _snap_to_max(self): pos = (pos + shift).astype('int') pts[count] = pos count += 1 - self.viewer.layers[self.active_points].refresh() + self.viewer.layers[self.active_points.currentText()].refresh() def _get_slices(self, rad_xy, rad_z, loc, shape): @@ -889,6 +834,7 @@ def _setup_spin(curr_class, spinbox, minval=None, maxval=None, suff=None, val=No setattr(curr_class, attrname, spinbox.value()) def _update_attr(curr_class, value, attrname): + print('setting attribute', value, attrname) setattr(curr_class, attrname, value) def _update_combos(curr_class,