예제 #1
0
class MainWindow(QMainWindow):
    def __init__(self, title):
        super().__init__()
        self.setWindowTitle(title)
        self.lib_path = ""
        self.final_title = ""
        analysis_icon = QIcon(os.path.join(icons_dir, "icon.png"))
        stack_icon = QIcon(os.path.join(icons_dir, "icon_stack.png"))
        self.analysis_button = QToolButton(self)
        self.analysis_button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        self.analysis_button.setIcon(analysis_icon)
        # TODO use more general solution for text wrapping
        self.analysis_button.setText(ANALYSIS_NAME.replace(" ", "\n"))
        self.analysis_button.setIconSize(QSize(100, 100))
        self.mask_button = QToolButton(self)
        self.mask_button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        self.mask_button.setIcon(stack_icon)
        self.mask_button.setText(MASK_NAME.replace(" ", "\n"))
        self.mask_button.setIconSize(QSize(100, 100))
        self.analysis_button.clicked.connect(self.launch_analysis)
        self.mask_button.clicked.connect(self.launch_mask)
        self.progress = QProgressBar()
        self.progress.setHidden(True)
        layout = QGridLayout()
        layout.addWidget(self.progress, 0, 0, 1, 2)
        layout.addWidget(self.analysis_button, 1, 1)
        layout.addWidget(self.mask_button, 1, 0)
        widget = QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)
        self.setWindowIcon(analysis_icon)
        self.prepare = None
        self.wind = None
        self._update_theme()

    def _update_theme(self):
        napari_settings = napari_get_settings(state_store.save_folder)
        with warnings.catch_warnings():
            warnings.simplefilter("ignore", FutureWarning)
            theme = get_theme(napari_settings.appearance.theme)
        # TODO understand qss overwrite mechanism
        self.setStyleSheet(napari_template(get_stylesheet(), **theme))

    def _launch_begin(self):
        self.progress.setVisible(True)
        self.progress.setRange(0, 0)
        self.analysis_button.setDisabled(True)
        self.mask_button.setDisabled(True)
        import_config()

    def launch_analysis(self):
        self._launch_begin()
        self._launch_analysis()
        self.prepare.start()

    def _launch_analysis(self):
        self.lib_path = "PartSeg._roi_analysis.main_window"
        self.final_title = f"{APP_NAME} {ANALYSIS_NAME}"
        self.prepare = Prepare(self.lib_path)
        self.prepare.finished.connect(self.launch)

    def launch_mask(self):
        self._launch_begin()
        self._launch_mask()
        self.prepare.start()

    def _launch_mask(self):
        self.lib_path = "PartSeg._roi_mask.main_window"
        self.final_title = f"{APP_NAME} {MASK_NAME}"
        self.prepare = Prepare(self.lib_path)
        self.prepare.finished.connect(self.launch)

    def window_shown(self):
        self.close()

    def launch(self):
        if self.prepare.result is None:
            self.close()
            return
        if self.prepare.errors:
            errors_message = QMessageBox()
            errors_message.setText("There are errors during start")
            errors_message.setInformativeText(
                "During load saved state some of data could not be load properly\n"
                "The files has prepared backup copies in  state directory (Help > State directory)"
            )
            errors_message.setStandardButtons(QMessageBox.Ok)
            text = "\n".join("File: " + x[0] + "\n" + str(x[1])
                             for x in self.prepare.errors)

            errors_message.setDetailedText(text)
            errors_message.exec_()
        wind = self.prepare.result(title=self.final_title,
                                   signal_fun=self.window_shown)
        wind.show()
        self.wind = wind
