Beispiel #1
0
    def __init__(self, parent, viewer_reference):
        QtWidgets.QDockWidget.__init__(self, parent)
        self.setFloating(True)
        self.setWindowTitle('Caiman detrend ΔF/F')

        self.vi = ViewerUtils(viewer_reference)

        opts = \
            {
                'quantileMin':
                    {
                        'minmax': (0, 100)
                    },
                'frames_window':
                    {
                        'minmax': (0, 1000),
                        'step': 10
                    }
            }

        self.function = Function(detrend_df_f, opts, parent=self)
        self.function.sig_set_clicked.connect(self.set_data)

        self.setWidget(self.function.widget)
Beispiel #2
0
class NusetWidget(QtWidgets.QWidget):
    sig_zlevel_changed = QtCore.pyqtSignal(int)

    def __init__(self, parent, viewer_ref):
        QtWidgets.QWidget.__init__(self, parent)

        self.vlayout = QtWidgets.QVBoxLayout(self)

        self.splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
        self.vlayout.addWidget(self.splitter)

        self.left_layout = QtWidgets.QVBoxLayout(self)

        self.left_widget = QtWidgets.QWidget(self.splitter)
        self.left_widget.setLayout(self.left_layout)

        hlayout_custom_img = QtWidgets.QHBoxLayout(self.left_widget)
        self.lineedit_custom_img_path = QtWidgets.QLineEdit(self.left_widget)
        self.lineedit_custom_img_path.setPlaceholderText(
            "Path to custom image or stack")
        self.lineedit_custom_img_path.setToolTip(
            "Use a different image or stack for segmentation, such as an image or stack of nuclei."
        )
        self.button_use_custom = QtWidgets.QPushButton(self.left_widget)
        self.button_use_custom.setMaximumWidth(50)
        self.button_use_custom.setText("Set")
        hlayout_custom_img.addWidget(self.lineedit_custom_img_path)
        hlayout_custom_img.addWidget(self.button_use_custom)
        self.left_layout.addLayout(hlayout_custom_img)

        hlayout_projection_radios = QtWidgets.QHBoxLayout(self.left_widget)
        self.radio_std = QtWidgets.QRadioButton(self.left_widget)
        self.radio_std.setText("Std. Deviation")
        self.radio_max = QtWidgets.QRadioButton(self.left_widget)
        self.radio_max.setText("Max")
        self.radio_mean = QtWidgets.QRadioButton(self.left_widget)
        self.radio_mean.setText("Mean")

        self.projection_option: str = ''

        for w in [self.radio_std, self.radio_max, self.radio_mean]:
            hlayout_projection_radios.addWidget(w)
            w.clicked.connect(self.update_projection)

        label_projections = QtWidgets.QLabel(self.left_widget)
        label_projections.setText("Choose Input Projection")
        label_projections.setStyleSheet("font-weight: bold")

        self.left_layout.addWidget(label_projections)
        self.left_layout.addLayout(hlayout_projection_radios)

        # projection image
        self.glw_raw = GraphicsLayoutWidget(self.left_widget)
        self.imgitem_raw = ImageItem()
        self.viewbox_raw = self.glw_raw.addViewBox()
        self.viewbox_raw.setAspectLocked(True)
        self.viewbox_raw.addItem(self.imgitem_raw)

        self.left_layout.addWidget(self.glw_raw)

        hlayout_preprocess = QtWidgets.QHBoxLayout(self.left_widget)

        arg_opts_preprocess = \
            {
                'img': {'ignore': True},

                'sigmoid_cutoff': {
                    'step': 10,
                    'minmax': (0, 9999.9)
                },

                'sigmoid_gain': {
                    'step': 0.01
                },
                'equalize_lower': {
                    'step': 0.01,
                    'minmax': (-1.0, 1.0)
                },
                'equalize_upper': {
                    'step': 0.01,
                    'minmax': (-1.0, 1.0)
                }
            }

        self.preprocess_controls = \
            Function(
                get_preprocess,
                arg_opts=arg_opts_preprocess,
                parent=self.left_widget
            )
        self.preprocess_controls.button_set.hide()
        self.preprocess_controls.sig_changed.connect(self.update_preprocess)
        self.preprocess_controls.set_title("Pre-process Settings")

        hlayout_preprocess.addWidget(self.preprocess_controls.widget)

        self.zslider = QtWidgets.QSlider(parent=self.left_widget,
                                         orientation=QtCore.Qt.Vertical)
        self.zslider.setInvertedAppearance(True)
        self.zslider.setSingleStep(1)
        self.zslider.valueChanged.connect(self.update_zlevel)

        label_zslider = QtWidgets.QLabel(self.left_widget)
        label_zslider.setText("z-level")

        self.spinbox_zlevel = QtWidgets.QSpinBox(self.left_widget)
        self.spinbox_zlevel.setSingleStep(1)
        self.spinbox_zlevel.valueChanged.connect(self.zslider.setValue)
        self.zslider.valueChanged.connect(self.spinbox_zlevel.setValue)

        hlayout_preprocess.addWidget(label_zslider)
        hlayout_preprocess.addWidget(self.zslider)
        hlayout_preprocess.addWidget(self.spinbox_zlevel)

        self.left_layout.addLayout(hlayout_preprocess)

        # preprocess image item
        self.glw_preprocess = GraphicsLayoutWidget(self.left_widget)
        self.imgitem_preprocess = ImageItem()
        self.viewbox_preprocess = self.glw_preprocess.addViewBox()
        self.viewbox_preprocess.setAspectLocked(True)
        self.viewbox_preprocess.addItem(self.imgitem_preprocess)

        self.left_layout.addWidget(self.glw_preprocess)

        self.splitter.addWidget(self.left_widget)

        # segmentation stuff
        self.nuset_model = Nuset()

        self.right_layout = QtWidgets.QVBoxLayout(self)

        self.right_widget = QtWidgets.QWidget(self.splitter)
        self.right_widget.setLayout(self.right_layout)

        hlayout_nuset = QtWidgets.QHBoxLayout(self.right_widget)

        arg_opts_nuset = \
            {
                'image': {'ignore': True},

                'min_score': {
                    'minmax': (0.0, 1.0),
                    'step': 0.05
                },

                'nms_threshold': {
                    'minmax': (0.0, 1.0),
                    'step': 0.05
                },

                'rescale_ratio': {
                    'minmax': (0.1, 10.0),
                    'step': 0.25,
                    'val': 1.25  # not working if set to 1.0 with pyqtgraph ImageItem for some reason
                }

            }

        self.nuset_controls = \
            Function(
                self.nuset_model.predict,
                arg_opts=arg_opts_nuset,
                parent=self.right_widget
            )

        # self.nuset_controls.button_set.hide()
        self.nuset_controls.sig_set_clicked.connect(self.update_segmentation)
        self.nuset_controls.set_title("NuSeT Parameters")
        hlayout_nuset.addWidget(self.nuset_controls.widget)

        arg_opts_postprocess = \
            {
                'img': {'ignore': True},

                'abs_obj_threshold': {
                    'minmax': (-1, 100),
                    'step': 2,
                },

                'rel_obj_threshold': {
                    'minmax': (0, 100),
                    'step': 2
                },

                'obj_connectivity': {
                    'minmax': (0, 10),
                    'step': 1
                },

                'abs_hol_threshold': {
                    'minmax': (-1, 100),
                    'step': 2,
                },

                'rel_hol_threshold': {
                    'minmax': (0, 100),
                    'step': 2
                },

                'hol_connectivity': {
                    'minmax': (0, 100),
                    'step': 1
                }
            }

        self.postprocess_controls = \
            Function(
                get_postprocess,
                arg_opts=arg_opts_postprocess,
                parent=self.right_widget
            )
        self.postprocess_controls.button_set.hide()
        self.postprocess_controls.sig_changed.connect(self.update_postprocess)
        self.postprocess_controls.set_title("Post-process Parameters")

        hlayout_nuset.addWidget(self.postprocess_controls.widget)
        self.right_layout.addLayout(hlayout_nuset)

        self.checkbox_segment_current_plane = QtWidgets.QCheckBox(
            self.nuset_controls.widget)
        self.checkbox_segment_current_plane.setText(
            "Only segment current plane")
        self.checkbox_segment_current_plane.setToolTip(
            "Performs segmentation for only the current plane, "
            "useful for trying out parameters.")
        self.checkbox_segment_current_plane.setChecked(True)
        self.nuset_controls.vlayout.addWidget(
            self.checkbox_segment_current_plane)

        self.glw_segmented = GraphicsLayoutWidget(self.right_widget)
        self.imgitem_segmented = ImageItem()
        self.imgitem_segmented_underlay = ImageItem()
        self.viewbox_segmented = self.glw_segmented.addViewBox()
        self.viewbox_segmented.setAspectLocked(True)
        self.viewbox_segmented.addItem(self.imgitem_segmented)
        self.viewbox_segmented.addItem(self.imgitem_segmented_underlay)

        # colormaps for the mask overlay plot
        cm_cyan = cm.get_cmap(cmap_cyan)
        cm_cyan._init()
        lut_cyan = (cm_cyan._lut * 255).view(np.ndarray)[128:-5]
        self.imgitem_segmented_underlay.setLookupTable(lut_cyan)

        # colormaps for the mask overlay plot
        cm_magenta = cm.get_cmap(cmap_magenta)
        cm_magenta._init()
        lut_magenta = (cm_magenta._lut * 255).view(
            np.ndarray)[:-5]  # so it displays as a mask
        self.imgitem_segmented.setLookupTable(lut_magenta)

        # allow transparency
        # self.imgitem_segmented.setCompositionMode(QtGui.QPainter.CompositionMode_Overlay)
        self.imgitem_segmented_underlay.setCompositionMode(
            QtGui.QPainter.CompositionMode_SourceOver)

        self.imgitem_segmented.setZValue(2)
        self.imgitem_segmented.setOpacity(0.5)
        self.imgitem_segmented_underlay.setZValue(1)
        self.imgitem_segmented_underlay.setOpacity(0.3)

        self.slider_underlay_opacity = QtWidgets.QSlider(QtCore.Qt.Horizontal)
        self.slider_underlay_opacity.setMinimum(0)
        self.slider_underlay_opacity.setMaximum(100)
        self.slider_underlay_opacity.setValue(30)
        self.slider_underlay_opacity.valueChanged.connect(
            lambda v: self.imgitem_segmented_underlay.setOpacity(v / 100))
        label_underlay_opacity = QtWidgets.QLabel(self.nuset_controls.widget)
        label_underlay_opacity.setText("Underlay opacity")
        self.nuset_controls.vlayout.addWidget(label_underlay_opacity)
        self.nuset_controls.vlayout.addWidget(self.slider_underlay_opacity)

        self.slider_mask_opacity = QtWidgets.QSlider(QtCore.Qt.Horizontal)
        self.slider_mask_opacity.setMinimum(0)
        self.slider_mask_opacity.setMaximum(100)
        self.slider_mask_opacity.setValue(50)
        self.slider_mask_opacity.valueChanged.connect(
            lambda v: self.imgitem_segmented.setOpacity(v / 100))
        label_segmented_opacity = QtWidgets.QLabel(self.nuset_controls.widget)
        label_segmented_opacity.setText("Segmentation opacity")
        self.nuset_controls.vlayout.addWidget(label_segmented_opacity)
        self.nuset_controls.vlayout.addWidget(self.slider_mask_opacity)

        self.combo_blend_mode = QtWidgets.QComboBox(self.nuset_controls.widget)
        self.combo_blend_mode.addItems(
            ['SourceOver', 'Overlay', 'Plus', 'Multiply'])
        self.combo_blend_mode.setCurrentIndex(0)
        self.combo_blend_mode.currentTextChanged.connect(
            lambda opt: self.imgitem_segmented.setCompositionMode(
                getattr(QtGui.QPainter, f'CompositionMode_{opt}')))
        label_blend_mode = QtWidgets.QLabel(self.nuset_controls.widget)
        label_blend_mode.setText('Blend mode:')
        self.nuset_controls.vlayout.addWidget(label_blend_mode)
        self.nuset_controls.vlayout.addWidget(self.combo_blend_mode)

        self.right_layout.addWidget(self.glw_segmented)
        self.splitter.addWidget(self.right_widget)

        self.export_widget = ExportWidget(self)

        self.imgs_projected: List[np.ndarray] = []
        self.imgs_preprocessed: List[np.ndarray] = []
        self.imgs_segmented: List[np.ndarray] = []
        self.imgs_postprocessed: List[np.ndarray] = []

        self.input_img: np.ndarray = np.empty(0)
        self.zlevel = 0
        self.z_max: int = 0

        self.process_pool = Pool(cpu_count())

        self.error_label = QtWidgets.QLabel(self)
        self.error_label.setMaximumHeight(20)
        self.error_label.setStyleSheet("font-weight: bold; color: red")
        self.vlayout.addWidget(self.error_label)

        self.projection_option = ''
        self.params_final = None

        if viewer_ref is None:
            logger.info("Assuming testing mode")
        else:
            self.vi = ViewerUtils(viewer_ref)
            self.vi.viewer.sig_workEnv_changed.connect(self.set_input)
            self.set_input(self.vi.viewer.workEnv)

    @use_open_file_dialog('Open image file', None, ['*.tiff', '*.tif'])
    @present_exceptions('Error', 'Error loading custom input image')
    def set_custom_input(self, path, *args):
        self.clear_widget()
        img = tifffile.imread(path)
        self._set_input_image(img.T)

    def set_input(self, workEnv: ViewerWorkEnv):
        self.clear_widget()

        try:
            img = workEnv.imgdata._seq
        except:
            return

        self._set_input_image(img)

    def _set_input_image(self, img: np.ndarray):
        self.input_img = img

        if self.input_img.ndim == 4:
            self.z_max = self.input_img.shape[3] - 1
        else:
            self.z_max = 0

        self.zslider.valueChanged.disconnect(self.update_zlevel)
        self.zslider.setValue(0)
        self.zslider.setMaximum(self.z_max)
        self.spinbox_zlevel.setMaximum(self.z_max)
        self.zslider.valueChanged.connect(self.update_zlevel)

    def update_zlevel(self, z: int):
        self.zlevel = z
        self.sig_zlevel_changed.emit(z)

        for imgitem, imglist in zip([
                self.imgitem_raw, self.imgitem_preprocess,
                self.imgitem_segmented_underlay, self.imgitem_segmented
        ], [
                self.imgs_projected, self.imgs_preprocessed,
                self.imgs_preprocessed, self.imgs_postprocessed
        ]):
            if imglist:  # set if the list is not empty
                if imglist[z].size > 0:
                    imgitem.setImage(imglist[z])

    def update_projection(self):
        if not self.input_img.size > 0:
            self.error_label.setText("No input image")
            return

        if self.radio_std.isChecked():
            opt = 'std'
        elif self.radio_max.isChecked():
            opt = 'max'
        elif self.radio_mean.isChecked():
            opt = 'mean'

        if self.projection_option == opt:
            return

        self.projection_option = opt

        func = getattr(np, f'nan{opt}')

        logger.info("Updating Projection(s)")
        if self.input_img.ndim == 4:
            self.imgs_projected = [
                func(self.input_img[:, :, :, z], axis=2)
                for z in tqdm(range(self.z_max + 1))
            ]
        else:
            self.imgs_projected = [func(self.input_img, axis=2)]

        self.imgitem_raw.setImage(self.imgs_projected[self.zlevel])
        self.error_label.clear()

    def update_preprocess(self, params):
        if not self.imgs_projected:
            self.error_label.setText("Projection Image is Empty")
            return

        logger.info("Preprocessing Image(s)")

        # self.image_preprocesses = [
        #     get_preprocess(p, **params) for p in tqdm(self.image_projections)
        # ]

        kwargs = [{'img': img, **params} for img in self.imgs_projected]

        self.imgs_preprocessed = self.process_pool.map(wrap_preprocess, kwargs)

        self.imgitem_preprocess.setImage(self.imgs_preprocessed[self.zlevel])
        self.imgitem_segmented_underlay.setImage(
            self.imgs_preprocessed[self.zlevel])
        self.error_label.clear()

    def update_segmentation(self, params):
        if not self.imgs_preprocessed:
            self.error_label.setText("Preprocess Image is Empty")
            return

        logger.info("Segmenting Image(s)")
        if not self.checkbox_segment_current_plane.isChecked():
            self.imgs_segmented = [
                self.nuset_model.predict(img, **params)
                for img in tqdm(self.imgs_preprocessed)
            ]
        else:
            self.imgs_segmented = [np.empty(0) for i in range(self.z_max + 1)]

            self.imgs_segmented[self.zlevel] = self.nuset_model.predict(
                self.imgs_preprocessed[self.zlevel], **params)

        # postprocess funciton will just return the segmented img if do_postprocess is False
        self.update_postprocess(self.postprocess_controls.get_data())

        self.params_final = \
            {
                'method': 'NuSeT',
                'projection_option': self.projection_option,
                **self.preprocess_controls.get_data(),
                **self.nuset_controls.get_data(),
                **self.postprocess_controls.get_data(),
            }

        self.error_label.clear()

    def update_postprocess(self, params):
        if not self.imgs_segmented:
            self.error_label.setText("Segmented Image is Empty")
            return

        logger.info("Postprocessing Image(s)")
        self.imgs_postprocessed = [
            get_postprocess(img, **params) for img in tqdm(self.imgs_segmented)
        ]

        self.imgitem_segmented.setImage(self.imgs_postprocessed[self.zlevel])
        self.error_label.clear()

    def clear_widget(self):
        self.imgs_projected.clear()
        self.imgs_preprocessed.clear()
        self.imgs_segmented.clear()
        self.imgs_postprocessed.clear()

        self.imgitem_raw.clear()
        self.imgitem_preprocess.clear()
        self.imgitem_segmented.clear()
        self.imgitem_segmented_underlay.clear()

        self.radio_std.setChecked(False)
        self.radio_max.setChecked(False)
        self.radio_mean.setChecked(False)

        self.projection_option = ''
