synapse_net.tools.postprocessing_widget

 1import napari
 2import napari.layers
 3import napari.viewer
 4
 5import numpy as np
 6
 7from napari.utils.notifications import show_info
 8from qtpy.QtWidgets import QVBoxLayout, QPushButton
 9from skimage.measure import regionprops
10from skimage.segmentation import find_boundaries
11
12from .base_widget import BaseWidget
13
14
15class PostprocessingWidget(BaseWidget):
16    def __init__(self):
17        super().__init__()
18
19        self.viewer = napari.current_viewer()
20        layout = QVBoxLayout()
21
22        # Create the dropdown to select the segmentation to post-process.
23        self.segmentation_selector_name = "Segmentation"
24        self.segmentation_selector_widget = self._create_layer_selector(
25            self.segmentation_selector_name, layer_type="Labels"
26        )
27        layout.addWidget(self.segmentation_selector_widget)
28
29        # Create dropdown to select the mask for filtering / intersection.
30        self.mask_selector_name = "Mask"
31        self.mask_selector_widget = self._create_layer_selector(self.mask_selector_name, layer_type="Labels")
32        layout.addWidget(self.mask_selector_widget)
33
34        # Create input for label id in the mask.
35        self.mask_id_param, _ = self._add_int_param(
36            "mask_id", 0, min_val=0, max_val=1000, layout=layout, title="Mask ID"
37        )
38
39        # Create text field to choose the name of the output layer.
40        self.output_layer_param, _ = self._add_string_param("output_layer", "", title="Output Layer", layout=layout)
41
42        # First postprocessing option: Filter with mask.
43        self.button1 = QPushButton("Filter")
44        self.button1.clicked.connect(self.on_filter)
45        layout.addWidget(self.button1)
46
47        # Second postprocessing option: intersect with boundary of the mask.
48        self.button2 = QPushButton("Intersect with Boundary")
49        self.button2.clicked.connect(self.on_intersect)
50        layout.addWidget(self.button2)
51
52        # Add the widgets to the layout.
53        self.setLayout(layout)
54
55    def _write_pp(self, segmentation):
56        layer_name = self.output_layer_param.text()
57        if layer_name in self.viewer.layers:
58            self.viewer.layers[layer_name].data = segmentation
59        else:
60            self.viewer.add_labels(segmentation, name=layer_name)
61
62    def _conditions_met(self):
63        if self.output_layer_param.text() == "":
64            show_info("Please choose an output layer.")
65            return False
66        return True
67
68    def _get_segmentation_and_mask(self):
69        segmentation = self._get_layer_selector_data(self.segmentation_selector_name).copy()
70        mask = self._get_layer_selector_data(self.mask_selector_name)
71        mask_id = self.mask_id_param.value()
72        if mask_id != 0:
73            mask = (mask == mask_id).astype(mask.dtype)
74        return segmentation, mask
75
76    def on_filter(self):
77        if not self._conditions_met():
78            return
79        segmentation, mask = self._get_segmentation_and_mask()
80        props = regionprops(segmentation, mask)
81        filter_ids = [prop.label for prop in props if prop.max_intensity == 0]
82        segmentation[np.isin(segmentation, filter_ids)] = 0
83        self._write_pp(segmentation)
84
85    def on_intersect(self):
86        if not self._conditions_met():
87            return
88        segmentation, mask = self._get_segmentation_and_mask()
89        boundary = find_boundaries(mask)
90        segmentation = np.logical_and(segmentation > 0, boundary).astype(segmentation.dtype)
91        self._write_pp(segmentation)
class PostprocessingWidget(synapse_net.tools.base_widget.BaseWidget):
16class PostprocessingWidget(BaseWidget):
17    def __init__(self):
18        super().__init__()
19
20        self.viewer = napari.current_viewer()
21        layout = QVBoxLayout()
22
23        # Create the dropdown to select the segmentation to post-process.
24        self.segmentation_selector_name = "Segmentation"
25        self.segmentation_selector_widget = self._create_layer_selector(
26            self.segmentation_selector_name, layer_type="Labels"
27        )
28        layout.addWidget(self.segmentation_selector_widget)
29
30        # Create dropdown to select the mask for filtering / intersection.
31        self.mask_selector_name = "Mask"
32        self.mask_selector_widget = self._create_layer_selector(self.mask_selector_name, layer_type="Labels")
33        layout.addWidget(self.mask_selector_widget)
34
35        # Create input for label id in the mask.
36        self.mask_id_param, _ = self._add_int_param(
37            "mask_id", 0, min_val=0, max_val=1000, layout=layout, title="Mask ID"
38        )
39
40        # Create text field to choose the name of the output layer.
41        self.output_layer_param, _ = self._add_string_param("output_layer", "", title="Output Layer", layout=layout)
42
43        # First postprocessing option: Filter with mask.
44        self.button1 = QPushButton("Filter")
45        self.button1.clicked.connect(self.on_filter)
46        layout.addWidget(self.button1)
47
48        # Second postprocessing option: intersect with boundary of the mask.
49        self.button2 = QPushButton("Intersect with Boundary")
50        self.button2.clicked.connect(self.on_intersect)
51        layout.addWidget(self.button2)
52
53        # Add the widgets to the layout.
54        self.setLayout(layout)
55
56    def _write_pp(self, segmentation):
57        layer_name = self.output_layer_param.text()
58        if layer_name in self.viewer.layers:
59            self.viewer.layers[layer_name].data = segmentation
60        else:
61            self.viewer.add_labels(segmentation, name=layer_name)
62
63    def _conditions_met(self):
64        if self.output_layer_param.text() == "":
65            show_info("Please choose an output layer.")
66            return False
67        return True
68
69    def _get_segmentation_and_mask(self):
70        segmentation = self._get_layer_selector_data(self.segmentation_selector_name).copy()
71        mask = self._get_layer_selector_data(self.mask_selector_name)
72        mask_id = self.mask_id_param.value()
73        if mask_id != 0:
74            mask = (mask == mask_id).astype(mask.dtype)
75        return segmentation, mask
76
77    def on_filter(self):
78        if not self._conditions_met():
79            return
80        segmentation, mask = self._get_segmentation_and_mask()
81        props = regionprops(segmentation, mask)
82        filter_ids = [prop.label for prop in props if prop.max_intensity == 0]
83        segmentation[np.isin(segmentation, filter_ids)] = 0
84        self._write_pp(segmentation)
85
86    def on_intersect(self):
87        if not self._conditions_met():
88            return
89        segmentation, mask = self._get_segmentation_and_mask()
90        boundary = find_boundaries(mask)
91        segmentation = np.logical_and(segmentation > 0, boundary).astype(segmentation.dtype)
92        self._write_pp(segmentation)

QWidget(parent: typing.Optional[QWidget] = None, flags: Union[Qt.WindowFlags, Qt.WindowType] = Qt.WindowFlags())

viewer
segmentation_selector_name
segmentation_selector_widget
mask_selector_name
mask_selector_widget
button1
button2
def on_filter(self):
77    def on_filter(self):
78        if not self._conditions_met():
79            return
80        segmentation, mask = self._get_segmentation_and_mask()
81        props = regionprops(segmentation, mask)
82        filter_ids = [prop.label for prop in props if prop.max_intensity == 0]
83        segmentation[np.isin(segmentation, filter_ids)] = 0
84        self._write_pp(segmentation)
def on_intersect(self):
86    def on_intersect(self):
87        if not self._conditions_met():
88            return
89        segmentation, mask = self._get_segmentation_and_mask()
90        boundary = find_boundaries(mask)
91        segmentation = np.logical_and(segmentation > 0, boundary).astype(segmentation.dtype)
92        self._write_pp(segmentation)