예제 #2
0
class MainWindow(QMainWindow):
    def __init__(self, title):
        super().__init__()
        self.setWindowTitle(title)
        self.lib_path = ""
        self.final_title = ""
        analysis_icon = QIcon(os.path.join(icons_dir, "icon.png"))
        stack_icon = QIcon(os.path.join(icons_dir, "icon_stack.png"))
        self.analysis_button = QToolButton(self)
        self.analysis_button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        self.analysis_button.setIcon(analysis_icon)
        # TODO use more general solution for text wrapping
        self.analysis_button.setText(SEGMENTATION_NAME.replace(" ", "\n"))
        self.analysis_button.setIconSize(QSize(100, 100))
        self.mask_button = QToolButton(self)
        self.mask_button.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        self.mask_button.setIcon(stack_icon)
        self.mask_button.setText(MASK_NAME.replace(" ", "\n"))
        self.mask_button.setIconSize(QSize(100, 100))
        self.analysis_button.clicked.connect(self.launch_analysis)
        self.mask_button.clicked.connect(self.launch_mask)
        self.progress = QProgressBar()
        self.progress.setHidden(True)
        layout = QGridLayout()
        layout.addWidget(self.progress, 0, 0, 1, 2)
        layout.addWidget(self.analysis_button, 1, 1)
        layout.addWidget(self.mask_button, 1, 0)
        widget = QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)
        self.setWindowIcon(analysis_icon)
        self.prepare = None
        self.wind = None

    def _launch_begin(self):
        self.progress.setVisible(True)
        self.progress.setRange(0, 0)
        self.analysis_button.setDisabled(True)
        self.mask_button.setDisabled(True)
        import_config()

    def launch_analysis(self):
        self._launch_begin()
        self.lib_path = "PartSeg.segmentation_analysis.main_window"
        self.final_title = "PartSeg Segmentation Analysis"
        self.prepare = Prepare(self.lib_path)
        self.prepare.finished.connect(self.launch)
        self.prepare.start()

    def launch_mask(self):
        self._launch_begin()
        self.lib_path = "PartSeg.segmentation_mask.main_window"
        self.final_title = "PartSeg Mask Segmentation"
        self.prepare = Prepare(self.lib_path)
        self.prepare.finished.connect(self.launch)
        self.prepare.start()

    def window_shown(self):
        self.close()

    def launch(self):
        if self.prepare.result is None:
            self.close()
            return
        if self.prepare.errors:
            errors_message = QMessageBox()
            errors_message.setText("There are errors during start")
            errors_message.setInformativeText(
                "During load saved state some of data could not be load properly\n"
                "The files has prepared backup copies in  state directory (Help > State directory)"
            )
            errors_message.setStandardButtons(QMessageBox.Ok)
            text = "\n".join(["File: " + x[0] + "\n" + str(x[1]) for x in self.prepare.errors])
            errors_message.setDetailedText(text)
            errors_message.exec()
        wind = self.prepare.result(title=self.final_title, signal_fun=self.window_shown)
        wind.show()
        self.wind = wind