Beispiel #3
0
    def __init__(self, parent, viewer_ref):
        QtWidgets.QWidget.__init__(self, parent)

        self.vlayout = QtWidgets.QVBoxLayout(self)

        self.splitter = QtWidgets.QSplitter(QtCore.Qt.Horizontal)
        self.vlayout.addWidget(self.splitter)

        self.left_layout = QtWidgets.QVBoxLayout(self)

        self.left_widget = QtWidgets.QWidget(self.splitter)
        self.left_widget.setLayout(self.left_layout)

        hlayout_custom_img = QtWidgets.QHBoxLayout(self.left_widget)
        self.lineedit_custom_img_path = QtWidgets.QLineEdit(self.left_widget)
        self.lineedit_custom_img_path.setPlaceholderText(
            "Path to custom image or stack")
        self.lineedit_custom_img_path.setToolTip(
            "Use a different image or stack for segmentation, such as an image or stack of nuclei."
        )
        self.button_use_custom = QtWidgets.QPushButton(self.left_widget)
        self.button_use_custom.setMaximumWidth(50)
        self.button_use_custom.setText("Set")
        hlayout_custom_img.addWidget(self.lineedit_custom_img_path)
        hlayout_custom_img.addWidget(self.button_use_custom)
        self.left_layout.addLayout(hlayout_custom_img)

        hlayout_projection_radios = QtWidgets.QHBoxLayout(self.left_widget)
        self.radio_std = QtWidgets.QRadioButton(self.left_widget)
        self.radio_std.setText("Std. Deviation")
        self.radio_max = QtWidgets.QRadioButton(self.left_widget)
        self.radio_max.setText("Max")
        self.radio_mean = QtWidgets.QRadioButton(self.left_widget)
        self.radio_mean.setText("Mean")

        self.projection_option: str = ''

        for w in [self.radio_std, self.radio_max, self.radio_mean]:
            hlayout_projection_radios.addWidget(w)
            w.clicked.connect(self.update_projection)

        label_projections = QtWidgets.QLabel(self.left_widget)
        label_projections.setText("Choose Input Projection")
        label_projections.setStyleSheet("font-weight: bold")

        self.left_layout.addWidget(label_projections)
        self.left_layout.addLayout(hlayout_projection_radios)

        # projection image
        self.glw_raw = GraphicsLayoutWidget(self.left_widget)
        self.imgitem_raw = ImageItem()
        self.viewbox_raw = self.glw_raw.addViewBox()
        self.viewbox_raw.setAspectLocked(True)
        self.viewbox_raw.addItem(self.imgitem_raw)

        self.left_layout.addWidget(self.glw_raw)

        hlayout_preprocess = QtWidgets.QHBoxLayout(self.left_widget)

        arg_opts_preprocess = \
            {
                'img': {'ignore': True},

                'sigmoid_cutoff': {
                    'step': 10,
                    'minmax': (0, 9999.9)
                },

                'sigmoid_gain': {
                    'step': 0.01
                },
                'equalize_lower': {
                    'step': 0.01,
                    'minmax': (-1.0, 1.0)
                },
                'equalize_upper': {
                    'step': 0.01,
                    'minmax': (-1.0, 1.0)
                }
            }

        self.preprocess_controls = \
            Function(
                get_preprocess,
                arg_opts=arg_opts_preprocess,
                parent=self.left_widget
            )
        self.preprocess_controls.button_set.hide()
        self.preprocess_controls.sig_changed.connect(self.update_preprocess)
        self.preprocess_controls.set_title("Pre-process Settings")

        hlayout_preprocess.addWidget(self.preprocess_controls.widget)

        self.zslider = QtWidgets.QSlider(parent=self.left_widget,
                                         orientation=QtCore.Qt.Vertical)
        self.zslider.setInvertedAppearance(True)
        self.zslider.setSingleStep(1)
        self.zslider.valueChanged.connect(self.update_zlevel)

        label_zslider = QtWidgets.QLabel(self.left_widget)
        label_zslider.setText("z-level")

        self.spinbox_zlevel = QtWidgets.QSpinBox(self.left_widget)
        self.spinbox_zlevel.setSingleStep(1)
        self.spinbox_zlevel.valueChanged.connect(self.zslider.setValue)
        self.zslider.valueChanged.connect(self.spinbox_zlevel.setValue)

        hlayout_preprocess.addWidget(label_zslider)
        hlayout_preprocess.addWidget(self.zslider)
        hlayout_preprocess.addWidget(self.spinbox_zlevel)

        self.left_layout.addLayout(hlayout_preprocess)

        # preprocess image item
        self.glw_preprocess = GraphicsLayoutWidget(self.left_widget)
        self.imgitem_preprocess = ImageItem()
        self.viewbox_preprocess = self.glw_preprocess.addViewBox()
        self.viewbox_preprocess.setAspectLocked(True)
        self.viewbox_preprocess.addItem(self.imgitem_preprocess)

        self.left_layout.addWidget(self.glw_preprocess)

        self.splitter.addWidget(self.left_widget)

        # segmentation stuff
        self.nuset_model = Nuset()

        self.right_layout = QtWidgets.QVBoxLayout(self)

        self.right_widget = QtWidgets.QWidget(self.splitter)
        self.right_widget.setLayout(self.right_layout)

        hlayout_nuset = QtWidgets.QHBoxLayout(self.right_widget)

        arg_opts_nuset = \
            {
                'image': {'ignore': True},

                'min_score': {
                    'minmax': (0.0, 1.0),
                    'step': 0.05
                },

                'nms_threshold': {
                    'minmax': (0.0, 1.0),
                    'step': 0.05
                },

                'rescale_ratio': {
                    'minmax': (0.1, 10.0),
                    'step': 0.25,
                    'val': 1.25  # not working if set to 1.0 with pyqtgraph ImageItem for some reason
                }

            }

        self.nuset_controls = \
            Function(
                self.nuset_model.predict,
                arg_opts=arg_opts_nuset,
                parent=self.right_widget
            )

        # self.nuset_controls.button_set.hide()
        self.nuset_controls.sig_set_clicked.connect(self.update_segmentation)
        self.nuset_controls.set_title("NuSeT Parameters")
        hlayout_nuset.addWidget(self.nuset_controls.widget)

        arg_opts_postprocess = \
            {
                'img': {'ignore': True},

                'abs_obj_threshold': {
                    'minmax': (-1, 100),
                    'step': 2,
                },

                'rel_obj_threshold': {
                    'minmax': (0, 100),
                    'step': 2
                },

                'obj_connectivity': {
                    'minmax': (0, 10),
                    'step': 1
                },

                'abs_hol_threshold': {
                    'minmax': (-1, 100),
                    'step': 2,
                },

                'rel_hol_threshold': {
                    'minmax': (0, 100),
                    'step': 2
                },

                'hol_connectivity': {
                    'minmax': (0, 100),
                    'step': 1
                }
            }

        self.postprocess_controls = \
            Function(
                get_postprocess,
                arg_opts=arg_opts_postprocess,
                parent=self.right_widget
            )
        self.postprocess_controls.button_set.hide()
        self.postprocess_controls.sig_changed.connect(self.update_postprocess)
        self.postprocess_controls.set_title("Post-process Parameters")

        hlayout_nuset.addWidget(self.postprocess_controls.widget)
        self.right_layout.addLayout(hlayout_nuset)

        self.checkbox_segment_current_plane = QtWidgets.QCheckBox(
            self.nuset_controls.widget)
        self.checkbox_segment_current_plane.setText(
            "Only segment current plane")
        self.checkbox_segment_current_plane.setToolTip(
            "Performs segmentation for only the current plane, "
            "useful for trying out parameters.")
        self.checkbox_segment_current_plane.setChecked(True)
        self.nuset_controls.vlayout.addWidget(
            self.checkbox_segment_current_plane)

        self.glw_segmented = GraphicsLayoutWidget(self.right_widget)
        self.imgitem_segmented = ImageItem()
        self.imgitem_segmented_underlay = ImageItem()
        self.viewbox_segmented = self.glw_segmented.addViewBox()
        self.viewbox_segmented.setAspectLocked(True)
        self.viewbox_segmented.addItem(self.imgitem_segmented)
        self.viewbox_segmented.addItem(self.imgitem_segmented_underlay)

        # colormaps for the mask overlay plot
        cm_cyan = cm.get_cmap(cmap_cyan)
        cm_cyan._init()
        lut_cyan = (cm_cyan._lut * 255).view(np.ndarray)[128:-5]
        self.imgitem_segmented_underlay.setLookupTable(lut_cyan)

        # colormaps for the mask overlay plot
        cm_magenta = cm.get_cmap(cmap_magenta)
        cm_magenta._init()
        lut_magenta = (cm_magenta._lut * 255).view(
            np.ndarray)[:-5]  # so it displays as a mask
        self.imgitem_segmented.setLookupTable(lut_magenta)

        # allow transparency
        # self.imgitem_segmented.setCompositionMode(QtGui.QPainter.CompositionMode_Overlay)
        self.imgitem_segmented_underlay.setCompositionMode(
            QtGui.QPainter.CompositionMode_SourceOver)

        self.imgitem_segmented.setZValue(2)
        self.imgitem_segmented.setOpacity(0.5)
        self.imgitem_segmented_underlay.setZValue(1)
        self.imgitem_segmented_underlay.setOpacity(0.3)

        self.slider_underlay_opacity = QtWidgets.QSlider(QtCore.Qt.Horizontal)
        self.slider_underlay_opacity.setMinimum(0)
        self.slider_underlay_opacity.setMaximum(100)
        self.slider_underlay_opacity.setValue(30)
        self.slider_underlay_opacity.valueChanged.connect(
            lambda v: self.imgitem_segmented_underlay.setOpacity(v / 100))
        label_underlay_opacity = QtWidgets.QLabel(self.nuset_controls.widget)
        label_underlay_opacity.setText("Underlay opacity")
        self.nuset_controls.vlayout.addWidget(label_underlay_opacity)
        self.nuset_controls.vlayout.addWidget(self.slider_underlay_opacity)

        self.slider_mask_opacity = QtWidgets.QSlider(QtCore.Qt.Horizontal)
        self.slider_mask_opacity.setMinimum(0)
        self.slider_mask_opacity.setMaximum(100)
        self.slider_mask_opacity.setValue(50)
        self.slider_mask_opacity.valueChanged.connect(
            lambda v: self.imgitem_segmented.setOpacity(v / 100))
        label_segmented_opacity = QtWidgets.QLabel(self.nuset_controls.widget)
        label_segmented_opacity.setText("Segmentation opacity")
        self.nuset_controls.vlayout.addWidget(label_segmented_opacity)
        self.nuset_controls.vlayout.addWidget(self.slider_mask_opacity)

        self.combo_blend_mode = QtWidgets.QComboBox(self.nuset_controls.widget)
        self.combo_blend_mode.addItems(
            ['SourceOver', 'Overlay', 'Plus', 'Multiply'])
        self.combo_blend_mode.setCurrentIndex(0)
        self.combo_blend_mode.currentTextChanged.connect(
            lambda opt: self.imgitem_segmented.setCompositionMode(
                getattr(QtGui.QPainter, f'CompositionMode_{opt}')))
        label_blend_mode = QtWidgets.QLabel(self.nuset_controls.widget)
        label_blend_mode.setText('Blend mode:')
        self.nuset_controls.vlayout.addWidget(label_blend_mode)
        self.nuset_controls.vlayout.addWidget(self.combo_blend_mode)

        self.right_layout.addWidget(self.glw_segmented)
        self.splitter.addWidget(self.right_widget)

        self.export_widget = ExportWidget(self)

        self.imgs_projected: List[np.ndarray] = []
        self.imgs_preprocessed: List[np.ndarray] = []
        self.imgs_segmented: List[np.ndarray] = []
        self.imgs_postprocessed: List[np.ndarray] = []

        self.input_img: np.ndarray = np.empty(0)
        self.zlevel = 0
        self.z_max: int = 0

        self.process_pool = Pool(cpu_count())

        self.error_label = QtWidgets.QLabel(self)
        self.error_label.setMaximumHeight(20)
        self.error_label.setStyleSheet("font-weight: bold; color: red")
        self.vlayout.addWidget(self.error_label)

        self.projection_option = ''
        self.params_final = None

        if viewer_ref is None:
            logger.info("Assuming testing mode")
        else:
            self.vi = ViewerUtils(viewer_ref)
            self.vi.viewer.sig_workEnv_changed.connect(self.set_input)
            self.set_input(self.vi.viewer.workEnv)
Beispiel #4
0
from pyqtgraph.console import ConsoleWidget


def f(a: int = 1, b: float = 3.14, c: str = 'yay', d: bool = True):
    pass


if __name__ == '__main__':
    app = QtWidgets.QApplication([])

    opts = \
        {
            'b':
                {
                    'use_slider': True,
                    'minmax': (0, 100),
                    'step': 1,
                    'suffix': '%',
                    'typ': int,
                    'tooltip': 'yay tooltips'
                }
        }

    func = Function(f, arg_opts=opts)
    func.widget.show()

    console = ConsoleWidget(parent=func.widget, namespace={'this': func})
    func.vlayout.addWidget(console)

    app.exec()