예제 #3
0
class AlgorithmOptions(QWidget):
    def __init__(self, settings: StackSettings, image_view: StackImageView):
        super().__init__()
        self.settings = settings
        self.view_name = image_view.name
        self.show_result = QEnumComboBox(
            enum_class=LabelEnum)  # QCheckBox("Show result")
        self._set_show_label_from_settings()
        self.opacity = QDoubleSpinBox()
        self.opacity.setRange(0, 1)
        self.opacity.setSingleStep(0.1)
        self._set_opacity_from_settings()
        self.only_borders = QCheckBox("Only borders")
        self._set_border_mode_from_settings()
        self.borders_thick = QSpinBox()
        self.borders_thick.setRange(1, 25)
        self.borders_thick.setSingleStep(1)
        self._set_border_thick_from_settings()
        self.execute_in_background_btn = QPushButton("Execute in background")
        self.execute_in_background_btn.setToolTip(
            "Run calculation in background. Put result in multiple files panel"
        )
        self.execute_btn = QPushButton("Execute")
        self.execute_btn.setStyleSheet("QPushButton{font-weight: bold;}")
        self.execute_all_btn = QPushButton("Execute all")
        self.execute_all_btn.setToolTip(
            "Execute in batch mode segmentation with current parameter. File list need to be specified in image tab."
        )
        self.execute_all_btn.setDisabled(True)
        self.save_parameters_btn = QPushButton("Save parameters")
        self.block_execute_all_btn = False
        self.algorithm_choose_widget = AlgorithmChoose(settings,
                                                       mask_algorithm_dict)
        self.algorithm_choose_widget.result.connect(self.execution_result_set)
        self.algorithm_choose_widget.finished.connect(self.execution_finished)
        self.algorithm_choose_widget.progress_signal.connect(
            self.progress_info)

        # self.stack_layout = QStackedLayout()
        self.keep_chosen_components_chk = QCheckBox("Save selected components")
        self.keep_chosen_components_chk.setToolTip(
            "Save chosen components when loading segmentation form file\n or from multiple file widget."
        )
        self.keep_chosen_components_chk.stateChanged.connect(
            self.set_keep_chosen_components)
        self.keep_chosen_components_chk.setChecked(
            settings.keep_chosen_components)
        self.show_parameters = QPushButton("Show parameters")
        self.show_parameters.setToolTip(
            "Show parameters of segmentation for each components")
        self.show_parameters_widget = SegmentationInfoDialog(
            self.settings, self.algorithm_choose_widget.change_algorithm)
        self.show_parameters.clicked.connect(self.show_parameters_widget.show)
        self.choose_components = ChosenComponents()
        self.choose_components.check_change_signal.connect(
            image_view.refresh_selected)
        self.choose_components.mouse_leave.connect(image_view.component_unmark)
        self.choose_components.mouse_enter.connect(image_view.component_mark)
        # WARNING works only with one channels algorithms
        # SynchronizeValues.add_synchronization("channels_chose", widgets_list)
        self.chosen_list = []
        self.progress_bar2 = QProgressBar()
        self.progress_bar2.setHidden(True)
        self.progress_bar = QProgressBar()
        self.progress_bar.setHidden(True)
        self.progress_info_lab = QLabel()
        self.progress_info_lab.setHidden(True)
        self.file_list = []
        self.batch_process = BatchProceed()
        self.batch_process.progress_signal.connect(self.progress_info)
        self.batch_process.error_signal.connect(self.execution_all_error)
        self.batch_process.execution_done.connect(self.execution_all_done)
        self.batch_process.range_signal.connect(self.progress_bar.setRange)
        self.is_batch_process = False

        self.setContentsMargins(0, 0, 0, 0)
        main_layout = QVBoxLayout()
        # main_layout.setSpacing(0)
        opt_layout = QHBoxLayout()
        opt_layout.setContentsMargins(0, 0, 0, 0)
        opt_layout.addWidget(self.show_result)
        opt_layout.addWidget(right_label("Opacity:"))
        opt_layout.addWidget(self.opacity)
        main_layout.addLayout(opt_layout)
        opt_layout2 = QHBoxLayout()
        opt_layout2.setContentsMargins(0, 0, 0, 0)
        opt_layout2.addWidget(self.only_borders)
        opt_layout2.addWidget(right_label("Border thick:"))
        opt_layout2.addWidget(self.borders_thick)
        main_layout.addLayout(opt_layout2)
        btn_layout = QGridLayout()
        btn_layout.setContentsMargins(0, 0, 0, 0)
        btn_layout.addWidget(self.execute_btn, 0, 0)
        btn_layout.addWidget(self.execute_in_background_btn, 0, 1)
        btn_layout.addWidget(self.execute_all_btn, 1, 0)
        btn_layout.addWidget(self.save_parameters_btn, 1, 1)
        main_layout.addLayout(btn_layout)
        main_layout.addWidget(self.progress_bar2)
        main_layout.addWidget(self.progress_bar)
        main_layout.addWidget(self.progress_info_lab)
        main_layout.addWidget(self.algorithm_choose_widget, 1)
        # main_layout.addWidget(self.algorithm_choose)
        # main_layout.addLayout(self.stack_layout, 1)
        main_layout.addWidget(self.choose_components)
        down_layout = QHBoxLayout()
        down_layout.addWidget(self.keep_chosen_components_chk)
        down_layout.addWidget(self.show_parameters)
        main_layout.addLayout(down_layout)
        main_layout.addStretch()
        main_layout.setContentsMargins(0, 0, 0, 0)
        # main_layout.setSpacing(0)
        self.setLayout(main_layout)

        # noinspection PyUnresolvedReferences
        self.execute_in_background_btn.clicked.connect(
            self.execute_in_background)
        self.execute_btn.clicked.connect(self.execute_action)
        self.execute_all_btn.clicked.connect(self.execute_all_action)
        self.save_parameters_btn.clicked.connect(self.save_parameters)
        # noinspection PyUnresolvedReferences
        self.opacity.valueChanged.connect(self._set_opacity)
        # noinspection PyUnresolvedReferences
        self.show_result.currentEnumChanged.connect(self._set_show_label)
        self.only_borders.stateChanged.connect(self._set_border_mode)
        # noinspection PyUnresolvedReferences
        self.borders_thick.valueChanged.connect(self._set_border_thick)
        image_view.component_clicked.connect(
            self.choose_components.other_component_choose)
        settings.chosen_components_widget = self.choose_components
        settings.components_change_list.connect(
            self.choose_components.new_choose)
        settings.image_changed.connect(
            self.choose_components.remove_components)
        settings.connect_to_profile(
            f"{self.view_name}.image_state.only_border",
            self._set_border_mode_from_settings)
        settings.connect_to_profile(
            f"{self.view_name}.image_state.border_thick",
            self._set_border_thick_from_settings)
        settings.connect_to_profile(f"{self.view_name}.image_state.opacity",
                                    self._set_opacity_from_settings)
        settings.connect_to_profile(f"{self.view_name}.image_state.show_label",
                                    self._set_show_label_from_settings)

    def _set_border_mode(self, value: bool):
        self.settings.set_in_profile(
            f"{self.view_name}.image_state.only_border", value)

    def _set_border_thick(self, value: int):
        self.settings.set_in_profile(
            f"{self.view_name}.image_state.border_thick", value)

    def _set_opacity(self, value: float):
        self.settings.set_in_profile(f"{self.view_name}.image_state.opacity",
                                     value)

    def _set_show_label(self, value: LabelEnum):
        self.settings.set_in_profile(
            f"{self.view_name}.image_state.show_label", value)

    def _set_border_mode_from_settings(self):
        self.only_borders.setChecked(
            self.settings.get_from_profile(
                f"{self.view_name}.image_state.only_border", True))

    def _set_border_thick_from_settings(self):
        self.borders_thick.setValue(
            self.settings.get_from_profile(
                f"{self.view_name}.image_state.border_thick", 1))

    def _set_opacity_from_settings(self):
        self.opacity.setValue(
            self.settings.get_from_profile(
                f"{self.view_name}.image_state.opacity", 1.0))

    def _set_show_label_from_settings(self):
        self.show_result.setCurrentEnum(
            self.settings.get_from_profile(
                f"{self.view_name}.image_state.show_label",
                LabelEnum.Show_results))

    @Slot(int)
    def set_keep_chosen_components(self, val):
        self.settings.set_keep_chosen_components(val)

    def save_parameters(self):
        dial = PSaveDialog(io_functions.save_parameters_dict,
                           system_widget=False,
                           settings=self.settings,
                           path=IO_SAVE_DIRECTORY)
        if not dial.exec_():
            return
        res = dial.get_result()
        res.save_class.save(res.save_destination,
                            self.algorithm_choose_widget.current_parameters())

    def file_list_change(self, val):
        self.file_list = val
        if len(self.file_list) > 0 and not self.block_execute_all_btn:
            self.execute_all_btn.setEnabled(True)
        else:
            self.execute_all_btn.setDisabled(True)

    def get_chosen_components(self):
        return sorted(self.choose_components.get_chosen())

    @property
    def segmentation(self):
        return self.settings.roi

    @segmentation.setter
    def segmentation(self, val):
        self.settings.roi = val

    def _image_changed(self):
        self.settings.roi = None
        self.choose_components.set_chose([], [])

    def _execute_in_background_init(self):
        if self.batch_process.isRunning():
            return
        self.progress_bar2.setVisible(True)
        self.progress_bar2.setRange(0, self.batch_process.queue.qsize())
        self.progress_bar2.setValue(self.batch_process.index)
        self.progress_bar.setVisible(True)
        self.progress_bar.setValue(0)
        self.execute_btn.setDisabled(True)
        self.batch_process.start()

    def execute_in_background(self):
        # TODO check if components are properly passed
        widget = self.algorithm_choose_widget.current_widget()
        segmentation_profile = widget.get_segmentation_profile()
        task = BatchTask(self.settings.get_project_info(),
                         segmentation_profile, None)
        self.batch_process.add_task(task)
        self.progress_bar2.setRange(0, self.progress_bar2.maximum() + 1)
        self._execute_in_background_init()

    def execute_all_action(self):
        dial = PSaveDialog(
            SaveROI,
            settings=self.settings,
            system_widget=False,
            path="io.save_batch",
            file_mode=PSaveDialog.Directory,
        )
        if not dial.exec_():
            return
        folder_path = str(dial.selectedFiles()[0])

        widget = self.algorithm_choose_widget.current_widget()

        save_parameters = dial.values
        segmentation_profile = widget.get_segmentation_profile()
        for file_path in self.file_list:
            task = BatchTask(file_path, segmentation_profile,
                             (folder_path, save_parameters))
            self.batch_process.add_task(task)
        self.progress_bar2.setRange(
            0,
            self.progress_bar2.maximum() + len(self.file_list))
        self._execute_in_background_init()

    def execution_all_error(self, text):
        QMessageBox.warning(self, "Proceed error", text)

    def execution_all_done(self):
        if not self.batch_process.queue.empty():
            self._execute_in_background_init()
            return
        self.execute_btn.setEnabled(True)
        self.block_execute_all_btn = False
        if len(self.file_list) > 0:
            self.execute_all_btn.setEnabled(True)
        self.progress_bar.setHidden(True)
        self.progress_bar2.setHidden(True)
        self.progress_info_lab.setHidden(True)

    def execute_action(self):
        self.execute_btn.setDisabled(True)
        self.execute_all_btn.setDisabled(True)
        self.block_execute_all_btn = True
        self.is_batch_process = False
        self.progress_bar.setRange(0, 0)
        self.choose_components.setDisabled(True)
        chosen = sorted(self.choose_components.get_chosen())
        blank = get_mask(self.settings.roi, self.settings.mask, chosen)
        if blank is not None:
            # Problem with handling time data in algorithms
            # TODO Fix This
            blank = blank[0]
        self.progress_bar.setHidden(False)
        widget: AlgorithmSettingsWidget = self.algorithm_choose_widget.current_widget(
        )
        widget.set_mask(blank)
        self.progress_bar.setRange(0, widget.algorithm.get_steps_num())
        widget.execute()
        self.chosen_list = chosen

    def progress_info(self, text, num, file_name="", file_num=0):
        self.progress_info_lab.setVisible(True)
        if file_name != "":
            self.progress_info_lab.setText(file_name + "\n" + text)
        else:
            self.progress_info_lab.setText(text)
        self.progress_bar.setValue(num)
        self.progress_bar2.setValue(file_num)

    def execution_finished(self):
        self.execute_btn.setEnabled(True)
        self.block_execute_all_btn = False
        if len(self.file_list) > 0:
            self.execute_all_btn.setEnabled(True)
        self.progress_bar.setHidden(True)
        self.progress_info_lab.setHidden(True)
        self.choose_components.setDisabled(False)

    def execution_result_set(self, result):
        self.settings.set_segmentation_result(result)

    def showEvent(self, _):
        widget = self.algorithm_choose_widget.current_widget()
        widget.image_changed(self.settings.image)