Esempio n. 1
0
class ElaWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(ElaWidget, self).__init__(parent)

        params_layout = QHBoxLayout()
        params_layout.addWidget(QLabel(self.tr('Quality:')))
        self.quality_spin = QSpinBox()
        self.quality_spin.setRange(0, 100)
        self.quality_spin.setSuffix(self.tr(' %'))
        self.quality_spin.valueChanged.connect(self.process)
        params_layout.addWidget(self.quality_spin)

        params_layout.addWidget(QLabel(self.tr('Scale:')))
        self.scale_spin = QSpinBox()
        self.scale_spin.setRange(1, 100)
        self.scale_spin.valueChanged.connect(self.process)
        params_layout.addWidget(self.scale_spin)

        self.equalize_check = QCheckBox(self.tr('Equalized'))
        self.equalize_check.stateChanged.connect(self.process)
        params_layout.addWidget(self.equalize_check)

        params_layout.addStretch()
        default_button = QPushButton(self.tr('Default'))
        default_button.clicked.connect(self.default)
        params_layout.addWidget(default_button)

        self.image = image
        self.viewer = ImageViewer(self.image, self.image)
        self.default()
        self.process()

        main_layout = QVBoxLayout()
        main_layout.addLayout(params_layout)
        main_layout.addWidget(self.viewer)
        self.setLayout(main_layout)

    def process(self):
        equalize = self.equalize_check.isChecked()
        self.scale_spin.setEnabled(not equalize)
        start = time()
        quality = self.quality_spin.value()
        scale = self.scale_spin.value()
        compressed = compress_jpeg(self.image, quality)
        if not equalize:
            ela = cv.convertScaleAbs(cv.subtract(compressed, self.image), None,
                                     scale)
        else:
            ela = cv.merge([
                cv.equalizeHist(c)
                for c in cv.split(cv.absdiff(compressed, self.image))
            ])
        self.viewer.update_processed(ela)
        self.info_message.emit(
            self.tr('Error Level Analysis = {}'.format(elapsed_time(start))))

    def default(self):
        self.quality_spin.setValue(75)
        self.scale_spin.setValue(20)
Esempio n. 2
0
class TestingPanel(Panel):
    def __init__(self, maps, threads):
        super().__init__()
        self.maps = maps
        self.rbfn = None
        self.threads = threads

        self.__set_execution_ui()
        self.__set_outputs_ui()
        self.__set_graphic_ui()
        self.__set_console_ui()

    def __set_execution_ui(self):
        group_box = QGroupBox('Testing Execution')
        inner_layout = QHBoxLayout()
        group_box.setLayout(inner_layout)

        self.map_selector = QComboBox()
        self.map_selector.addItems(list(self.maps.keys()))
        self.map_selector.setStatusTip('Select the training dataset.')
        self.map_selector.currentIndexChanged.connect(self.__change_map)

        self.start_btn = QPushButton('Test')
        self.start_btn.setStatusTip(
            'Start testing. (available after training)')
        self.start_btn.setDisabled(True)
        self.start_btn.clicked.connect(self.__run)

        self.stop_btn = QPushButton('Stop')
        self.stop_btn.setStatusTip('Force the testing stop running.')
        self.stop_btn.setDisabled(True)

        self.fps = QSpinBox()
        self.fps.setMinimum(1)
        self.fps.setMaximum(60)
        self.fps.setValue(20)
        self.fps.setStatusTip(
            "The re-drawing rate for car simulator. High fps "
            "may cause the plot shows discontinuously.")

        inner_layout.addWidget(self.map_selector, 1)
        inner_layout.addWidget(QLabel("FPS:"))
        inner_layout.addWidget(self.fps)
        inner_layout.addWidget(self.start_btn)
        inner_layout.addWidget(self.stop_btn)

        self._layout.addWidget(group_box)

    def __set_outputs_ui(self):
        group_box = QGroupBox("Testing Details")
        inner_layout = QFormLayout()
        group_box.setLayout(inner_layout)

        self.car_position = QLabel('--')
        self.car_angle = QLabel('--')
        self.wheel_angle = QLabel('--')
        self.dist_front = QLabel('--')
        self.dist_left = QLabel('--')
        self.dist_right = QLabel('--')

        self.car_position.setAlignment(Qt.AlignCenter)
        self.car_angle.setAlignment(Qt.AlignCenter)
        self.wheel_angle.setAlignment(Qt.AlignCenter)
        self.dist_front.setAlignment(Qt.AlignCenter)
        self.dist_left.setAlignment(Qt.AlignCenter)
        self.dist_right.setAlignment(Qt.AlignCenter)

        inner_layout.addRow('Car Position:', self.car_position)
        inner_layout.addRow('Car Angle:', self.car_angle)
        inner_layout.addRow('Wheel Angle:', self.wheel_angle)
        inner_layout.addRow('Front Distance:', self.dist_front)
        inner_layout.addRow('Left Distance:', self.dist_left)
        inner_layout.addRow('Right Distance:', self.dist_right)

        self._layout.addWidget(group_box)

    def __set_graphic_ui(self):
        self.simulator = CarSimulatorPlot()
        self.simulator.setStatusTip("Show the graphic of the car controled by "
                                    "the result of the PSO in mazz.")
        self.__change_map()
        self._layout.addWidget(self.simulator)

    def __set_console_ui(self):
        self.__console = QTextEdit()
        self.__console.setReadOnly(True)
        self.__console.setStatusTip("Show the logs of status changing.")
        self._layout.addWidget(self.__console)

    @Slot()
    def __init_widgets(self):
        self.start_btn.setDisabled(True)
        self.stop_btn.setEnabled(True)
        self.fps.setDisabled(True)
        self.map_selector.setDisabled(True)

    @Slot()
    def __reset_widgets(self):
        self.start_btn.setEnabled(True)
        self.stop_btn.setDisabled(True)
        self.fps.setEnabled(True)
        self.map_selector.setEnabled(True)

    @Slot(str)
    def print_console(self, text):
        self.__console.append(text)

    @Slot(list, list, list)
    def __show_dists(self, pos, intersections, dists):
        self.simulator.paint_dist(pos, intersections)
        self.dist_front.setText(str(dists[0]))
        self.dist_left.setText(str(dists[1]))
        self.dist_right.setText(str(dists[2]))

    @Slot()
    def __show_car_collided(self):
        self.simulator.paint_car_collided()

    def __show_path(self, xdata, ydata):
        self.simulator.paint_path(xdata, ydata)

    @Slot()
    def __change_map(self):
        self.__current_map = self.maps[self.map_selector.currentText()]
        self.__car = Car(self.__current_map['start_pos'],
                         self.__current_map['start_angle'], 3,
                         self.__current_map['route_edge'])
        self.simulator.paint_map(self.__current_map)
        self.__move_car(self.__current_map['start_pos'],
                        self.__current_map['start_angle'])
        self.__show_dists(self.__current_map['start_pos'],
                          [self.__current_map['start_pos']] * 3, ['--'] * 3)

    @Slot(list, float, float)
    def __move_car(self, pos, angle, wheel_angle=0.0):
        self.simulator.paint_car(pos, angle)
        self.car_position.setText("({:.7f}, {:.7f})".format(*pos))
        self.car_angle.setText(str(angle))
        self.wheel_angle.setText(str(wheel_angle))

    @Slot(RBFN)
    def load_rbfn(self, rbfn):
        self.rbfn = rbfn
        self.print_console('New RBFN model has been loaded.')
        self.start_btn.setEnabled(True)

    @Slot()
    def __run(self):
        # reset the map
        self.__change_map()
        # create a QThread
        if self.rbfn is None:
            raise TypeError('The RBFN model has not yet loaded.')
        self.__thread = RunCar(self.__car, self.rbfn,
                               (self.__current_map['end_area_lt'],
                                self.__current_map['end_area_rb']),
                               self.fps.value())
        self.threads.append(self.__thread)
        self.stop_btn.clicked.connect(self.__thread.stop)
        self.__thread.started.connect(self.__init_widgets)
        self.__thread.finished.connect(self.__reset_widgets)
        self.__thread.sig_console.connect(self.print_console)
        self.__thread.sig_car.connect(self.__move_car)
        self.__thread.sig_car_collided.connect(self.__show_car_collided)
        self.__thread.sig_dists.connect(self.__show_dists)
        self.__thread.sig_results.connect(self.__get_results)
        self.__thread.start()

    @Slot(list)
    def __get_results(self, results):
        """Get the results of last running and draw the path of it."""
        self.simulator.paint_path([d['x'] for d in results],
                                  [d['y'] for d in results])
Esempio n. 3
0
class Widget(QWidget):

    movie_url_label_text = "粘贴有 dailymotion 版的連續劇网址 (例子: https://dramaq.de/cn191023b/): "

    def __init__(self):
        QWidget.__init__(self)

        self.q = None
        self.pool = None

        self.top = QHBoxLayout()
        self.top.setMargin(10)

        self.middle = QVBoxLayout()
        self.middle.setMargin(10)

        self.radioButtonDailyMotionDrama = QRadioButton(
            "有 Dailymotion Drama 的網站")
        self.radioButtonAny = QRadioButton("其它類型網站 (例如 YouTube)")

        self.top.addWidget(self.radioButtonDailyMotionDrama)
        self.top.addWidget(self.radioButtonAny)

        self.url_label = QLabel()
        self.url = QLineEdit()
        self.url_label.setBuddy(self.url)
        self.middle.addWidget(self.url_label)
        self.middle.addWidget(self.url)

        self.browse_folder_label = QLabel("下載到:")
        self.browseFolder = QPushButton("選擇目錄")
        self.browse_folder_label.setBuddy(self.browseFolder)
        self.middle.addWidget(self.browse_folder_label)
        self.middle.addWidget(self.browseFolder)
        self.browse_folder_value = ""

        self.bk_cinemae_spin_from = 1
        self.bk_cinemae_spin_to = 1
        self.fromEpSpinBox = QSpinBox()
        self.fromEpSpinBox.setMinimum(1)
        self.fromEpSpinBox.setMaximum(2147483647)
        self.fromEpLabel = QLabel("&從第幾集開始下載:")
        self.fromEpLabel.setBuddy(self.fromEpSpinBox)

        self.toEpSpinBox = QSpinBox()
        self.toEpSpinBox.setMinimum(1)
        self.toEpSpinBox.setMaximum(2147483647)
        self.toEpLabel = QLabel("&到第幾集停止下載:")
        self.toEpLabel.setBuddy(self.toEpSpinBox)

        self.cinema_ly = QHBoxLayout()
        #self.cinema_ly.setMargin(10)
        self.cinema_ly.addWidget(self.fromEpLabel)
        self.cinema_ly.addWidget(self.fromEpSpinBox)
        self.cinema_ly.addWidget(self.toEpLabel)
        self.cinema_ly.addWidget(self.toEpSpinBox)
        self.middle.addLayout(self.cinema_ly)

        self.add = QPushButton("開始下載")
        self.add.setEnabled(False)
        self.middle.addWidget(self.add)

        self.stop_me = QPushButton("停止下載")
        self.stop_me.setEnabled(False)
        self.middle.addWidget(self.stop_me)

        self.log_area = QPlainTextEdit()
        self.log_area.setReadOnly(True)
        self.log_area.setMaximumBlockCount(1000)
        self.middle.addWidget(self.log_area)

        #self.table_view.setSizePolicy(size)
        #self.layout.addWidget(self.table)
        self.layout = QVBoxLayout()
        self.layout.addLayout(self.top)
        self.layout.addLayout(self.middle)
        self.setLayout(self.layout)

        self.radioButtonDailyMotionDrama.toggled.connect(
            self.choose_DailyMotionDrama_widgets)
        self.radioButtonAny.toggled.connect(self.choose_Any_widgets)
        self.url.textChanged[str].connect(self.check_disable_download)
        self.browseFolder.clicked.connect(self.add_folder)
        self.add.clicked.connect(self.start_download)
        self.stop_me.clicked.connect(self.stop_download)

        self.radioButtonDailyMotionDrama.setChecked(
            True)  #set default only after .connect above

        # TESTING PURPOSE
        '''
        self.url.setText('https://journalflash.com/cn191023b/')
        self.browse_folder_value = 'C:/Users/Administrator/Documents/duboku'
        '''

        #set current process (not queue that one) log handler:
        logger = logging.getLogger(__name__)
        handler2 = LoggerWriter()
        logger.addHandler(handler2)
        logger.setLevel(logging.INFO)  #DEBUG
        handler2.emitter.sigLog.connect(self.log_area.appendPlainText)
        sys.stdout = handler2  #LoggerWriter()
        #sys.stderr = handler2 #Seems no difference
        #handler2.emitter.sigLog.emit('hihi')

    @Slot()
    def choose_DailyMotionDrama_widgets(self):

        if self.radioButtonDailyMotionDrama.isChecked():

            self.fromEpLabel.setEnabled(True)
            self.toEpLabel.setEnabled(True)

            self.fromEpSpinBox.setEnabled(True)
            self.toEpSpinBox.setEnabled(True)

            self.fromEpSpinBox.setValue(self.bk_cinemae_spin_from)
            self.toEpSpinBox.setValue(self.bk_cinemae_spin_to)
            self.fromEpLabel.setDisabled(True)
            self.toEpLabel.setDisabled(True)

    @Slot()
    def choose_Any_widgets(self):

        if self.radioButtonAny.isChecked():

            self.fromEpSpinBox.setDisabled(True)
            self.toEpSpinBox.setDisabled(True)

            self.bk_cinemae_spin_from = self.fromEpSpinBox.value()
            self.bk_cinemae_spin_to = self.toEpSpinBox.value()
            self.fromEpSpinBox.setValue(1)
            self.toEpSpinBox.setValue(1)

    @Slot()
    def add_folder(self, s):

        #fname = QFileDialog.getOpenFileName(self, 'Open file', "c:\'", "Image files (*.jpg *.gif)")
        #fname = QFileDialog.getOpenFileName(self, 'Open file', '', QFileDialog.ShowDirsOnly)
        fname = QFileDialog.getExistingDirectory(self, '選擇下載至什麼目錄', '',
                                                 QFileDialog.ShowDirsOnly)
        #print('repr: ' + repr(fname))
        if fname and fname.strip():
            fname = fname.strip()
            self.browse_folder_value = fname
            #if getOpenFileName, will return ('/home/xiaobai/Pictures/disco.jpg', 'Image files (*.jpg *.gif)')
            #, while if getExistingDirectory, will return single path string only
            self.browseFolder.setText(fname)
            self.check_disable_download(fname)
        #else:
        #    print('User cancel')

    @Slot()
    def check_disable_download(self, s):

        if self.url.text() and self.browse_folder_value:
            self.add.setEnabled(True)
        else:
            self.add.setEnabled(False)

    def task_done(self, retVal):
        self.add.setEnabled(True)
        self.stop_me.setEnabled(False)

    @Slot()
    def stop_download(self):
        if self.q:
            self.q.close()
        if self.pool:
            self.pool.terminate()
        self.add.setEnabled(True)
        self.stop_me.setEnabled(False)
        print('下載停止。')

    @Slot()
    def start_download(self):

        if self.fromEpSpinBox.value() > self.toEpSpinBox.value():
            self.log_area.setPlainText('[!] 從第幾集必須小於或等於到第幾集。')
            return

        #No need worry click twice too fast, it seems already handle by PySide2
        self.add.setEnabled(False)
        self.stop_me.setEnabled(True)
        self.log_area.clear()

        dest_full_path = self.browse_folder_value
        '''
        print('dest_full_path: ' + repr(dest_full_path))
        print('self.url.text(): ' + repr(self.url.text()))
        print('self.fromEpSpinBox.value(): ' + repr(self.fromEpSpinBox.value()))
        print('self.toEpSpinBox.value(): ' + repr(self.toEpSpinBox.value()))
        '''

        import drama_dailymotion_console

        #Windows can't set like that bcoz not update for args.url, must put explicitly
        #drama_dailymotion_console.redirect_stdout_to_custom_stdout(arg_url, ...etc, LoggerWriter())

        #failed other process
        handler = LogHandlerOtherProcess()
        handler.emitter.sigLog.connect(self.log_area.appendPlainText)
        ''' #ref current process:
        logger = logging.getLogger(__name__)
        handler2 = LoggerWriter()
        logger.addHandler(handler2)
        logger.setLevel(logging.DEBUG)
        handler2.emitter.sigLog.connect(self.log_area.appendPlainText)
        sys.stdout = handler2 #LoggerWriter()
        #handler2.emitter.sigLog.emit('hihi')
        '''

        #handler = LoggerWriter()
        #handler.emitter.sigLog.connect(self.log_area.appendPlainText)

        self.q = multiprocessing.Queue()
        self.ql = QueueListener(self.q, handler)
        self.ql.start()

        self.pool = multiprocessing.Pool(1, worker_init, [self.q])

        if self.radioButtonDailyMotionDrama.isChecked():
            self.pool.apply_async(drama_dailymotion_console.main,
                                  args=(dest_full_path,
                                        self.fromEpSpinBox.value(),
                                        self.toEpSpinBox.value(),
                                        self.url.text(),
                                        LoggerWriterOtherProcess(), False),
                                  callback=self.task_done)
        else:
            self.pool.apply_async(drama_dailymotion_console.main,
                                  args=(dest_full_path,
                                        self.fromEpSpinBox.value(),
                                        self.toEpSpinBox.value(),
                                        self.url.text(),
                                        LoggerWriterOtherProcess(), True),
                                  callback=self.task_done)
Esempio n. 4
0
class MagnifierWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(MagnifierWidget, self).__init__(parent)

        self.equalize_radio = QRadioButton(self.tr("Equalization"))
        self.equalize_radio.setToolTip(self.tr("RGB histogram equalization"))
        self.contrast_radio = QRadioButton(self.tr("Auto Contrast"))
        self.contrast_radio.setToolTip(self.tr("Compress luminance tonality"))
        self.centile_spin = QSpinBox()
        self.centile_spin.setRange(0, 100)
        self.centile_spin.setValue(20)
        self.centile_spin.setSuffix(self.tr(" %"))
        self.centile_spin.setToolTip(self.tr("Histogram percentile amount"))
        self.channel_check = QCheckBox(self.tr("By channel"))
        self.channel_check.setToolTip(self.tr("Independent RGB compression"))
        self.equalize_radio.setChecked(True)
        self.last_radio = self.equalize_radio

        self.image = image
        self.viewer = ImageViewer(self.image, self.image)
        self.change()

        self.viewer.viewChanged.connect(self.process)
        self.equalize_radio.clicked.connect(self.change)
        self.contrast_radio.clicked.connect(self.change)
        self.centile_spin.valueChanged.connect(self.change)
        self.channel_check.stateChanged.connect(self.change)

        top_layout = QHBoxLayout()
        top_layout.addWidget(QLabel(self.tr("Mode:")))
        top_layout.addWidget(self.equalize_radio)
        top_layout.addWidget(self.contrast_radio)
        top_layout.addWidget(self.centile_spin)
        top_layout.addWidget(self.channel_check)
        top_layout.addStretch()

        main_layout = QVBoxLayout()
        main_layout.addLayout(top_layout)
        main_layout.addWidget(self.viewer)
        self.setLayout(main_layout)

    def process(self, rect):
        y1 = rect.top()
        y2 = rect.bottom()
        x1 = rect.left()
        x2 = rect.right()
        roi = self.image[y1:y2, x1:x2]
        if self.equalize_radio.isChecked():
            self.centile_spin.setEnabled(False)
            self.channel_check.setEnabled(False)
            roi = equalize_img(roi)
            self.last_radio = self.equalize_radio
        elif self.contrast_radio.isChecked():
            self.centile_spin.setEnabled(True)
            self.channel_check.setEnabled(True)
            centile = self.centile_spin.value() / 200
            if self.channel_check.isChecked():
                roi = cv.merge(
                    [cv.LUT(c, auto_lut(c, centile)) for c in cv.split(roi)])
            else:
                roi = cv.LUT(
                    roi, auto_lut(cv.cvtColor(roi, cv.COLOR_BGR2GRAY),
                                  centile))
            self.last_radio = self.contrast_radio
        else:
            self.last_radio.setChecked(True)
            return
        processed = np.copy(self.image)
        processed[y1:y2, x1:x2] = roi
        self.viewer.update_processed(processed)

    def change(self):
        self.process(self.viewer.get_rect())
Esempio n. 5
0
class TrainingPanel(Panel):

    def __init__(self, datasets, testing_panel, threads):
        super().__init__()
        if isinstance(testing_panel, TestingPanel):
            self.testing_panel = testing_panel
        else:
            raise TypeError('"testing_panel" must be the instance of '
                            '"TestingPanel"')
        self.datasets = datasets
        self.threads = threads

        self.__set_execution_ui()
        self.__set_options_ui()
        self.__set_outputs_ui()
        self.__set_graphic_ui()

    def __set_execution_ui(self):
        group_box = QGroupBox('Training Execution')
        inner_layout = QHBoxLayout()
        group_box.setLayout(inner_layout)

        self.data_selector = QComboBox()
        self.data_selector.addItems(list(self.datasets.keys()))
        self.data_selector.setStatusTip('Select the training dataset.')

        self.start_btn = QPushButton('Train')
        self.start_btn.setStatusTip('Start training.')
        self.start_btn.clicked.connect(self.__run)

        self.stop_btn = QPushButton('Stop')
        self.stop_btn.setStatusTip('Force the training stop running.')
        self.stop_btn.setDisabled(True)

        self.multicore_cb = QCheckBox('Multicore')
        self.multicore_cb.setStatusTip('Use multiprocessing in calculating '
                                       'fitting for populations.')
        self.multicore_cb.setChecked(True)

        inner_layout.addWidget(self.data_selector, 1)
        inner_layout.addWidget(self.start_btn)
        inner_layout.addWidget(self.stop_btn)
        inner_layout.addWidget(self.multicore_cb)

        self._layout.addWidget(group_box)

    def __set_options_ui(self):
        group_box = QGroupBox('Training Options')
        inner_layout = QFormLayout()
        group_box.setLayout(inner_layout)

        self.iter_times = QSpinBox()
        self.iter_times.setRange(1, 1000000)
        self.iter_times.setValue(200)
        self.iter_times.setStatusTip('The total iterating times for training.')

        self.population_size = QSpinBox()
        self.population_size.setRange(1, 100000)
        self.population_size.setValue(100)
        self.population_size.setStatusTip('The population size for the PSO.')

        self.inertia_weight = QDoubleSpinBox()
        self.inertia_weight.setRange(0, 50)
        self.inertia_weight.setValue(1)
        self.inertia_weight.setSingleStep(0.1)
        self.inertia_weight.setStatusTip('The inertia weight of the velocity '
                                         ' for each individual.')

        self.cognitive_const_rand_upper = QDoubleSpinBox()
        self.cognitive_const_rand_upper.setRange(0, 50)
        self.cognitive_const_rand_upper.setValue(2)
        self.cognitive_const_rand_upper.setSingleStep(0.1)
        self.cognitive_const_rand_upper.setStatusTip(
            'The random upper bound for cognitive accelerate constant.')

        self.social_const_rand_upper = QDoubleSpinBox()
        self.social_const_rand_upper.setRange(0, 50)
        self.social_const_rand_upper.setValue(3)
        self.social_const_rand_upper.setSingleStep(0.1)
        self.social_const_rand_upper.setStatusTip(
            'The random upper bound for social accelerate constant.')

        self.v_max = QDoubleSpinBox()
        self.v_max.setRange(0.5, 100)
        self.v_max.setValue(5)
        self.v_max.setSingleStep(1)
        self.v_max.setStatusTip('The maximum of velocity for each individual.')

        self.nneuron = QSpinBox()
        self.nneuron.setRange(1, 100)
        self.nneuron.setValue(6)
        self.nneuron.setStatusTip('The number of RBFN neuron.')

        self.sd_max = QDoubleSpinBox()
        self.sd_max.setRange(0.01, 20)
        self.sd_max.setValue(10)
        self.sd_max.setSingleStep(0.1)
        self.sd_max.setStatusTip('The random range maximum of standard '
                                 'deviation of each neuron in RBFN (only for '
                                 'initialization).')

        inner_layout.addRow('Iterating Times:', self.iter_times)
        inner_layout.addRow('Population Size:', self.population_size)
        inner_layout.addRow('Inertia Weight:', self.inertia_weight)
        inner_layout.addRow('Cognitive Const Upper:',
                            self.cognitive_const_rand_upper)
        inner_layout.addRow('Social Const Upper:',
                            self.social_const_rand_upper)
        inner_layout.addRow('Maximum of Velocity:', self.v_max)
        inner_layout.addRow('Number of Neuron:', self.nneuron)
        inner_layout.addRow('Maximum of SD:', self.sd_max)

        self._layout.addWidget(group_box)

    def __set_outputs_ui(self):
        group_box = QGroupBox('Training Details')
        inner_layout = QFormLayout()
        group_box.setLayout(inner_layout)

        self.current_iter_time = QLabel('--')
        self.current_error = QLabel('--')
        self.avg_error = QLabel('--')
        self.global_best_error = QLabel('--')
        self.total_best_error = QLabel('--')
        self.progressbar = QProgressBar()

        self.current_iter_time.setAlignment(Qt.AlignCenter)
        self.current_error.setAlignment(Qt.AlignCenter)
        self.avg_error.setAlignment(Qt.AlignCenter)
        self.global_best_error.setAlignment(Qt.AlignCenter)
        self.total_best_error.setAlignment(Qt.AlignCenter)

        self.current_iter_time.setStatusTip('The current iterating time of '
                                            'the PSO.')
        self.current_error.setStatusTip('The current error from the fitting '
                                        'function. ("( )": normalized error)')
        self.avg_error.setStatusTip('The average error from the fitting '
                                    'function in current iteration.  ("( )": '
                                    'normalized error)')
        self.global_best_error.setStatusTip(
            'The error of global best individual from the fitting function in '
            'current iteration.  ("( )": normalized error)')
        self.total_best_error.setStatusTip(
            'The error of total best individual from the fitting function in '
            'training.  ("( )": normalized error)')

        inner_layout.addRow('Current Iterating Time:', self.current_iter_time)
        inner_layout.addRow('Current Error:', self.current_error)
        inner_layout.addRow('Average Error:', self.avg_error)
        inner_layout.addRow('Global Best Error:', self.global_best_error)
        inner_layout.addRow('Total Best Error:', self.total_best_error)
        inner_layout.addRow(self.progressbar)

        self._layout.addWidget(group_box)

    def __set_graphic_ui(self):
        group_box = QGroupBox('Error Line Charts:')
        inner_layout = QVBoxLayout()
        group_box.setLayout(inner_layout)

        self.err_chart = ErrorLineChart(1)
        self.err_chart.setStatusTip('The history of error from the fitting '
                                    'of the PSO for each data.')
        self.__err_x = 1

        self.iter_err_chart = ErrorLineChart(
            3, ('Avg', 'Global Best', 'Total Best'))
        self.iter_err_chart.setStatusTip('The history of average and least '
                                         'error from the fitting of the PSO '
                                         'for each iteration.')
        self.iter_err_chart.setMinimumHeight(150)

        inner_layout.addWidget(QLabel('Current Error'))
        inner_layout.addWidget(self.err_chart)
        inner_layout.addWidget(QLabel('Average Error'))
        inner_layout.addWidget(self.iter_err_chart)
        self._layout.addWidget(group_box)

    @Slot()
    def __init_widgets(self):
        self.start_btn.setDisabled(True)
        self.stop_btn.setEnabled(True)
        self.multicore_cb.setDisabled(True)
        self.data_selector.setDisabled(True)
        self.iter_times.setDisabled(True)
        self.population_size.setDisabled(True)
        self.inertia_weight.setDisabled(True)
        self.cognitive_const_rand_upper.setDisabled(True)
        self.social_const_rand_upper.setDisabled(True)
        self.v_max.setDisabled(True)
        self.nneuron.setDisabled(True)
        self.sd_max.setDisabled(True)
        self.err_chart.clear()
        self.iter_err_chart.clear()
        self.__err_x = 1

    @Slot()
    def __reset_widgets(self):
        self.start_btn.setEnabled(True)
        self.stop_btn.setDisabled(True)
        self.multicore_cb.setEnabled(True)
        self.data_selector.setEnabled(True)
        self.iter_times.setEnabled(True)
        self.population_size.setEnabled(True)
        self.inertia_weight.setEnabled(True)
        self.cognitive_const_rand_upper.setEnabled(True)
        self.social_const_rand_upper.setEnabled(True)
        self.v_max.setEnabled(True)
        self.nneuron.setEnabled(True)
        self.sd_max.setEnabled(True)
        self.progressbar.setMinimum(0)
        self.progressbar.setMaximum(100)

    @Slot()
    def __indicate_busy(self):
        self.progressbar.setMinimum(0)
        self.progressbar.setMaximum(0)

    @Slot(int)
    def __show_current_iter_time(self, value):
        self.current_iter_time.setText(str(value + 1))
        self.progressbar.setValue(value + 1)

    @Slot(float)
    def __show_current_error(self, value):
        self.current_error.setText('{:.5f} ({:.5f})'.format(value, value / 40))
        self.err_chart.append_point(self.__err_x, value)
        self.__err_x += 1

    @Slot(float, float, float)
    def __show_iter_error(self, avg, glob, total):
        self.avg_error.setText('{:.5f} ({:.5f})'.format(avg, avg / 40))
        self.global_best_error.setText(
            '{:.5f} ({:.5f})'.format(glob, glob / 40))
        self.total_best_error.setText(
            '{:.5f} ({:.5f})'.format(total, total / 40))
        self.iter_err_chart.append_point(
            int(self.current_iter_time.text()), total, 2)
        self.iter_err_chart.append_point(
            int(self.current_iter_time.text()), glob, 1)
        self.iter_err_chart.append_point(
            int(self.current_iter_time.text()), avg, 0)

    def __run(self):
        self.progressbar.setMaximum(self.iter_times.value())

        self.__current_dataset = self.datasets[
            self.data_selector.currentText()]

        self.__pso = PSO(self.iter_times.value(), self.population_size.value(),
                         self.inertia_weight.value(),
                         self.cognitive_const_rand_upper.value(),
                         self.social_const_rand_upper.value(),
                         self.v_max.value(), self.nneuron.value(),
                         self.__current_dataset, self.sd_max.value(),
                         is_multicore=self.multicore_cb.isChecked())
        self.threads.append(self.__pso)
        self.stop_btn.clicked.connect(self.__pso.stop)
        self.__pso.started.connect(self.__init_widgets)
        self.__pso.finished.connect(self.__reset_widgets)
        self.__pso.sig_current_iter_time.connect(self.__show_current_iter_time)
        self.__pso.sig_current_error.connect(self.__show_current_error)
        self.__pso.sig_iter_error.connect(self.__show_iter_error)
        self.__pso.sig_indicate_busy.connect(self.__indicate_busy)
        self.__pso.sig_console.connect(self.testing_panel.print_console)
        self.__pso.sig_rbfn.connect(self.testing_panel.load_rbfn)
        self.__pso.start()
Esempio n. 6
0
class MinMaxWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(MinMaxWidget, self).__init__(parent)

        self.chan_combo = QComboBox()
        self.chan_combo.addItems(
            [self.tr("Luminance"), self.tr("Red"), self.tr("Green"), self.tr("Blue"), self.tr("RGB Norm")]
        )
        colors = [self.tr("Red"), self.tr("Green"), self.tr("Blue"), self.tr("White"), self.tr("Black")]
        self.process_button = QPushButton(self.tr("Process"))

        self.min_combo = QComboBox()
        self.min_combo.addItems(colors)
        self.min_combo.setCurrentIndex(1)

        self.max_combo = QComboBox()
        self.max_combo.addItems(colors)
        self.max_combo.setCurrentIndex(0)

        self.filter_spin = QSpinBox()
        self.filter_spin.setRange(0, 5)
        self.filter_spin.setSpecialValueText(self.tr("Off"))

        self.image = image
        self.viewer = ImageViewer(self.image, self.image)
        self.low = self.high = None
        self.stopped = False
        self.change()

        self.process_button.clicked.connect(self.preprocess)
        self.chan_combo.currentIndexChanged.connect(self.change)
        self.min_combo.currentIndexChanged.connect(self.process)
        self.max_combo.currentIndexChanged.connect(self.process)
        self.filter_spin.valueChanged.connect(self.process)

        top_layout = QHBoxLayout()
        top_layout.addWidget(QLabel(self.tr("Channel:")))
        top_layout.addWidget(self.chan_combo)
        top_layout.addWidget(self.process_button)
        top_layout.addWidget(QLabel(self.tr("Minimum:")))
        top_layout.addWidget(self.min_combo)
        top_layout.addWidget(QLabel(self.tr("Maximum:")))
        top_layout.addWidget(self.max_combo)
        top_layout.addWidget(QLabel(self.tr("Filter:")))
        top_layout.addWidget(self.filter_spin)
        top_layout.addStretch()
        main_layout = QVBoxLayout()
        main_layout.addLayout(top_layout)
        main_layout.addWidget(self.viewer)
        self.setLayout(main_layout)

    @staticmethod
    def minmax_dev(patch, mask):
        c = patch[1, 1]
        minimum, maximum, _, _ = cv.minMaxLoc(patch, mask)
        if c < minimum:
            return -1
        if c > maximum:
            return +1
        return 0

    @staticmethod
    def blk_filter(img, radius):
        result = np.zeros_like(img, np.float32)
        rows, cols = result.shape
        block = 2 * radius + 1
        for i in range(radius, rows, block):
            for j in range(radius, cols, block):
                result[i - radius : i + radius + 1, j - radius : j + radius + 1] = np.std(
                    img[i - radius : i + radius + 1, j - radius : j + radius + 1]
                )
        return cv.normalize(result, None, 0, 127, cv.NORM_MINMAX, cv.CV_8UC1)

    def change(self):
        self.min_combo.setEnabled(False)
        self.max_combo.setEnabled(False)
        self.filter_spin.setEnabled(False)
        self.process_button.setEnabled(True)
        self.viewer.update_processed(self.image)

    def preprocess(self):
        start = time()
        channel = self.chan_combo.currentIndex()
        if channel == 0:
            img = cv.cvtColor(self.image, cv.COLOR_BGR2GRAY)
        elif channel == 4:
            b, g, r = cv.split(self.image.astype(np.float64))
            img = cv.sqrt(cv.pow(b, 2) + cv.pow(g, 2) + cv.pow(r, 2))
        else:
            img = self.image[:, :, 3 - channel]
        kernel = 3
        border = kernel // 2
        shape = (img.shape[0] - kernel + 1, img.shape[1] - kernel + 1, kernel, kernel)
        strides = 2 * img.strides
        patches = np.lib.stride_tricks.as_strided(img, shape=shape, strides=strides)
        patches = patches.reshape((-1, kernel, kernel))
        mask = np.full((kernel, kernel), 255, dtype=np.uint8)
        mask[border, border] = 0
        progress = QProgressDialog(
            self.tr("Computing deviation..."), self.tr("Cancel"), 0, shape[0] * shape[1] - 1, self
        )
        progress.canceled.connect(self.cancel)
        progress.setWindowModality(Qt.WindowModal)
        blocks = [0] * shape[0] * shape[1]
        for i, patch in enumerate(patches):
            blocks[i] = self.minmax_dev(patch, mask)
            progress.setValue(i)
            if self.stopped:
                self.stopped = False
                return
        output = np.array(blocks).reshape(shape[:-2])
        output = cv.copyMakeBorder(output, border, border, border, border, cv.BORDER_CONSTANT)
        self.low = output == -1
        self.high = output == +1
        self.min_combo.setEnabled(True)
        self.max_combo.setEnabled(True)
        self.filter_spin.setEnabled(True)
        self.process_button.setEnabled(False)
        self.process()
        self.info_message.emit(self.tr(f"Min/Max Deviation = {elapsed_time(start)}"))

    def cancel(self):
        self.stopped = True

    def process(self):
        minmax = np.zeros_like(self.image)
        minimum = self.min_combo.currentIndex()
        maximum = self.max_combo.currentIndex()
        radius = self.filter_spin.value()
        if radius > 0:
            start = time()
            radius += 3
            if minimum < 4:
                low = self.blk_filter(self.low, radius)
                if minimum <= 2:
                    minmax[:, :, 2 - minimum] = low
                else:
                    minmax = np.repeat(low[:, :, np.newaxis], 3, axis=2)
            if maximum < 4:
                high = self.blk_filter(self.high, radius)
                if maximum <= 2:
                    minmax[:, :, 2 - maximum] += high
                else:
                    minmax += np.repeat(high[:, :, np.newaxis], 3, axis=2)
            minmax = norm_mat(minmax)
            self.info_message.emit(self.tr(f"Min/Max Filter = {elapsed_time(start)}"))
        else:
            if minimum == 0:
                minmax[self.low] = [0, 0, 255]
            elif minimum == 1:
                minmax[self.low] = [0, 255, 0]
            elif minimum == 2:
                minmax[self.low] = [255, 0, 0]
            elif minimum == 3:
                minmax[self.low] = [255, 255, 255]
            if maximum == 0:
                minmax[self.high] = [0, 0, 255]
            elif maximum == 1:
                minmax[self.high] = [0, 255, 0]
            elif maximum == 2:
                minmax[self.high] = [255, 0, 0]
            elif maximum == 3:
                minmax[self.high] = [255, 255, 255]
        self.viewer.update_processed(minmax)
Esempio n. 7
0
class EmptyVolumeUI(QSplitter):
    def __init__(self, *args, **kwargs):
        super(EmptyVolumeUI, self).__init__(*args, **kwargs)
        self.visible = QGraphicsOpacityEffect(self)
        self.visible.setOpacity(1.0)

        self.disvisible = QGraphicsOpacityEffect(self)
        self.disvisible.setOpacity(0.0)

        main_layout = QHBoxLayout()
        self.variety_tree = VarietyTree(self)

        main_layout.addWidget(self.variety_tree)

        self.right_widget = QWidget(self)
        right_layout = QVBoxLayout()
        right_layout.setContentsMargins(QMargins(1, 1, 1, 1))
        opts_layout = QHBoxLayout()

        # 选择分析的目标数据类别
        self.radio_button_group = QButtonGroup(self)
        radio_button_1 = QRadioButton("行情统计", self)
        radio_button_1.setChecked(True)
        self.radio_button_group.addButton(radio_button_1)
        radio_button_2 = QRadioButton("排名持仓", self)
        self.radio_button_group.addButton(radio_button_2)
        opts_layout.addWidget(radio_button_1)
        opts_layout.addWidget(radio_button_2)
        self.rank_spinbox = QSpinBox(self)
        self.rank_spinbox.setPrefix("前 ")
        self.rank_spinbox.setSuffix(" 名")
        self.rank_spinbox.setRange(1, 20)
        self.rank_spinbox.setValue(20)
        self.rank_spinbox.setEnabled(False)
        opts_layout.addWidget(self.rank_spinbox)
        # 分割线
        vertical_line = QFrame(self)
        vertical_line.setFrameShape(QFrame.VLine)
        opts_layout.addWidget(vertical_line)

        opts_layout.addWidget(QLabel("选择合约:", self))
        self.contract_combobox = QComboBox(self)
        opts_layout.addWidget(self.contract_combobox)

        self.confirm_button = QPushButton("确定", self)
        opts_layout.addWidget(self.confirm_button)

        self.tip_button = QPushButton('左侧选择品种后进行查询 ', self)  # 提示文字
        opts_layout.addWidget(self.tip_button)
        self.tip_button.setGraphicsEffect(self.disvisible)
        opts_layout.addStretch()

        right_layout.addLayout(opts_layout)

        self.web_container = QWebEngineView(self)
        right_layout.addWidget(self.web_container)

        self.right_widget.setLayout(right_layout)
        main_layout.addWidget(self.right_widget)

        self.setStretchFactor(1, 2)
        self.setStretchFactor(2, 8)
        self.setHandleWidth(1)
        self.contract_combobox.setMinimumWidth(80)
        self.setLayout(main_layout)
        self.tip_button.setObjectName("tipButton")
        self.setStyleSheet(
            "#tipButton{border:none;color:rgb(230,50,50);font-weight:bold;}")
class InputsLayout(QFormLayout):
    # this signal is connected to print_output from output_layout class. Connection is done in center_layout
    ga_result = Signal(
        str
    )  # a signal that is emitted so it can transfer resulting string to the output_layout class

    def __init__(self):
        super(InputsLayout, self).__init__()
        self.big_font = QFont()
        self.medium_font = QFont()
        self.header = QLabel()
        self.header_general = QLabel()
        self.header_fitness_remapping = QLabel()
        self.header_stop = QLabel()
        self.header_selection = QLabel()
        self.header_pairing = QLabel()
        self.header_crossover = QLabel()
        self.header_mutation = QLabel()

        self.inp_functions_combo = QComboBox()
        self.inp_num_variables = QSpinBox()
        self.inp_extrema_min = QRadioButton("Minimum")
        self.inp_extrema_max = QRadioButton("Maximum")
        self.inp_pop_size = QSpinBox()
        self.inp_lower_bound = QDoubleSpinBox()
        self.inp_upper_bound = QDoubleSpinBox()
        # Stopping
        self.inp_max_iter = QSpinBox()
        self.inp_similarity_cb = QCheckBox()
        self.inp_similarity = QSpinBox()
        self.inp_best_result_cb = QCheckBox()
        self.inp_best_result = QDoubleSpinBox()
        self.inp_average_result_cb = QCheckBox()
        self.inp_average_result = QDoubleSpinBox()
        # Fitness remapping
        self.inp_fitness_remapping = QComboBox()
        # Selection
        self.inp_selection_method = QComboBox()
        self.inp_elitism = QDoubleSpinBox()
        # Pairing
        self.inp_pairing_method = QComboBox()
        # Crossover
        self.inp_crossover_method = QComboBox()
        self.inp_crossover_fraction = QDoubleSpinBox()
        self.intermediate_offset = QDoubleSpinBox()
        # Mutation
        self.inp_mutation_method = QComboBox()
        self.inp_mutation_intensity = QDoubleSpinBox()
        self.inp_mutation_intensity_final = QDoubleSpinBox()

        self.init_fonts()
        self.init_header()
        self.init_row_functions()
        self.init_row_general()
        self.init_row_fitness_remapping()
        self.init_row_stop()
        self.init_row_selection()
        self.init_row_pairing()
        self.init_row_crossover()
        self.init_row_mutation()

    def init_fonts(self):
        self.big_font.setPointSizeF(14)
        self.medium_font.setPointSizeF(12)

    def init_header(self):
        self.header.setFont(self.big_font)
        self.header.setAlignment(Qt.AlignCenter)
        self.header.setText("Genetic Algorithm Continuous Optimization")
        self.addRow(self.header)
        self.addRow(QHLine())

    def init_row_functions(self):
        self.inp_functions_combo.addItem("Ackley", ackley)
        self.inp_functions_combo.addItem("Griewank", griewank)
        self.inp_functions_combo.addItem("Michalewicz", michalewicz)

        self.inp_extrema_min.setChecked(True)

        radio_box = QHBoxLayout()
        radio_box.addWidget(self.inp_extrema_min)
        radio_box.addWidget(self.inp_extrema_max)
        self.addRow("Function:", self.inp_functions_combo)
        self.inp_num_variables.setMaximum(10000)
        self.inp_num_variables.setValue(10)
        self.addRow("Number of variables:", self.inp_num_variables)
        self.addRow("Find:", radio_box)
        self.addRow(QHLine())

    def init_row_general(self):
        self.header_general.setFont(self.medium_font)
        self.header_general.setText("General")

        self.inp_pop_size.setMaximum(10000)
        self.inp_pop_size.setValue(300)
        self.inp_lower_bound.setMaximum(1000000)
        self.inp_lower_bound.setMinimum(-1000000.0)
        self.inp_lower_bound.setValue(-10)
        self.inp_upper_bound.setMaximum(1000000)
        self.inp_upper_bound.setMinimum(-1000000.0)
        self.inp_upper_bound.setValue(10)

        self.addRow(self.header_general)
        self.addRow("Population size", self.inp_pop_size)
        self.addRow("Lower Bound", self.inp_lower_bound)
        self.addRow("Upper Bound", self.inp_upper_bound)
        self.addRow(QHLine())

    def init_row_fitness_remapping(self):
        self.header_fitness_remapping.setFont(self.medium_font)
        self.header_fitness_remapping.setText("Fitness Remapping")

        self.inp_fitness_remapping.addItem("Rank Scaling", "Rank Scaling")
        self.inp_fitness_remapping.addItem("Fitness Scaling",
                                           "Fitness Scaling")

        self.addRow(self.header_fitness_remapping)
        self.addRow("Fitness remapping", self.inp_fitness_remapping)
        self.addRow(QHLine())

    def init_row_stop(self):
        self.header_stop.setFont(self.medium_font)
        self.header_stop.setText("Stopping Criteria")

        self.inp_max_iter.setMaximum(100000)
        self.inp_similarity.setMaximum(100000)
        self.inp_best_result.setMinimum(-100000)
        self.inp_best_result.setMaximum(100000)
        self.inp_average_result.setMinimum(-100000)
        self.inp_average_result.setMaximum(100000)

        self.inp_max_iter.setValue(500)
        self.inp_similarity.setValue(80)
        self.inp_best_result.setValue(-10)
        self.inp_average_result.setValue(-10000)

        self.inp_similarity_cb.setText("Similar Results")
        self.inp_best_result_cb.setText("Best Result")
        self.inp_average_result_cb.setText("Average Result")
        self.inp_similarity_cb.stateChanged.connect(self.cb_similarity_signal)
        self.inp_best_result_cb.stateChanged.connect(
            self.cb_best_result_signal)
        self.inp_average_result_cb.stateChanged.connect(
            self.cb_average_result_signal)

        self.inp_similarity_cb.setChecked(False)
        self.inp_best_result_cb.setChecked(False)
        self.inp_average_result_cb.setChecked(False)

        self.inp_similarity.setEnabled(True)
        self.inp_best_result.setEnabled(False)
        self.inp_best_result.setStyleSheet("background:#555")
        self.inp_average_result.setEnabled(False)
        self.inp_average_result.setStyleSheet("background:#555")

        self.addRow(self.header_stop)
        self.addRow("Max iter", self.inp_max_iter)
        self.addRow(self.inp_similarity_cb, self.inp_similarity)
        self.addRow(self.inp_best_result_cb, self.inp_best_result)
        self.addRow(self.inp_average_result_cb, self.inp_average_result)
        self.addRow(QHLine())

    def init_row_selection(self):
        self.header_selection.setFont(self.medium_font)
        self.header_selection.setText("Selection")

        self.inp_selection_method.addItem("Fittest Half", "Fittest Half")
        self.inp_selection_method.addItem("Roulette Wheel", "Roulette Wheel")
        self.inp_selection_method.addItem("Random", "Random")
        self.inp_selection_method.addItem("Whole Population",
                                          "Whole Population")
        self.inp_elitism.setMaximum(1)
        self.inp_elitism.setValue(0.01)
        self.inp_elitism.setSingleStep(0.01)

        self.addRow(self.header_selection)
        self.addRow("Selection Method", self.inp_selection_method)
        self.addRow("Elitism Percentage", self.inp_elitism)
        self.addRow(QHLine())

    def init_row_pairing(self):
        self.header_pairing.setFont(self.medium_font)
        self.header_pairing.setText("Pairing")

        self.inp_pairing_method.addItem("Random", "Random")
        self.inp_pairing_method.addItem("Roulette Wheel", "Roulette Wheel")
        self.inp_pairing_method.addItem("Fittest", "Fittest")

        self.addRow(self.header_pairing)
        self.addRow("Pairing Method", self.inp_pairing_method)
        self.addRow(QHLine())

    def init_row_crossover(self):
        self.header_crossover.setFont(self.medium_font)
        self.header_crossover.setText("Crossover")

        self.inp_crossover_method.addItem("Intermediate", "Intermediate")
        self.inp_crossover_method.addItem("Line Intermediate",
                                          "Line Intermediate")
        self.inp_crossover_method.addItem("Heuristic", "Heuristic")
        self.inp_crossover_method.addItem("One point", "One point")
        self.inp_crossover_method.addItem("Two point", "Two point")
        self.inp_crossover_method.addItem("Random", "Random")
        self.inp_mutation_method.setCurrentIndex(2)
        self.inp_crossover_fraction.setMaximum(1)
        self.inp_crossover_fraction.setValue(0.7)
        self.inp_crossover_fraction.setSingleStep(0.05)
        self.intermediate_offset.setMaximum(20)
        self.intermediate_offset.setValue(1.55)
        self.intermediate_offset.setSingleStep(0.05)

        self.addRow(self.header_crossover)
        self.addRow("Crossover Method", self.inp_crossover_method)
        self.addRow("Crossover Fraction", self.inp_crossover_fraction)
        self.addRow("Intermediate Offset", self.intermediate_offset)
        self.addRow(QHLine())

    def init_row_mutation(self):
        self.header_mutation.setFont(self.medium_font)
        self.header_mutation.setText("Mutation")

        self.inp_mutation_method.addItem("Gauss", "Gauss")
        self.inp_mutation_method.addItem("Random", "Random")
        self.inp_mutation_intensity.setMaximum(200)
        self.inp_mutation_intensity.setValue(2)
        self.inp_mutation_intensity.setDecimals(4)

        self.inp_mutation_intensity.setSingleStep(0.01)
        self.inp_mutation_intensity_final.setMaximum(200)
        self.inp_mutation_intensity_final.setDecimals(4)
        self.inp_mutation_intensity_final.setValue(0.001)
        self.inp_mutation_intensity_final.setSingleStep(0.5)

        self.addRow(self.header_mutation)
        self.addRow("Mutation Method", self.inp_mutation_method)
        self.addRow("Mutation Intensity", self.inp_mutation_intensity)
        self.addRow("Final Mutation Intensity",
                    self.inp_mutation_intensity_final)
        self.addRow(QHLine())

    def get_options(self):
        function = self.inp_functions_combo.currentData()
        num_var = self.inp_num_variables.text()
        if self.inp_extrema_min.isChecked():
            extrem = 0
        else:
            extrem = 1
        pop_size = self.inp_pop_size.text()
        low_bound = self.inp_lower_bound.text()
        upp_bound = self.inp_upper_bound.text()
        max_iter = self.inp_max_iter.text()
        sim_results = self.inp_similarity.text()
        best_res = self.inp_best_result.text()
        average_res = self.inp_average_result.text()
        select_method = self.inp_selection_method.currentText()
        elite_percent = self.inp_elitism.text()
        pairing = self.inp_pairing_method.currentText()
        crossover_method = self.inp_crossover_method.currentText()
        crossover_fraction = self.inp_crossover_fraction.text()
        intermediate_offset = self.intermediate_offset.text()
        mutation_method = self.inp_mutation_method.currentText()
        mutation_intensity = self.inp_mutation_intensity.text()
        mutation_intensity_final = self.inp_mutation_intensity_final.text()
        fitness_remapping = self.inp_fitness_remapping.currentText()

        options = {
            "function":
            function,
            "num_var":
            num_var,
            "pop_size":
            int(pop_size),
            "max_iter":
            int(max_iter),
            "lower_bound":
            float(low_bound.replace(",", ".")),
            "upper_bound":
            float(upp_bound.replace(",", ".")),
            "find_max":
            extrem,
            "prints":
            0,
            "average_result":
            float(average_res.replace(",", ".")),
            "best_result":
            float(best_res.replace(",", ".")),
            "similarity":
            float(sim_results.replace(",", ".")),
            "selection":
            select_method,
            "pairing":
            pairing,
            "crossover":
            crossover_method,
            "crossover_fraction":
            float(crossover_fraction.replace(",", ".")),
            "intermediate_offset":
            float(intermediate_offset.replace(",", ".")),
            # 0 mean child will be between parents, 1 mean offset is same as two parent distance
            "mutation":
            mutation_method,
            "mutation_intensity":
            float(mutation_intensity.replace(",", ".")),
            "mutation_intensity_final":
            float(mutation_intensity_final.replace(",", ".")),
            "elitism":
            float(elite_percent.replace(",", ".")),
            "fitness_remapping":
            fitness_remapping
        }

        if not self.inp_similarity_cb.isChecked():
            options["similarity"] = None
        if not self.inp_best_result_cb.isChecked():
            options["best_result"] = None
        if not self.inp_average_result_cb.isChecked():
            options["average_result"] = None
        return options

    def cb_similarity_signal(self):
        if self.inp_similarity_cb.isChecked():
            self.inp_similarity.setEnabled(True)
            self.inp_similarity.setStyleSheet("")
        else:
            self.inp_similarity.setEnabled(False)
            self.inp_similarity.setStyleSheet("background:#555")

    def cb_best_result_signal(self):
        if self.inp_best_result_cb.isChecked():
            self.inp_best_result.setEnabled(True)
            self.inp_best_result.setStyleSheet("")
        else:
            self.inp_best_result.setEnabled(False)
            self.inp_best_result.setStyleSheet("background:#555")

    def cb_average_result_signal(self):
        if self.inp_average_result_cb.isChecked():
            self.inp_average_result.setEnabled(True)
            self.inp_average_result.setStyleSheet("")
        else:
            self.inp_average_result.setEnabled(False)
            self.inp_average_result.setStyleSheet("background:#555")
Esempio n. 9
0
class mainWindow(QObject):

    signalRun = Signal(SpiderThread)
    signalRunApi = Signal(apiTester)
    def __init__(self):
        QObject.__init__(self)  # must init parent QObject,if you want to use signal
        self.widget = QWidget()
        self.ipLabel = QLabel(self.widget)
        self.thread = QThread()
        self.worker = Worker()
        self.worker.moveToThread(self.thread)
        self.man = SpiderThread()
        self.api = apiTester()
        # 1 2:loop 3: time
        self.testStatus = [False,1,0,"ip","mac"]

        # advance config
        self.findCoreStop = True
        self.cleanCacheSet = False
        self.useApiTest = False
        self.showTestProgress = True
        self.saveTestLog = False
        self.saveLogPath = ""
        self.chromePath =  ""
        self.showChrome = False
        self.coreDumpPath = ""

        # ui form
        self.passwordLabel = QLabel(self.widget)

        self.ipLineEdit = QLineEdit(self.widget)
        self.passwordLineEdit = QLineEdit(self.widget)

        self.startBtn = QPushButton(self.widget)
        self.stopBtn = QPushButton(self.widget)

        self.messageBox = QTextEdit(self.widget)
        self.messageBox.setReadOnly(True)

        self.userLabel = QLabel(self.widget)
        self.userLineEdit = QLineEdit(self.widget)

        self.intervalLabel = QLabel(self.widget)
        self.intervalSpinBox = QSpinBox(self.widget)

        self.loopLabel = QLabel(self.widget)
        self.loopSpinBox = QSpinBox(self.widget)

        self.intervalSpinBox.setRange(0,9999)
        self.loopSpinBox.setRange(1,9999)

        self.radioReboot = QRadioButton(self.widget)
        self.radioProvision = QRadioButton(self.widget)
        self.radioFactory = QRadioButton(self.widget)

        # self.apiCheckBox = QCheckBox(self.widget)

        self.menu = QMenu()
        self.gxpAction = QAction("Classic UI")
        self.grp2602Action = QAction("Ant Design UI")
        self.gxpAction.setCheckable(True)
        self.grp2602Action.setCheckable(True)
        self.menu.addAction(self.gxpAction)
        self.menu.addAction(self.grp2602Action)
        self.webLabel = QLabel(self.widget)
        self.webBtn = QPushButton(self.widget)
        self.webBtn.setMenu(self.menu)
        self.clearBtn = QPushButton(self.widget)
        self.messageList = deque()
        self.timer = QTimer()


        self.advanceBtn = QPushButton(self.widget)
        self.infoLabel = QLabel(self.widget)

        # provision widget
        self.provWidget = QWidget(self.widget)
        self.ver1Label = QLabel(self.provWidget)
        self.ver2Label = QLabel(self.provWidget)
        self.ver3Label = QLabel(self.provWidget)
        self.ver1LineEdit = QLineEdit(self.provWidget)
        self.ver2LineEdit = QLineEdit(self.provWidget)
        self.ver3LineEdit = QLineEdit(self.provWidget)

        self.dir1Label = QLabel(self.provWidget)
        self.dir2Label = QLabel(self.provWidget)
        self.dir3Label = QLabel(self.provWidget)
        self.dir1LineEdit = QLineEdit(self.provWidget)
        self.dir2LineEdit = QLineEdit(self.provWidget)
        self.dir3LineEdit = QLineEdit(self.provWidget)

        self.radioHttp = QRadioButton(self.provWidget)
        self.radioHttps = QRadioButton(self.provWidget)
        self.radioTftp = QRadioButton(self.provWidget)
        self.radioFtp = QRadioButton(self.provWidget)
        self.radioFtps = QRadioButton(self.provWidget)
        self.radioWindow = QRadioButton(self.provWidget)

        # advance widget
        self.advanceWidget = QWidget()
        self.checkCoreBox = QCheckBox(self.advanceWidget)
        self.cleanCache = QCheckBox(self.advanceWidget)
        self.checkSaveLogBox = QCheckBox(self.advanceWidget)
        self.selectDirBtn = QPushButton(self.advanceWidget)
        self.saveDirLabel = QLabel(self.advanceWidget)
        self.saveDirLabel.setStyleSheet("background:white")
        self.checkProgressBox = QCheckBox(self.advanceWidget)
        self.advanceOkBtn = QPushButton(self.advanceWidget)
        self.selectChromeBtn = QPushButton(self.advanceWidget)
        self.chromePathLabel = QLabel(self.advanceWidget)
        self.chromePathLabel.setStyleSheet("background:white")
        self.checkShowChromeBox = QCheckBox(self.advanceWidget)
        self.chromeLabel = QLabel(self.advanceWidget)
        self.pcapLabel = QLabel(self.advanceWidget)
        self.apiCheckBox = QCheckBox(self.advanceWidget)
        self.corePathLabel = QLabel(self.advanceWidget)
        self.corePathLabel.setStyleSheet("background:white")
        self.corePathBtn = QPushButton(self.advanceWidget)

        self.interfaceMenu = QComboBox(self.advanceWidget)
        self.interfaceMenu.addItem('Default')

        self.aiOptionBox= QCheckBox(self.advanceWidget)

        a = IFACES
        print(a)
        for i in a.keys():
            print(a[i].description)
            self.interfaceMenu.addItem(a[i].description)

        # connect singal and slot
        self.startBtn.clicked.connect(self.clickedStarBtn)
        self.radioProvision.clicked.connect(self.clickedProvision)
        self.radioReboot.clicked.connect(self.clickedOthers)
        self.radioFactory.clicked.connect(self.clickedOthers)
        self.stopBtn.clicked.connect(self.clickedStopBtn)
        self.grp2602Action.triggered.connect(self.clickedGrp2602)
        self.gxpAction.triggered.connect(self.clickedGxpType)
        self.timer.timeout.connect(self.updateMessage)
        self.apiCheckBox.stateChanged.connect(self.apiTestBoxCheck)
        self.clearBtn.clicked.connect(self.clickedClearBtn)

        self.advanceBtn.clicked.connect(self.clickedAdvanceBtn)
        self.advanceOkBtn.clicked.connect(self.clickedAdvanceOkBtn)
        self.checkSaveLogBox.stateChanged.connect(self.saveLogBoxCheck)
        self.selectChromeBtn.clicked.connect(self.clickedSelectChromeBtn)
        self.selectDirBtn.clicked.connect(self.clickedSelectDirBtn)
        self.corePathBtn.clicked.connect(self.clickedCorePathBtn)

        self.worker.signalJobEnd.connect(self.slotTestStoped)
        self.worker.apiTestFinished.connect(self.slotTestStoped)
        self.signalRun.connect(self.worker.dowork)
        self.signalRunApi.connect(self.worker.doworkApi)

        # self.man.signalUpdateMessage.connect(self.pushMessage)

    def setupUI(self):
        # set text content /value
        self.widget.setWindowTitle("自动重启升降级测试工具")
        self.ipLabel.setText("初始IP:")
        self.passwordLabel.setText("密码:")
        self.startBtn.setText("开始测试")
        self.stopBtn.setText("停止测试")
        self.userLabel.setText("用户名:")
        self.intervalLabel.setText("间隔时间:")
        self.loopLabel.setText("测试次数:")
        self.intervalSpinBox.setValue(130)
        self.radioFactory.setText("恢复出厂")
        self.radioProvision.setText("升降级")
        self.radioReboot.setText("重启")
        self.ver1Label.setText("版本 1:")
        self.ver2Label.setText("版本 2:")
        self.ver3Label.setText("版本 3:")
        self.dir1Label.setText("路径 1:")
        self.dir2Label.setText("路径 2:")
        self.dir3Label.setText("路径 3:")
        self.radioHttp.setText("Http")
        self.radioHttps.setText("Https")
        self.radioTftp.setText("Tftp")
        self.radioFtp.setText("Ftp")
        self.radioFtps.setText("Ftps")
        self.apiCheckBox.setText("使用API测试,配置CoreDump下载路径")
        self.webLabel.setText("网页类型:")
        self.webBtn.setText("请选择UI类型")
        self.clearBtn.setText("清空输入")

        self.advanceWidget.setWindowTitle("高级设置")
        self.advanceBtn.setText("高级设置")
        self.checkCoreBox.setText("发现Core Dump时停止测试")
        self.cleanCache.setText("清除页面cache")
        self.checkSaveLogBox.setText("保存测试日志")
        self.selectDirBtn.setText("浏览")
        self.checkProgressBox.setText("显示底部状态条")
        self.advanceOkBtn.setText("OK")
        self.checkShowChromeBox.setText("测试时显示Chrome浏览器")
        self.selectChromeBtn.setText("浏览")
        self.chromeLabel.setText("Chrome浏览器路径")
        self.infoLabel.setText("未开始测试")
        self.pcapLabel.setText("Net Interface")
        self.corePathBtn.setText("浏览")
        self.radioWindow.setText("网页拖拽文件")
        # self.aiOptionBox.setText("AI")

        #init value
        self.saveDirLabel.hide()
        self.selectDirBtn.hide()

        self.gxpAction.setChecked(True)
        self.radioReboot.click()
        self.radioHttp.click()
        self.stopBtn.setEnabled(False)
        self.passwordLineEdit.setEchoMode(QLineEdit.PasswordEchoOnEdit)

        # set position-------------------------------
        xPos = 20
        yPos = 30
        colum2 = xPos +200

        # line 1
        self.ipLabel.move(xPos,yPos)
        self.intervalLabel.move(colum2,yPos)
        self.intervalSpinBox.move(colum2+60,yPos-2)
        self.ipLineEdit.move(xPos+50,yPos-2)

        # line 2
        line2 = yPos +40
        self.passwordLabel.move(xPos,line2)
        self.passwordLineEdit.move(xPos+50,line2-2)
        self.loopLabel.move(colum2,line2)
        self.loopSpinBox.move(colum2+60,line2-2)

        # line3
        line3 = yPos +80
        self.userLabel.move(xPos,line3)
        self.userLineEdit.move(xPos+50,line3-2)

        self.radioReboot.move(colum2,line3)
        self.radioFactory.move(colum2+60,line3)
        self.radioProvision.move(colum2,line3+30)

        self.webLabel.move(xPos,line3+40)
        self.webBtn.move(xPos+60,line3+35)

        # provWidget
        self.provWidget.resize(400,130)
        self.provWidget.move(xPos,line3+70)
        spaceY = 30
        x = 0
        y = 0
        cl = 200
        self.ver1Label.move(x,y)
        self.ver1LineEdit.move(x+50,y)
        self.ver2Label.move(x,y+spaceY)
        self.ver2LineEdit.move(x+50,y+spaceY)
        self.ver3Label.move(x,y+spaceY*2)
        self.ver3LineEdit.move(x+50,y+spaceY*2)

        self.dir1Label.move(cl,y)
        self.dir1LineEdit.move(cl+50,y)
        self.dir2Label.move(cl,y+spaceY)
        self.dir2LineEdit.move(cl+50,y+spaceY)
        self.dir3Label.move(cl,y+spaceY*2)
        self.dir3LineEdit.move(cl+50,y+spaceY*2)

        self.radioHttp.move(x,y+spaceY*3)
        self.radioHttps.move(x+50,y+spaceY*3)
        self.radioTftp.move(x+110,y+spaceY*3)
        self.radioFtp.move(x+160,y+spaceY*3)
        self.radioFtps.move(x+210,y+spaceY*3)
        self.radioWindow.move(x+265,y+spaceY*3)

        # advance widget
        self.advanceWidget.resize(300,400)
        x = 20
        y = 20
        space = 30

        self.checkCoreBox.move(x,y)
        self.cleanCache.move(x,y+space)
        self.checkProgressBox.move(x,y+space*2)
        self.checkShowChromeBox.move(x,y+space*3)
        self.apiCheckBox.move(x,y+space*4)
        self.corePathBtn.move(x-2,y+space*5-8)
        self.corePathLabel.move(x+35,y+space*5-8)

        y += 40
        self.chromeLabel.move(x,y+space*4+10)
        self.selectChromeBtn.move(x-2,y+space*5)
        self.chromePathLabel.move(x+35,y+space*5+2)

        self.checkSaveLogBox.move(x,y+space*6+10)
        self.selectDirBtn.move(x-2,y+space*7)
        self.saveDirLabel.move(x+35,y+space*7+2)
        self.advanceOkBtn.move(x+170,y+space*10+10)
        self.interfaceMenu.move(x-5,y+space*8+10)
        self.pcapLabel.move(x,y+space*8-2)
        # self.aiOptionBox.move(x, y+space*9+8)
        # set size
        self.messageBox.resize(373,155)
        # self.widget.resize(410,400)
        self.loopSpinBox.resize(60,25)
        self.intervalSpinBox.resize(60,25)
        self.webBtn.resize(100,25)

        self.saveDirLabel.resize(185,22)
        self.selectDirBtn.resize(32,24)
        self.selectChromeBtn.resize(32,24)
        self.chromePathLabel.resize(185,22)
        self.infoLabel.resize(400, 25)
        self.corePathBtn.resize(32,24)
        self.corePathLabel.resize(185,22)
        #
        self.provWidget.hide()
        self.changePosition(True)
        self.widget.show()
        self.loadCache()
    # ----------------end of setupUI ---------------------


    def changePosition(self,hide):
        xPos = 20
        if hide:
            buttonLine = 200
            self.widget.resize(420,415)
        else:
            buttonLine = 310
            self.widget.resize(420,524)

        self.startBtn.move(xPos,buttonLine)
        self.stopBtn.move(xPos+90,buttonLine)
        self.clearBtn.move(xPos+180,buttonLine)
        self.advanceBtn.move(xPos+270,buttonLine)
        self.messageBox.move(xPos,buttonLine+30)
        boxH = self.messageBox.height()
        self.infoLabel.move(xPos,buttonLine+boxH+35)

    def setItemEnable(self,enable):
        self.provWidget.setEnabled(enable)
        self.ipLineEdit.setEnabled(enable)
        self.passwordLineEdit.setEnabled(enable)
        self.userLineEdit.setEnabled(enable)
        self.intervalSpinBox.setEnabled(enable)
        self.loopSpinBox.setEnabled(enable)
        self.radioFactory.setEnabled(enable)
        self.radioReboot.setEnabled(enable)
        self.radioProvision.setEnabled(enable)
        self.advanceBtn.setEnabled(enable)
        self.startBtn.setEnabled(enable)
        self.clearBtn.setEnabled(enable)
        if self.useApiTest:
            self.webBtn.setEnabled(False)
        else:
            self.webBtn.setEnabled(enable)
        self.stopBtn.setEnabled(not enable)

    def outputError(self,str):
        appstr = "<span style=\"color:red\">"
        appstr += str + "</span>"
        self.messageBox.append(appstr)

    def outputWarning(self,str):
        appstr = "<span style=\"color:orange\">"
        appstr += str + "</span>"
        self.messageBox.append(appstr)

    def loadCache(self):
        file = QFile("cache")
        if not file.open(QIODevice.ReadOnly | QIODevice.Text):
            return

        inStream = QTextStream(file)

        # ip
        self.ipLineEdit.setText(inStream.readLine())
        # passwordLabel
        self.passwordLineEdit.setText(inStream.readLine())
        # user
        self.userLineEdit.setText(inStream.readLine())
        # ver1
        self.ver1LineEdit.setText(inStream.readLine())
        self.dir1LineEdit.setText(inStream.readLine())
        # ver2
        self.ver2LineEdit.setText(inStream.readLine())
        self.dir2LineEdit.setText(inStream.readLine())
        # ver3
        self.ver3LineEdit.setText(inStream.readLine())
        self.dir3LineEdit.setText(inStream.readLine())

        self.intervalSpinBox.setValue(int(inStream.readLine()))
        self.loopSpinBox.setValue(int(inStream.readLine()))

        # web type button
        webType = inStream.readLine()
        if webType == "gxpAction":
            self.grp2602Action.setChecked(False)
            self.gxpAction.setChecked(True)
            self.webBtn.setText(self.gxpAction.text())
        else:
            self.grp2602Action.setChecked(True)
            self.gxpAction.setChecked(False)
            self.webBtn.setText(self.grp2602Action.text())

        testType = inStream.readLine()
        if testType == "reboot":
            self.radioReboot.setChecked(True)
        elif testType == "provision":
            self.radioProvision.setChecked(True)
            self.changePosition(False)
            self.provWidget.show()
        else:
            self.radioFactory.setChecked(True)

        serverType = inStream.readLine()
        if serverType == "Http":
            self.radioHttp.setChecked(True)
        elif serverType == "Https":
            self.radioHttps.setChecked(True)
        elif serverType == "Tftp":
            self.radioTftp.setChecked(True)
        elif serverType == "Ftp":
            self.radioFtp.setChecked(True)
        elif serverType == "Ftps":            
            self.radioFtps.setChecked(True)
        else:
            self.radioWindow.setChecked(True)

        if inStream.readLine() == "True":
            self.findCoreStop = True
        else:
            self.findCoreStop = False

        if inStream.readLine() == "True":
            self.cleanCacheSet = True
        else:
            self.cleanCacheSet = False

        if inStream.readLine() == "True":
            self.useApiTest = True
            self.webBtn.setEnabled(False)
        else:
            self.useApiTest = False
            self.corePathBtn.hide()
            self.corePathLabel.hide()

        if inStream.readLine() == "True":
            self.showTestProgress = True
        else:
            self.showTestProgress = False
            self.infoLabel.hide()

        if inStream.readLine() == "True":
            self.showChrome = True
        else:
            self.showChrome = False

        self.chromePath = inStream.readLine()

        if inStream.readLine() == "True":
            self.saveTestLog = True
        else:
            self.saveTestLog = False

        self.saveLogPath = inStream.readLine()

        self.coreDumpPath = inStream.readLine()

        file.close()

    def saveCache(self):
        file = QFile("cache")
        if not file.open(QIODevice.WriteOnly):
            return

        content = self.ipLineEdit.text() + "\n"
        content += self.passwordLineEdit.text() + "\n"
        content += self.userLineEdit.text() + "\n"
        content += self.ver1LineEdit.text() + "\n"
        content += self.dir1LineEdit.text() + "\n"
        content += self.ver2LineEdit.text() + "\n"
        content += self.dir2LineEdit.text() + "\n"
        content += self.ver3LineEdit.text() + "\n"
        content += self.dir3LineEdit.text() + "\n"

        content += str(self.intervalSpinBox.value()) + "\n"
        content += str(self.loopSpinBox.value()) + "\n"

        if self.gxpAction.isChecked():
            content += "gxpAction\n"
        else:
            content += "grp2602Action\n"

        if self.radioReboot.isChecked():
            content += "reboot\n"
        elif self.radioProvision.isChecked():
            content += "provision\n"
        else:
            content += "factory\n"

        if self.radioHttp.isChecked():
            content += "Http\n"
        elif self.radioHttps.isChecked():
            content += "Https\n"
        elif self.radioTftp.isChecked():
            content += "Tftp\n"
        elif self.radioFtp.isChecked():
            content += "Ftp\n"
        elif self.radioFtps.isChecked():
            content += "Ftps\n"
        else :
            content += "Window\n"

        content += str(self.findCoreStop) + "\n"
        content += str(self.cleanCacheSet) + "\n"
        content += str(self.useApiTest) + "\n"
        content += str(self.showTestProgress) + "\n"
        content += str(self.showChrome) + "\n"
        content += self.chromePath +"\n"
        content += str(self.saveTestLog) +"\n"
        content += self.saveLogPath +"\n"
        content += self.coreDumpPath +"\n"

        byteArr = bytes(content,"utf-8")
        file.write(QByteArray(byteArr))
        file.close()


    def checkBeforeRun(self):
        containError = False
        #---------check Ip address--------------
        if self.ipLineEdit.text() == "":
            containError = True
            self.outputError("IP地址不能为空!")
        else:
            pattern = re.compile("^((1[0-9][0-9]\.)|(2[0-4][0-9]\.)|(25[0-5]\.)|([1-9][0-9]\.)|([0-9]\.)){3}((1[0-9][0-9])|(2[0-4][0-9])|(25[0-5])|([1-9][0-9])|([0-9]))$")
            if not pattern.search(self.ipLineEdit.text()):
                containError = True
                self.outputError("IP地址格式错误,检查是否含有多余空格!(仅支持IPV4)")

        #------------------------
        if self.passwordLineEdit.text() == "":
            containError = True
            self.outputError("密码不能为空!")
        if self.userLineEdit.text() == "":
            containError = True
            self.outputError("用户名不能为空!")
        if self.intervalSpinBox.value() <= 40:
            self.outputWarning("间隔时间过短,可能对测试造成影响")
        if not self.radioProvision.isChecked() and not self.radioReboot.isChecked() and \
           not self.radioFactory.isChecked():
            containError = True
            self.outputError("必须选择测试方式(重启,升降级,恢复出厂)")

        # check provision ----------
        if self.radioProvision.isChecked():
            if self.ver1LineEdit.text() == "" or self.ver2LineEdit.text() == "" or \
               self.dir1LineEdit.text() == "" or self.dir2LineEdit.text() == "":
                containError = True
                self.outputError("升降级测试至少填上前两个版本及其路径")

            bin_name = ""
            if os.path.exists(os.path.abspath("config.ini") ):
                f = open(os.path.abspath("config.ini") , "r")
                line = f.readline()
                while line:
                    option = line.split("=")
                    if option[0] == "firmbinname":
                        if option[1].strip('"') != "":
                            filenamebin = option[1].strip()
                            bin_name = filenamebin.strip('"')
                        pass
                    line = f.readline()
                f.close()

            filename = os.path.join(self.dir1LineEdit.text(), bin_name)
            if not os.path.exists(filename) and self.radioWindow.isChecked():
                containError = True
                self.outputError("firmware1 文件不存在!" + filename)
            filename = os.path.join(self.dir2LineEdit.text(), bin_name)
            if not os.path.exists(filename) and self.radioWindow.isChecked():
                containError = True
                self.outputError("firmware2 文件不存在!" + filename)
           

            filename = os.path.join(self.dir3LineEdit.text(), bin_name)
            if self.ver3LineEdit.text() != "" and self.dir3LineEdit.text() == "":
                containError = True
                self.outputError("填写了版本3,但对应路径为空!")
            if self.dir3LineEdit.text() != "" and self.ver3LineEdit.text() == "":
                containError = True
                self.outputError("填写了路径3,但对应版本为空!")
            elif self.dir3LineEdit.text() != "" and self.radioWindow.isChecked() and not os.path.exists(filename):
                containError = True
                self.outputError("firmware3 文件不存在!" + filename)

            if not self.radioFtp.isChecked() and not self.radioFtps.isChecked() and \
               not self.radioHttp.isChecked() and not self.radioHttps.isChecked() and \
               not self.radioTftp.isChecked() and not self.radioWindow.isChecked():
                containError = True
                self.outputError("升降级测试必须选择服务器类型(Tftp,Ftp,Ftps,Http,Https)")
        return containError



    def startTest(self):
        ip = self.ipLineEdit.text()
        passwd = self.passwordLineEdit.text()
        username = self.userLineEdit.text()
        ptime = self.intervalSpinBox.value()
        loop = self.loopSpinBox.value()
        modelType = self.webBtn.text()
        if self.gxpAction.isChecked():
            device_type = "GXP21XX"
        elif self.grp2602Action.isChecked():
            device_type = "GRP260X"

        if self.radioReboot.isChecked():
            task_type = "reboot"
        elif self.radioProvision.isChecked():
            task_type = "provision"
            text_ver1 = self.ver1LineEdit.text()
            text_ver2 = self.ver2LineEdit.text()
            text_ver3 = self.ver3LineEdit.text()
            text_dir1 = self.dir1LineEdit.text()
            text_dir2 = self.dir2LineEdit.text()
            text_dir3 = self.dir3LineEdit.text()
            prov_dict = {"ver1": text_ver1.strip(), "dir1": text_dir1.strip(), "ver2": text_ver2.strip(),
                        "dir2": text_dir2.strip(), "ver3": text_ver3.strip(), "dir3": text_dir3.strip()}

            if self.radioHttp.isChecked():
                self.man.update_prov_setting("HTTP", prov_dict)
            elif self.radioHttps.isChecked():
                self.man.update_prov_setting("HTTPS", prov_dict)
            elif self.radioTftp.isChecked():
                self.man.update_prov_setting("TFTP", prov_dict)
            elif self.radioFtp.isChecked():
                self.man.update_prov_setting("FTP", prov_dict)
            elif self.radioFtps.isChecked():
                self.man.update_prov_setting("FTPS", prov_dict)
            elif self.radioWindow.isChecked():
                self.man.update_prov_setting("browser", prov_dict)

        else:
            task_type = "reset"

        coredump_stop = True
        headless_flag = False
        clean_cache = False
        if self.checkCoreBox.isChecked() == False:
            self.messageBox.append("Find core dump will not stop")
            coredump_stop = False
        if self.cleanCache.isChecked() == True:
            clean_cache = True
            
        if self.checkShowChromeBox.isChecked() == True or self.radioWindow.isChecked() == True:
            headless_flag = False
        else:
            headless_flag = True

        # ai_mode = False
        # if self.aiOptionBox.isChecked() == True:
        #     ai_mode = True

        browser_path = ""
        if self.chromePathLabel.text() != "":
            browser_path = self.chromePathLabel.text()

        self.testStatus = [True,1,0,"ip",""]
        print(self.interfaceMenu.currentText())
        self.man.setStatus(self.testStatus)
        self.man.setMessageList(self.messageList)
        self.man.update_setting(ip.strip(), username.strip(), passwd.strip(), device_type, \
                                task_type, loop, ptime, coredump_stop, headless_flag, browser_path, \
                                clean_cache, self.interfaceMenu.currentText(), False)
    
    def startApiTest(self):
        ip = self.ipLineEdit.text()
        passwd = self.passwordLineEdit.text()
        username = self.userLineEdit.text()
        ptime = self.intervalSpinBox.value()
        loop = self.loopSpinBox.value()
        
        testType = "Reboot"
        if self.radioProvision.isChecked():
            testType = "Provision"
        self.api.setValue(ip,username,passwd,ptime,loop,testType)

        v1 = self.ver1LineEdit.text()
        v2 = self.ver2LineEdit.text()
        v3 = self.ver3LineEdit.text()
        d1 = self.dir1LineEdit.text()
        d2 = self.dir2LineEdit.text()
        d3 = self.dir3LineEdit.text()
        self.api.setVersion(v1,v2,v3,d1,d2,d3)

        self.api.setTestStatus(self.testStatus,self.messageList,self.coreDumpPath)

        if self.radioHttp.isChecked():
            self.api.setServerType("http")
        elif self.radioHttps.isChecked():
            self.api.setServerType("https")
        elif self.radioTftp.isChecked():
            self.api.setServerType("tftp")
        elif self.radioFtp.isChecked():
            self.api.setServerType("ftp")
        else: #self.radioFtps.isChecked()
            self.api.setServerType("ftps")
        
        self.api.setFoundCoreStop(self.findCoreStop)


    # slot ---------------------------------
    def apiTestBoxCheck(self,state):
        if state == 2:
            self.corePathBtn.show()
            self.corePathLabel.show()
        else:
            self.corePathBtn.hide()
            self.corePathLabel.hide()

    def clickedCorePathBtn(self):
        dir = QFileDialog.getExistingDirectory(self.advanceWidget,"选择Core Dump存放路径","/home")
        if dir != "":
            self.corePathLabel.setText(dir)
            self.coreDumpPath = dir

    def clickedSelectDirBtn(self):
        dir = QFileDialog.getExistingDirectory(self.advanceWidget,"选择日志存放路径","/home")
        if dir != "":
            self.saveDirLabel.setText(dir)
            self.saveLogPath = dir

    def clickedSelectChromeBtn(self):
        fileName = QFileDialog.getOpenFileName(self.advanceWidget,"选择谷歌浏览器","/home","Chrome (*.exe)")
        if fileName != "":
            self.chromePathLabel.setText(fileName[0])
            self.chromePath = fileName[0]

    def saveLogBoxCheck(self,state):
        if state == 2: # checked
            self.selectDirBtn.show()
            self.saveDirLabel.show()
        else:
            self.selectDirBtn.hide()
            self.saveDirLabel.hide()

    def clickedAdvanceOkBtn(self):
        self.findCoreStop = self.checkCoreBox.isChecked()
        self.cleanCacheSet = self.cleanCache.isChecked()
        self.useApiTest = self.apiCheckBox.isChecked()
        self.showTestProgress = self.checkProgressBox.isChecked()
        self.saveTestLog = self.checkSaveLogBox.isChecked()
        self.saveLogPath = self.saveDirLabel.text()
        self.showChrome = self.checkShowChromeBox.isChecked()
        self.chromePath = self.chromePathLabel.text()
        self.coreDumpPath = self.corePathLabel.text()

        if self.useApiTest:
            self.webBtn.setEnabled(False)
            self.corePathBtn.show()
            self.corePathLabel.show()
        else:
            self.webBtn.setEnabled(True)
            self.corePathBtn.hide()
            self.corePathLabel.hide()

        if self.showTestProgress:
            self.infoLabel.show()
        else:
            self.infoLabel.hide()
                
        self.saveCache()
        self.advanceWidget.hide()


    def clickedAdvanceBtn(self):
        self.advanceWidget.hide()
        self.checkCoreBox.setChecked(self.findCoreStop)
        self.cleanCache.setChecked(self.cleanCacheSet)
        self.apiCheckBox.setChecked(self.useApiTest)
        self.checkProgressBox.setChecked(self.showTestProgress)
        self.checkSaveLogBox.setChecked(self.saveTestLog)
        self.saveDirLabel.setText(self.saveLogPath)
        self.checkShowChromeBox.setChecked(self.showChrome)
        self.chromePathLabel.setText(self.chromePath)
        self.corePathLabel.setText(self.coreDumpPath)
        self.advanceWidget.show()

    def slotTestStoped(self):
        self.testStatus[0] = False
        self.setItemEnable(True)
        self.timer.stop()
        self.updateMessage()
        self.thread.quit()

        # save Test log
        if self.saveTestLog:
            fileName = time.strftime("%Y_%m_%d.%H_%M_%S.",time.localtime())
            if self.radioReboot.isChecked():
                fileName += "reboot"
            elif self.radioProvision:
                fileName += "provision"
            else:
                fileName += "factoryReset"
            fileName += ".htm"
            if self.saveLogPath == "":
                self.outputWarning("日志地址没有设置,无法保存")
            else:
                fileName = self.saveLogPath + "\\" + fileName
                print(fileName)

                file = QFile(fileName)
                if not file.open(QIODevice.WriteOnly):
                    self.outputError("打开文件错误,保存日志失败")
                    return

                byteArr = bytes(self.messageBox.toHtml(),"utf-8")
                file.write(QByteArray(byteArr))
                file.close()

    def clickedClearBtn(self):
        self.ipLineEdit.setText("")
        self.passwordLineEdit.setText("")
        self.userLineEdit.setText("")
        self.ver1LineEdit.setText("")
        self.dir1LineEdit.setText("")
        self.ver2LineEdit.setText("")
        self.dir2LineEdit.setText("")
        self.ver3LineEdit.setText("")
        self.dir3LineEdit.setText("")

    def clickedStarBtn(self):
        if self.checkBeforeRun():
            return
        self.messageBox.clear()
        self.saveCache()
        self.messageBox.append("Init Setting...")
        self.setItemEnable(False)
        self.timer.start(500)
        self.thread.start()

        # deside use what to test
        if self.useApiTest:
            if self.radioFactory.isChecked():
                self.outputWarning("Api not support Factory Reset, will test as Gxp type web driver")	
                self.clickedGxpType()
                self.startTest()
                self.signalRun.emit(self.man)
            else:
                self.startApiTest()
                self.signalRunApi.emit(self.api)
        else:
            self.startTest()
            self.signalRun.emit(self.man)

    def clickedStopBtn(self):
        self.stopBtn.setEnabled(False)
        self.testStatus[0] = False
        self.man.quit()
        self.outputWarning("正在停止...")

    def clickedProvision(self):
        self.provWidget.show()
        self.changePosition(False)

    def clickedOthers(self):
        self.provWidget.hide()
        self.changePosition(True)

    def clickedGxpType(self):
        self.gxpAction.setChecked(True)
        self.grp2602Action.setChecked(False)
        self.webBtn.setText(self.gxpAction.text())

    def clickedGrp2602(self):
        self.gxpAction.setChecked(False)
        self.grp2602Action.setChecked(True)
        self.webBtn.setText(self.grp2602Action.text())

    def updateMessage(self):
        while len(self.messageList) >0:
            info = self.messageList.popleft()
            self.messageBox.append(info)
        if self.testStatus[0] == False:
            self.infoLabel.setText("未开始测试")
        else:
            info = "第" + str(self.testStatus[1]) + "次测试   "
            if self.testStatus[2] > 0:
                info += "等待:{} 秒".format( self.testStatus[2] )
            else:
                info += "运行中"
            
            info += "  " + self.testStatus[3]
            info += "  " + self.testStatus[4]
            self.infoLabel.setText(info)
Esempio n. 10
0
class EMMAResultChart(QDialog):
    N_DISPLAY_SAMPLES = 200

    def __init__(self, parent=None, toolbar=False):
        flags = Qt.Window | Qt.WindowTitleHint | Qt.CustomizeWindowHint | Qt.WindowCloseButtonHint
        super().__init__(parent=parent, f=flags)
        self.setWindowTitle(self.tr("EMMA Result Chart"))
        self.figure = plt.figure(figsize=(6, 8))
        self.canvas = FigureCanvas(self.figure)
        self.toolbar = NavigationToolbar(self.canvas, self)
        self.main_layout = QGridLayout(self)
        self.main_layout.addWidget(self.toolbar, 0, 0)
        self.main_layout.addWidget(self.canvas, 1, 0)
        if not toolbar:
            self.toolbar.hide()
        self.supported_scales = [("log-linear", self.tr("Log-linear")),
                                 ("log", self.tr("Log")),
                                 ("phi", self.tr("φ")),
                                 ("linear", self.tr("Linear"))]
        self.control_group = QGroupBox(self.tr("Control"))
        self.control_group.setSizePolicy(QSizePolicy.MinimumExpanding,
                                         QSizePolicy.Fixed)
        self.control_layout = QGridLayout(self.control_group)
        self.main_layout.addWidget(self.control_group, 0, 1, 2, 1)
        self.scale_label = QLabel(self.tr("Scale"))
        self.scale_combo_box = QComboBox()
        self.scale_combo_box.addItems(
            [name for key, name in self.supported_scales])
        self.scale_combo_box.currentIndexChanged.connect(self.update_chart)
        self.control_layout.addWidget(self.scale_label, 0, 0)
        self.control_layout.addWidget(self.scale_combo_box, 0, 1)

        self.supported_distances = ("1-norm", "2-norm", "3-norm", "4-norm",
                                    "MSE", "log10MSE", "cosine", "angular")
        self.distance_label = QLabel(self.tr("Distance"))
        self.distance_combo_box = QComboBox()
        self.distance_combo_box.addItems(self.supported_distances)
        self.distance_combo_box.setCurrentText("log10MSE")
        self.distance_combo_box.currentIndexChanged.connect(self.update_chart)
        self.control_layout.addWidget(self.distance_label, 1, 0)
        self.control_layout.addWidget(self.distance_combo_box, 1, 1)
        self.animated_checkbox = QCheckBox(self.tr("Animated"))
        self.animated_checkbox.setChecked(False)
        self.animated_checkbox.stateChanged.connect(self.on_animated_changed)
        self.control_layout.addWidget(self.animated_checkbox, 2, 0)
        self.interval_label = QLabel(self.tr("Interval [ms]"))
        self.interval_input = QSpinBox()
        self.interval_input.setRange(0, 10000)
        self.interval_input.setValue(30)
        self.interval_input.valueChanged.connect(self.update_chart)
        self.control_layout.addWidget(self.interval_label, 3, 0)
        self.control_layout.addWidget(self.interval_input, 3, 1)
        self.repeat_check_box = QCheckBox(self.tr("Repeat"))
        self.repeat_check_box.setChecked(False)
        self.repeat_check_box.stateChanged.connect(self.update_chart)
        self.save_button = QPushButton(self.tr("Save"))
        self.save_button.clicked.connect(self.save_animation)
        self.control_layout.addWidget(self.repeat_check_box, 4, 0)
        self.control_layout.addWidget(self.save_button, 4, 1)

        self.animation = None
        self.last_result = None

        self.normal_msg = QMessageBox(parent=self)
        self.file_dialog = QFileDialog(parent=self)
        self.on_animated_changed()

    @property
    def scale(self) -> str:
        index = self.scale_combo_box.currentIndex()
        key, name = self.supported_scales[index]
        return key

    @property
    def transfer(self) -> typing.Callable:
        if self.scale == "log-linear":
            return lambda classes_φ: convert_φ_to_μm(classes_φ)
        elif self.scale == "log":
            return lambda classes_φ: np.log(convert_φ_to_μm(classes_φ))
        elif self.scale == "phi":
            return lambda classes_φ: classes_φ
        elif self.scale == "linear":
            return lambda classes_φ: convert_φ_to_μm(classes_φ)

    @property
    def xlabel(self) -> str:
        if self.scale == "log-linear":
            return self.tr("Grain-size [μm]")
        elif self.scale == "log":
            return self.tr("Ln(grain-size in μm)")
        elif self.scale == "phi":
            return self.tr("Grain-size [φ]")
        elif self.scale == "linear":
            return self.tr("Grain-size [μm]")

    @property
    def ylabel(self) -> str:
        return self.tr("Frequency")

    @property
    def xlog(self) -> bool:
        if self.scale == "log-linear":
            return True
        else:
            return False

    @property
    def distance(self) -> str:
        return self.distance_combo_box.currentText()

    @property
    def interval(self) -> float:
        return self.interval_input.value()

    @property
    def repeat(self) -> bool:
        return self.repeat_check_box.isChecked()

    def update_chart(self):
        if self.last_result is not None:
            self.show_result(self.last_result)

    def on_animated_changed(self):
        if self.animated_checkbox.isChecked():
            enabled = True
        else:
            enabled = False
        self.interval_label.setEnabled(enabled)
        self.interval_input.setEnabled(enabled)
        self.repeat_check_box.setEnabled(enabled)
        self.save_button.setEnabled(enabled)
        self.update_chart()

    def show_final_result(self, result: EMMAResult):
        self.last_result = result
        self.figure.clear()
        if self.animation is not None:
            self.animation._stop()
            self.animation = None
        classes = self.transfer(result.dataset.classes_φ)
        sample_indexes = np.linspace(1, result.n_samples, result.n_samples)
        iteration_indexes = np.linspace(1, result.n_iterations,
                                        result.n_iterations)
        first_result = next(result.history)

        def get_valid(values):
            values = np.array(values)
            return values[~np.isinf(values) & ~np.isnan(values)]

        if self.distance == "cosine":
            min_class_wise_distance = np.max(
                get_valid(result.get_class_wise_distance_series(
                    self.distance)))
            max_class_wise_distance = np.min(
                get_valid(
                    first_result.get_class_wise_distance_series(
                        self.distance)))
            min_sample_wise_distance = np.max(
                get_valid(result.get_sample_wise_distance_series(
                    self.distance)))
            max_sample_wise_distance = np.min(
                get_valid(
                    first_result.get_sample_wise_distance_series(
                        self.distance)))
        else:
            min_class_wise_distance = np.min(
                get_valid(result.get_class_wise_distance_series(
                    self.distance)))
            max_class_wise_distance = np.max(
                get_valid(
                    first_result.get_class_wise_distance_series(
                        self.distance)))
            min_sample_wise_distance = np.min(
                get_valid(result.get_sample_wise_distance_series(
                    self.distance)))
            max_sample_wise_distance = np.max(
                get_valid(
                    first_result.get_sample_wise_distance_series(
                        self.distance)))
        d_class_wise_distance = max_class_wise_distance - min_class_wise_distance
        min_class_wise_distance -= d_class_wise_distance / 10
        max_class_wise_distance += d_class_wise_distance / 10
        d_sample_wise_distance = max_sample_wise_distance - min_sample_wise_distance
        min_sample_wise_distance -= d_sample_wise_distance / 10
        max_sample_wise_distance += d_sample_wise_distance / 10

        distance_history_axes = self.figure.add_subplot(3, 1, 1)
        distance_history_axes.plot(iteration_indexes,
                                   result.get_distance_series(self.distance))
        distance_history_axes.set_xlim(iteration_indexes[0],
                                       iteration_indexes[-1])
        distance_history_axes.set_xlabel(self.tr("Iteration index"))
        distance_history_axes.set_ylabel(self.tr("Distance"))
        distance_history_axes.set_title(self.tr("Distance history"))

        class_wise_distance_axes = self.figure.add_subplot(3, 2, 3)
        if self.xlog:
            class_wise_distance_axes.set_xscale("log")
        class_wise_distance_axes.plot(
            classes, result.get_class_wise_distance_series(self.distance))
        class_wise_distance_axes.set_xlim(classes[0], classes[-1])
        class_wise_distance_axes.set_ylim(min_class_wise_distance,
                                          max_class_wise_distance)
        class_wise_distance_axes.set_xlabel(self.xlabel)
        class_wise_distance_axes.set_ylabel(self.tr("Distance"))
        class_wise_distance_axes.set_title(self.tr("Class-wise distances"))

        sample_wise_distance_axes = self.figure.add_subplot(3, 2, 4)
        sample_wise_distance_axes.plot(
            sample_indexes,
            result.get_sample_wise_distance_series(self.distance))
        sample_wise_distance_axes.set_xlim(sample_indexes[0],
                                           sample_indexes[-1])
        sample_wise_distance_axes.set_ylim(min_sample_wise_distance,
                                           max_sample_wise_distance)
        sample_wise_distance_axes.set_xlabel(self.tr("Sample index"))
        sample_wise_distance_axes.set_ylabel(self.tr("Distance"))
        sample_wise_distance_axes.set_title(self.tr("Sample-wise distances"))

        # get the mode size of each end-members
        modes = [(i, result.dataset.classes_μm[np.unravel_index(
            np.argmax(result.end_members[i]), result.end_members[i].shape)])
                 for i in range(result.n_members)]
        # sort them by mode size
        modes.sort(key=lambda x: x[1])
        end_member_axes = self.figure.add_subplot(3, 2, 5)
        if self.xlog:
            end_member_axes.set_xscale("log")
        for i_em, (index, _) in enumerate(modes):
            end_member_axes.plot(classes,
                                 result.end_members[index],
                                 c=plt.get_cmap()(i_em),
                                 label=self.tr("EM{0}").format(i_em + 1))
        end_member_axes.set_xlim(classes[0], classes[-1])
        end_member_axes.set_ylim(0.0,
                                 round(np.max(result.end_members) * 1.2, 2))
        end_member_axes.set_xlabel(self.xlabel)
        end_member_axes.set_ylabel(self.ylabel)
        end_member_axes.set_title(self.tr("End-members"))
        if result.n_members < 6:
            end_member_axes.legend(loc="upper left")

        if result.n_samples > self.N_DISPLAY_SAMPLES:
            interval = result.n_samples // self.N_DISPLAY_SAMPLES
        else:
            interval = 1
        proportion_axes = self.figure.add_subplot(3, 2, 6)
        bottom = np.zeros(result.n_samples)
        for i_em, (index, _) in enumerate(modes):
            proportion_axes.bar(sample_indexes[::interval],
                                result.fractions[:, index][::interval],
                                bottom=bottom[::interval],
                                width=interval,
                                color=plt.get_cmap()(i_em))
            bottom += result.fractions[:, index]
        proportion_axes.set_xlim(sample_indexes[0], sample_indexes[-1])
        proportion_axes.set_ylim(0.0, 1.0)
        proportion_axes.set_xlabel(self.tr("Sample index"))
        proportion_axes.set_ylabel(self.tr("Proportion"))
        proportion_axes.set_title(self.tr("EM abundances"))
        self.figure.tight_layout()
        self.canvas.draw()

    def show_history_animation(self, result: EMMAResult):
        self.last_result = result
        self.figure.clear()
        if self.animation is not None:
            self.animation._stop()
            self.animation = None

        classes = self.transfer(result.dataset.classes_φ)
        sample_indexes = np.linspace(1, result.n_samples, result.n_samples)
        iteration_indexes = np.linspace(1, result.n_iterations,
                                        result.n_iterations)
        distance_series = result.get_distance_series(self.distance)
        min_distance, max_distance = np.min(distance_series), np.max(
            distance_series)
        first_result = next(result.history)

        def get_valid(values):
            values = np.array(values)
            return values[~np.isinf(values) & ~np.isnan(values)]

        if self.distance == "cosine":
            min_class_wise_distance = np.max(
                get_valid(result.get_class_wise_distance_series(
                    self.distance)))
            max_class_wise_distance = np.min(
                get_valid(
                    first_result.get_class_wise_distance_series(
                        self.distance)))
            min_sample_wise_distance = np.max(
                get_valid(result.get_sample_wise_distance_series(
                    self.distance)))
            max_sample_wise_distance = np.min(
                get_valid(
                    first_result.get_sample_wise_distance_series(
                        self.distance)))
        else:
            min_class_wise_distance = np.min(
                get_valid(result.get_class_wise_distance_series(
                    self.distance)))
            max_class_wise_distance = np.max(
                get_valid(
                    first_result.get_class_wise_distance_series(
                        self.distance)))
            min_sample_wise_distance = np.min(
                get_valid(result.get_sample_wise_distance_series(
                    self.distance)))
            max_sample_wise_distance = np.max(
                get_valid(
                    first_result.get_sample_wise_distance_series(
                        self.distance)))
        d_class_wise_distance = max_class_wise_distance - min_class_wise_distance
        min_class_wise_distance -= d_class_wise_distance / 10
        max_class_wise_distance += d_class_wise_distance / 10
        d_sample_wise_distance = max_sample_wise_distance - min_sample_wise_distance
        min_sample_wise_distance -= d_sample_wise_distance / 10
        max_sample_wise_distance += d_sample_wise_distance / 10

        self.distance_history_axes = self.figure.add_subplot(3, 1, 1)
        self.distance_history_axes.plot(iteration_indexes, distance_series)
        self.distance_history_axes.set_xlim(iteration_indexes[0],
                                            iteration_indexes[-1])
        self.distance_history_axes.set_xlabel(self.tr("Iteration index"))
        self.distance_history_axes.set_ylabel(self.tr("Distance"))
        self.distance_history_axes.set_title(self.tr("Distance history"))

        self.class_wise_distance_axes = self.figure.add_subplot(3, 2, 3)
        if self.xlog:
            self.class_wise_distance_axes.set_xscale("log")
        self.class_wise_distance_axes.set_xlim(classes[0], classes[-1])
        self.class_wise_distance_axes.set_ylim(min_class_wise_distance,
                                               max_class_wise_distance)
        self.class_wise_distance_axes.set_xlabel(self.xlabel)
        self.class_wise_distance_axes.set_ylabel(self.tr("Distance"))
        self.class_wise_distance_axes.set_title(
            self.tr("Class-wise distances"))

        self.sample_wise_distance_axes = self.figure.add_subplot(3, 2, 4)
        self.sample_wise_distance_axes.set_xlim(sample_indexes[0],
                                                sample_indexes[-1])
        self.sample_wise_distance_axes.set_ylim(min_sample_wise_distance,
                                                max_sample_wise_distance)
        self.sample_wise_distance_axes.set_xlabel(self.tr("Sample index"))
        self.sample_wise_distance_axes.set_ylabel(self.tr("Distance"))
        self.sample_wise_distance_axes.set_title(
            self.tr("Sample-wise distances"))

        # get the mode size of each end-members
        self.modes = [(i, result.dataset.classes_μm[np.unravel_index(
            np.argmax(result.end_members[i]), result.end_members[i].shape)])
                      for i in range(result.n_members)]
        # sort them by mode size
        self.modes.sort(key=lambda x: x[1])
        self.end_member_axes = self.figure.add_subplot(3, 2, 5)
        if self.xlog:
            self.end_member_axes.set_xscale("log")
        self.end_member_axes.set_xlim(classes[0], classes[-1])
        self.end_member_axes.set_ylim(
            0.0, round(np.max(result.end_members) * 1.2, 2))
        self.end_member_axes.set_xlabel(self.xlabel)
        self.end_member_axes.set_ylabel(self.ylabel)
        self.end_member_axes.set_title(self.tr("End-members"))

        if result.n_samples > self.N_DISPLAY_SAMPLES:
            interval = result.n_samples // self.N_DISPLAY_SAMPLES
        else:
            interval = 1
        self.proportion_axes = self.figure.add_subplot(3, 2, 6)
        self.proportion_axes.set_xlim(sample_indexes[0] - 0.5,
                                      sample_indexes[-1] - 0.5)
        self.proportion_axes.set_ylim(0.0, 1.0)
        self.proportion_axes.set_xlabel(self.tr("Sample index"))
        self.proportion_axes.set_ylabel(self.tr("Proportion"))
        self.proportion_axes.set_title(self.tr("EM abundances"))

        # self.figure.tight_layout()
        # self.canvas.draw()
        def init():
            self.iteration_position_line = self.distance_history_axes.plot(
                [1, 1], [min_distance, max_distance], c="black")[0]
            self.class_wise_distance_curve = self.class_wise_distance_axes.plot(
                classes,
                result.get_class_wise_distance_series(self.distance),
                c=plt.get_cmap()(0))[0]
            self.sample_wise_distance_curve = self.sample_wise_distance_axes.plot(
                sample_indexes,
                result.get_sample_wise_distance_series(self.distance),
                c=plt.get_cmap()(0))[0]
            self.end_member_curves = []
            for i_em, (index, _) in enumerate(self.modes):
                end_member_curve = self.end_member_axes.plot(
                    classes,
                    result.end_members[index],
                    c=plt.get_cmap()(i_em),
                    label=self.tr("EM{0}").format(i_em + 1))[0]
                self.end_member_curves.append(end_member_curve)
            bottom = np.zeros(result.n_samples)
            self.fraction_bars = []
            self.patches = []
            for i_em, (index, _) in enumerate(self.modes):
                bar = self.proportion_axes.bar(
                    sample_indexes[::interval],
                    result.fractions[:, index][::interval],
                    bottom=bottom[::interval],
                    width=interval,
                    color=plt.get_cmap()(i_em))
                self.fraction_bars.append(bar)
                self.patches.extend(bar.patches)
                bottom += result.fractions[:, index]
            return self.iteration_position_line, self.class_wise_distance_curve, self.sample_wise_distance_curve, *(
                self.end_member_curves + self.patches)

        def animate(args):
            iteration, current = args
            self.iteration_position_line.set_xdata([iteration, iteration])
            self.class_wise_distance_curve.set_ydata(
                current.get_class_wise_distance_series(self.distance))
            self.sample_wise_distance_curve.set_ydata(
                current.get_sample_wise_distance_series(self.distance))
            for i_em, (index, _) in enumerate(self.modes):
                self.end_member_curves[i_em].set_ydata(
                    current.end_members[index])
            bottom = np.zeros(current.n_samples)
            for i_em, (index, _) in enumerate(self.modes):
                for rect, height, y in zip(
                        self.fraction_bars[i_em].patches,
                        current.fractions[:, index][::interval],
                        bottom[::interval]):
                    rect.set_height(height)
                    rect.set_y(y)
                bottom += current.fractions[:, index]
            return self.iteration_position_line, self.class_wise_distance_curve, self.sample_wise_distance_curve, *(
                self.end_member_curves + self.patches)

        self.animation = FuncAnimation(self.figure,
                                       animate,
                                       init_func=init,
                                       frames=enumerate(result.history),
                                       interval=self.interval,
                                       blit=True,
                                       repeat=self.repeat,
                                       repeat_delay=3.0,
                                       save_count=result.n_iterations)

    def show_result(self, result: EMMAResult):
        if self.animated_checkbox.isChecked():
            self.show_history_animation(result)
        else:
            self.show_final_result(result)

    def save_animation(self):
        if self.last_result is not None:
            filename, format_str = self.file_dialog.getSaveFileName(
                self, self.tr("Save the animation of this EMMA result"), None,
                self.
                tr("MPEG-4 Video File (*.mp4);;Graphics Interchange Format (*.gif)"
                   ))
            if filename is None or filename == "":
                return
            progress = QProgressDialog(self)
            progress.setRange(0, 100)
            progress.setLabelText(
                self.tr("Saving Animation [{0} Frames]").format(
                    self.last_result.n_iterations))
            canceled = False

            def save_callback(i, n):
                if progress.wasCanceled():
                    nonlocal canceled
                    canceled = True
                    raise StopIteration()
                progress.setValue((i + 1) / n * 100)
                QCoreApplication.processEvents()

            self.show_history_animation(self.last_result)
            # plt.rcParams["savefig.dpi"] = 120.0
            if "*.gif" in format_str:
                if not ImageMagickWriter.isAvailable():
                    self.normal_msg.setWindowTitle(self.tr("Error"))
                    self.normal_msg.setText(
                        self.
                        tr("ImageMagick is not installed, please download and install it from its offical website (https://imagemagick.org/index.php)."
                           ))
                    self.normal_msg.exec_()
                else:
                    self.animation.save(filename,
                                        writer="imagemagick",
                                        fps=30,
                                        progress_callback=save_callback)
            elif "*.mp4" in format_str:
                if not FFMpegWriter.isAvailable():
                    self.normal_msg.setWindowTitle(self.tr("Error"))
                    self.normal_msg.setText(
                        self.
                        tr("FFMpeg is not installed, please download and install it from its offical website (https://ffmpeg.org/)."
                           ))
                    self.normal_msg.exec_()
                else:
                    self.animation.save(filename,
                                        writer="ffmpeg",
                                        fps=30,
                                        progress_callback=save_callback)
            # plt.rcParams["savefig.dpi"] = 300.0
            if not canceled:
                progress.setValue(100)
Esempio n. 11
0
class ControlFrame(QFrame):
    def __init__(self, dataset, display_panel, threads):
        super().__init__()
        if isinstance(display_panel, DisplayFrame):
            self.display_panel = display_panel
        else:
            raise TypeError("'display_panel' must be the instance of "
                            "'DisplayFrame'")
        self.dataset = dataset
        self.threads = threads

        self.__layout = QVBoxLayout()
        self.setLayout(self.__layout)
        self.__layout.setContentsMargins(0, 0, 0, 0)

        self.__set_running_options_ui()
        self.__set_fuzzy_set_operation_types_ui()
        self.__set_fuzzy_variables_ui()
        self.__set_fuzzy_rules_ui()
        self.__set_console_ui()

    def __set_running_options_ui(self):
        group_box = QGroupBox("Running Options")
        inner_layout = QHBoxLayout()
        group_box.setLayout(inner_layout)

        self.data_selector = QComboBox()
        self.data_selector.addItems(list(self.dataset.keys()))
        self.data_selector.setStatusTip("Select the road map case.")
        self.data_selector.currentIndexChanged.connect(self.__change_map)

        self.fps = QSpinBox()
        self.fps.setMinimum(1)
        self.fps.setMaximum(60)
        self.fps.setValue(20)
        self.fps.setStatusTip(
            "The re-drawing rate for car simulator. High fps "
            "may cause the plot shows discontinuously.")

        self.start_btn = QPushButton("Run")
        self.start_btn.setStatusTip("Run the car.")
        self.start_btn.clicked.connect(self.__run)

        self.stop_btn = QPushButton("Stop")
        self.stop_btn.setStatusTip("Force the simulation stop running.")
        self.stop_btn.setDisabled(True)

        self.save_btn = QPushButton()
        self.save_btn.setIcon(QIcon(':/icons/save_icon.png'))
        self.save_btn.setStatusTip("Save every details for the last time "
                                   "running.")
        self.save_btn.clicked.connect(self.__save_results)
        self.save_btn.setDisabled(True)

        self.__change_map()
        inner_layout.addWidget(self.data_selector, 1)
        inner_layout.addWidget(QLabel("FPS:"))
        inner_layout.addWidget(self.fps)
        inner_layout.addWidget(self.start_btn)
        inner_layout.addWidget(self.stop_btn)
        inner_layout.addWidget(self.save_btn)

        self.__layout.addWidget(group_box)

    def __set_fuzzy_set_operation_types_ui(self):
        group_box = QGroupBox("Fuzzy Sets Operation Types")
        inner_layout = QFormLayout()
        group_box.setLayout(inner_layout)

        self.implication_selections = RadioButtonSet([
            ("imp_dr", QRadioButton("Dienes-Rescher")),
            ("imp_l", QRadioButton("Lukasieweicz")),
            ("imp_z", QRadioButton("Zadel")), ("imp_g", QRadioButton("Godel")),
            ("imp_m", QRadioButton("Mamdani")),
            ("imp_p", QRadioButton("Product"))
        ])
        self.combination_vars_selections = RadioButtonSet([
            ("tn_min", QRadioButton("Minimum")),
            ("tn_ap", QRadioButton("Algebraic Product")),
            ("tn_bp", QRadioButton("Bounded Product")),
            ("tn_dp", QRadioButton("Drastic Product"))
        ])
        self.combination_rules_selections = RadioButtonSet([
            ("tc_max", QRadioButton("Maximum")),
            ("tc_as", QRadioButton("Algebraic Sum")),
            ("tc_bs", QRadioButton("Bounded Sum")),
            ("tc_ds", QRadioButton("Drastic Sum"))
        ])
        self.defuzzifier_selections = RadioButtonSet([
            ("gravity_center", QRadioButton("Center of Gravity")),
            ("maxima_mean", QRadioButton("Mean of Maxima")),
            ("modified_maxima_mean", QRadioButton("Modified Mean of Maxima"))
        ])

        self.implication_selections.set_selected('imp_m')
        self.combination_vars_selections.set_selected('tn_min')
        self.combination_rules_selections.set_selected('tc_max')
        self.defuzzifier_selections.set_selected('gravity_center')

        self.implication_selections.setStatusTip("Choose the method for fuzzy "
                                                 "implication.")
        self.combination_vars_selections.setStatusTip(
            "Choose the method of "
            "combination of multiple "
            "fuzzy variables.")
        self.combination_rules_selections.setStatusTip("Choose the method of "
                                                       "combination of "
                                                       "multiple fuzzy rules.")
        self.defuzzifier_selections.setStatusTip("Choose the method for the "
                                                 "defuzifier.")

        inner_layout.addRow(QLabel("Implication:"),
                            self.implication_selections)
        inner_layout.addRow(QLabel("Combination of Variables:"),
                            self.combination_vars_selections)
        inner_layout.addRow(QLabel("Combination of Rules:"),
                            self.combination_rules_selections)
        inner_layout.addRow(QLabel("Defuzzifier:"),
                            self.defuzzifier_selections)

        self.__layout.addWidget(group_box)

    def __set_fuzzy_variables_ui(self):
        group_box = QGroupBox("Fuzzy Variables Settings")
        group_box.setStatusTip("Set the membership functions for each fuzzy "
                               "variable.")
        inner_layout = QVBoxLayout()
        self.fuzzyvar_setting_stack = QStackedWidget()
        self.fuzzyvar_ui_selection = RadioButtonSet([
            ("front", QRadioButton("Front Distance Radar")),
            ("lrdiff", QRadioButton("(Left-Right) Distance Radar")),
            ("consequence", QRadioButton("Consequence"))
        ])
        self.fuzzyvar_setting_dist_front = FuzzierVarSetting()
        self.fuzzyvar_setting_dist_front.small.mean.setValue(5)
        self.fuzzyvar_setting_dist_front.medium.mean.setValue(12)
        self.fuzzyvar_setting_dist_front.large.mean.setValue(20)

        self.fuzzyvar_setting_dist_lrdiff = FuzzierVarSetting()
        self.fuzzyvar_setting_dist_lrdiff.small.mean.setValue(-10)
        self.fuzzyvar_setting_dist_lrdiff.medium.mean.setValue(0)
        self.fuzzyvar_setting_dist_lrdiff.large.mean.setValue(10)

        self.fuzzyvar_setting_consequence = FuzzierVarSetting()
        self.fuzzyvar_setting_consequence.small.mean.setValue(-12)
        self.fuzzyvar_setting_consequence.small.sd.setValue(20)
        self.fuzzyvar_setting_consequence.medium.mean.setValue(0)
        self.fuzzyvar_setting_consequence.medium.sd.setValue(20)
        self.fuzzyvar_setting_consequence.large.mean.setValue(12)
        self.fuzzyvar_setting_consequence.large.sd.setValue(20)

        inner_layout.addWidget(self.fuzzyvar_ui_selection)
        inner_layout.addWidget(self.fuzzyvar_setting_stack)
        group_box.setLayout(inner_layout)

        self.fuzzyvar_setting_stack.addWidget(self.fuzzyvar_setting_dist_front)
        self.fuzzyvar_setting_stack.addWidget(
            self.fuzzyvar_setting_dist_lrdiff)
        self.fuzzyvar_setting_stack.addWidget(
            self.fuzzyvar_setting_consequence)

        self.fuzzyvar_ui_selection.sig_rbtn_changed.connect(
            self.__change_fuzzyvar_setting_ui_stack)

        self.__layout.addWidget(group_box)

    def __set_fuzzy_rules_ui(self):
        antecedents = ('small', 'medium', 'large')

        group_box = QGroupBox("Fuzzy Rules Setting")
        inner_layout = QVBoxLayout()
        group_box.setStatusTip("Set the rules for the fuzzy system.")

        self.rules_setting = FuzzyRulesSetting(
            [p for p in itertools.product(antecedents, repeat=2)])
        self.rules_setting.set_consequence_fuzzysets(
            ('large', 'small', 'small', 'large', 'small', 'small', 'large',
             'small', 'small'))

        inner_layout.addWidget(self.rules_setting)
        group_box.setLayout(inner_layout)
        self.__layout.addWidget(group_box)

    def __set_console_ui(self):
        self.__console = QTextEdit()
        self.__console.setReadOnly(True)
        self.__console.setStatusTip("Show the logs of status changing.")
        self.__layout.addWidget(self.__console)

    @Slot(str)
    def __change_fuzzyvar_setting_ui_stack(self, name):
        if name == 'front':
            self.fuzzyvar_setting_stack.setCurrentIndex(0)
        elif name == 'lrdiff':
            self.fuzzyvar_setting_stack.setCurrentIndex(1)
        else:
            self.fuzzyvar_setting_stack.setCurrentIndex(2)

    @Slot()
    def __change_map(self):
        self.__current_data = self.dataset[self.data_selector.currentText()]
        self.__car = Car(self.__current_data['start_pos'],
                         self.__current_data['start_angle'], 3,
                         self.__current_data['route_edge'])
        self.display_panel.change_map(self.__current_data)

    @Slot(str)
    def __print_console(self, text):
        self.__console.append(text)

    @Slot(list)
    def __get_results(self, results):
        """Get the results of last running and draw the path of it."""
        self.results = results
        self.display_panel.show_path([d['x'] for d in results],
                                     [d['y'] for d in results])

    @Slot()
    def __save_results(self):
        save_dir = QFileDialog.getExistingDirectory(self,
                                                    'Select Saving Directory')
        file4d_filepath = os.path.join(save_dir, 'train4D.txt')
        file6d_filepath = os.path.join(save_dir, 'train6D.txt')
        with open(file4d_filepath, 'w') as file4d:
            for result in self.results:
                file4d.write('{:.7f} {:.7f} {:.7f} {:.7f}\n'.format(
                    result['front_dist'], result['right_dist'],
                    result['left_dist'], result['wheel_angle']))
        with open(file6d_filepath, 'w') as file6d:
            for result in self.results:
                file6d.write(
                    '{:.7f} {:.7f} {:.7f} {:.7f} {:.7f} {:.7f}\n'.format(
                        result['x'], result['y'], result['front_dist'],
                        result['right_dist'], result['left_dist'],
                        result['wheel_angle']))
        self.__print_console('Note: Detailed results have been saved in both'
                             ' "%s" and "%s".' %
                             (file4d_filepath, file6d_filepath))

    @Slot()
    def __init_widgets(self):
        self.start_btn.setDisabled(True)
        self.stop_btn.setEnabled(True)
        self.save_btn.setDisabled(True)
        self.fps.setDisabled(True)
        self.data_selector.setDisabled(True)
        self.implication_selections.setDisabled(True)
        self.combination_vars_selections.setDisabled(True)
        self.combination_rules_selections.setDisabled(True)
        self.defuzzifier_selections.setDisabled(True)
        self.fuzzyvar_setting_dist_front.setDisabled(True)
        self.fuzzyvar_setting_dist_lrdiff.setDisabled(True)
        self.fuzzyvar_setting_consequence.setDisabled(True)
        self.rules_setting.setDisabled(True)

    @Slot()
    def __reset_widgets(self):
        self.start_btn.setEnabled(True)
        self.stop_btn.setDisabled(True)
        self.save_btn.setEnabled(True)
        self.fps.setEnabled(True)
        self.data_selector.setEnabled(True)
        self.implication_selections.setEnabled(True)
        self.combination_vars_selections.setEnabled(True)
        self.combination_rules_selections.setEnabled(True)
        self.defuzzifier_selections.setEnabled(True)
        self.fuzzyvar_setting_dist_front.setEnabled(True)
        self.fuzzyvar_setting_dist_lrdiff.setEnabled(True)
        self.fuzzyvar_setting_consequence.setEnabled(True)
        self.rules_setting.setEnabled(True)

    @Slot()
    def __run(self):
        # reset the map
        self.__change_map()
        # create a QThread
        self.thread = RunCar(self.__car, self.__create_fuzzy_system(),
                             (self.__current_data['end_area_lt'],
                              self.__current_data['end_area_rb']),
                             self.fps.value())
        # Record the new created threads for the closeEvent in gui_base.py
        # By doing this, user can destroy the QMainWindow elegantly when there
        # are threads still running.
        self.threads.append(self.thread)
        self.stop_btn.clicked.connect(self.thread.stop)
        self.thread.started.connect(self.__init_widgets)
        self.thread.finished.connect(self.__reset_widgets)
        self.thread.sig_console.connect(self.__print_console)
        self.thread.sig_car.connect(self.display_panel.move_car)
        self.thread.sig_car_collided.connect(
            self.display_panel.show_car_collided)
        self.thread.sig_dists.connect(self.display_panel.show_dists)
        self.thread.sig_results.connect(self.__get_results)
        self.thread.start()

    def __create_fuzzy_system(self):
        """Create a fuzzy system with the parameter given in control panel."""
        dist_front = FuzzyVariable()
        dist_front.add_membershipf(
            'small',
            get_gaussianf(
                *self.fuzzyvar_setting_dist_front.small.get_values()))
        dist_front.add_membershipf(
            'medium',
            get_gaussianf(
                *self.fuzzyvar_setting_dist_front.medium.get_values()))
        dist_front.add_membershipf(
            'large',
            get_gaussianf(
                *self.fuzzyvar_setting_dist_front.large.get_values()))

        dist_lrdiff = FuzzyVariable()
        dist_lrdiff.add_membershipf(
            'small',
            get_gaussianf(
                *self.fuzzyvar_setting_dist_lrdiff.small.get_values()))
        dist_lrdiff.add_membershipf(
            'medium',
            get_gaussianf(
                *self.fuzzyvar_setting_dist_lrdiff.medium.get_values()))
        dist_lrdiff.add_membershipf(
            'large',
            get_gaussianf(
                *self.fuzzyvar_setting_dist_lrdiff.large.get_values()))

        consequence = FuzzyVariable()
        consequence.add_membershipf(
            'small',
            get_gaussianf(
                *self.fuzzyvar_setting_consequence.small.get_values()))
        consequence.add_membershipf(
            'medium',
            get_gaussianf(
                *self.fuzzyvar_setting_consequence.medium.get_values()))
        consequence.add_membershipf(
            'large',
            get_gaussianf(
                *self.fuzzyvar_setting_consequence.large.get_values()))

        fuzzy_system = FuzzySystem(consequence, dist_front, dist_lrdiff)
        fuzzy_system.set_operation_types(
            self.implication_selections.get_selected_name(),
            self.combination_vars_selections.get_selected_name(),
            self.combination_rules_selections.get_selected_name(),
            self.defuzzifier_selections.get_selected_name())

        for antecendent_names, consequence_name in self.rules_setting.rules.items(
        ):
            fuzzy_system.add_rule(consequence_name, antecendent_names)

        return fuzzy_system
Esempio n. 12
0
class QTgoLayoutGroupRow(QWidget):
    group_template_changed = Signal()

    def __init__(self, force_group: ForceGroup, group: TgoLayoutGroup) -> None:
        super().__init__()
        self.grid_layout = QGridLayout()
        self.setLayout(self.grid_layout)
        self.grid_layout.setColumnStretch(0, 100)
        self.amount_selector = QSpinBox()
        self.unit_selector = QComboBox()
        self.unit_selector.setMinimumWidth(250)
        self.group_selector = QCheckBox()

        # Add all possible units with the price
        for unit_type in force_group.unit_types_for_group(group):
            self.unit_selector.addItem(
                f"{unit_type.name} [${unit_type.price}M]",
                userData=(unit_type.dcs_unit_type, unit_type.price),
            )
        # Add all possible statics with price = 0
        for static_type in force_group.statics_for_group(group):
            self.unit_selector.addItem(f"{static_type} (Static)",
                                       userData=(static_type, 0))

        if self.unit_selector.count() == 0:
            raise LayoutException("No units available for the TgoLayoutGroup")

        self.unit_selector.adjustSize()
        self.unit_selector.setEnabled(self.unit_selector.count() > 1)
        self.grid_layout.addWidget(self.unit_selector,
                                   0,
                                   0,
                                   alignment=Qt.AlignRight)
        self.grid_layout.addWidget(self.amount_selector,
                                   0,
                                   1,
                                   alignment=Qt.AlignRight)

        dcs_unit_type, price = self.unit_selector.itemData(
            self.unit_selector.currentIndex())

        self.group_layout = QTgoLayoutGroup(group, dcs_unit_type,
                                            group.group_size, price)

        self.group_selector.setChecked(self.group_layout.enabled)
        self.group_selector.setEnabled(self.group_layout.layout.optional)

        self.amount_selector.setMinimum(1)
        self.amount_selector.setMaximum(self.group_layout.layout.max_size)
        self.amount_selector.setValue(self.group_layout.amount)
        self.amount_selector.setEnabled(self.group_layout.layout.max_size > 1)

        self.grid_layout.addWidget(self.group_selector,
                                   0,
                                   2,
                                   alignment=Qt.AlignRight)

        self.amount_selector.valueChanged.connect(self.on_group_changed)
        self.unit_selector.currentIndexChanged.connect(self.on_group_changed)
        self.group_selector.stateChanged.connect(self.on_group_changed)

    def on_group_changed(self) -> None:
        self.group_layout.enabled = self.group_selector.isChecked()
        unit_type, price = self.unit_selector.itemData(
            self.unit_selector.currentIndex())
        self.group_layout.dcs_unit_type = unit_type
        self.group_layout.unit_price = price
        self.group_layout.amount = self.amount_selector.value()
        self.group_template_changed.emit()
Esempio n. 13
0
class PilotSettingsBox(QGroupBox):
    def __init__(self, game: Game) -> None:
        super().__init__("Pilots and Squadrons")
        self.game = game

        layout = QGridLayout()
        self.setLayout(layout)

        self.ai_pilot_levelling = QCheckBox()
        self.ai_pilot_levelling.setChecked(self.game.settings.ai_pilot_levelling)
        self.ai_pilot_levelling.toggled.connect(self.set_ai_pilot_leveling)

        ai_pilot_levelling_info = (
            "Set whether or not AI pilots will level up after completing a number of"
            " sorties. Since pilot level affects the AI skill, you may wish to disable"
            " this, lest you face an Ace!"
        )

        self.ai_pilot_levelling.setToolTip(ai_pilot_levelling_info)
        ai_pilot_levelling_label = QLabel("Allow AI pilot levelling")
        ai_pilot_levelling_label.setToolTip(ai_pilot_levelling_info)

        layout.addWidget(ai_pilot_levelling_label, 0, 0)
        layout.addWidget(self.ai_pilot_levelling, 0, 1, Qt.AlignRight)

        enable_squadron_pilot_limits_info = (
            "If set, squadrons will be limited to a maximum number of pilots and dead "
            "pilots will replenish at a fixed rate, each defined with the settings"
            "below. Auto-purchase may buy aircraft for which there are no pilots"
            "available, so this feature is still a work-in-progress."
        )

        enable_squadron_pilot_limits_label = QLabel(
            "Enable per-squadron pilot limtits (WIP)"
        )
        enable_squadron_pilot_limits_label.setToolTip(enable_squadron_pilot_limits_info)
        enable_squadron_pilot_limits = QCheckBox()
        enable_squadron_pilot_limits.setToolTip(enable_squadron_pilot_limits_info)
        enable_squadron_pilot_limits.setChecked(
            self.game.settings.enable_squadron_pilot_limits
        )
        enable_squadron_pilot_limits.toggled.connect(
            self.set_enable_squadron_pilot_limits
        )

        layout.addWidget(enable_squadron_pilot_limits_label, 1, 0)
        layout.addWidget(enable_squadron_pilot_limits, 1, 1, Qt.AlignRight)

        self.pilot_limit = QSpinBox()
        self.pilot_limit.setMinimum(12)
        self.pilot_limit.setMaximum(72)
        self.pilot_limit.setValue(self.game.settings.squadron_pilot_limit)
        self.pilot_limit.setEnabled(self.game.settings.enable_squadron_pilot_limits)
        self.pilot_limit.valueChanged.connect(self.set_squadron_pilot_limit)

        pilot_limit_info = (
            "Sets the maximum number of pilots a squadron may have active. "
            "Changing this value will not have an immediate effect, but will alter "
            "replenishment for future turns."
        )

        self.pilot_limit.setToolTip(pilot_limit_info)
        pilot_limit_label = QLabel("Maximum number of pilots per squadron")
        pilot_limit_label.setToolTip(pilot_limit_info)

        layout.addWidget(pilot_limit_label, 2, 0)
        layout.addWidget(self.pilot_limit, 2, 1, Qt.AlignRight)

        self.squadron_replenishment_rate = QSpinBox()
        self.squadron_replenishment_rate.setMinimum(1)
        self.squadron_replenishment_rate.setMaximum(20)
        self.squadron_replenishment_rate.setValue(
            self.game.settings.squadron_replenishment_rate
        )
        self.squadron_replenishment_rate.setEnabled(
            self.game.settings.enable_squadron_pilot_limits
        )
        self.squadron_replenishment_rate.valueChanged.connect(
            self.set_squadron_replenishment_rate
        )

        squadron_replenishment_rate_info = (
            "Sets the maximum number of pilots that will be recruited to each squadron "
            "at the end of each turn. Squadrons will not recruit new pilots beyond the "
            "pilot limit, but each squadron with room for more pilots will recruit "
            "this many pilots each turn up to the limit."
        )

        self.squadron_replenishment_rate.setToolTip(squadron_replenishment_rate_info)
        squadron_replenishment_rate_label = QLabel("Squadron pilot replenishment rate")
        squadron_replenishment_rate_label.setToolTip(squadron_replenishment_rate_info)

        layout.addWidget(squadron_replenishment_rate_label, 3, 0)
        layout.addWidget(self.squadron_replenishment_rate, 3, 1, Qt.AlignRight)

    def set_enable_squadron_pilot_limits(self, checked: bool) -> None:
        self.game.settings.enable_squadron_pilot_limits = checked
        self.pilot_limit.setEnabled(checked)
        self.squadron_replenishment_rate.setEnabled(checked)

    def set_squadron_pilot_limit(self, value: int) -> None:
        self.game.settings.squadron_pilot_limit = value

    def set_squadron_replenishment_rate(self, value: int) -> None:
        self.game.settings.squadron_replenishment_rate = value

    def set_ai_pilot_leveling(self, checked: bool) -> None:
        self.game.settings.ai_pilot_levelling = checked
class QGroundObjectMenu(QDialog):
    def __init__(
        self,
        parent,
        ground_object: TheaterGroundObject,
        cp: ControlPoint,
        game: Game,
    ):
        super().__init__(parent)
        self.setMinimumWidth(350)
        self.ground_object = ground_object
        self.cp = cp
        self.game = game
        self.setWindowTitle(
            f"Location - {self.ground_object.obj_name} ({self.cp.name})"
        )
        self.setWindowIcon(EVENT_ICONS["capture"])
        self.intelBox = QGroupBox("Units :")
        self.buildingBox = QGroupBox("Buildings :")
        self.orientationBox = QGroupBox("Orientation :")
        self.intelLayout = QGridLayout()
        self.buildingsLayout = QGridLayout()
        self.sell_all_button = None
        self.total_value = 0
        self.init_ui()

    def init_ui(self):

        self.mainLayout = QVBoxLayout()
        self.budget = QBudgetBox(self.game)
        self.budget.setGame(self.game)

        self.doLayout()

        if isinstance(self.ground_object, BuildingGroundObject):
            self.mainLayout.addWidget(self.buildingBox)
            if self.cp.captured:
                self.mainLayout.addWidget(self.financesBox)
        else:
            self.mainLayout.addWidget(self.intelBox)
            self.mainLayout.addWidget(self.orientationBox)

        self.actionLayout = QHBoxLayout()

        self.sell_all_button = QPushButton("Disband (+" + str(self.total_value) + "M)")
        self.sell_all_button.clicked.connect(self.sell_all)
        self.sell_all_button.setProperty("style", "btn-danger")

        self.buy_replace = QPushButton("Buy/Replace")
        self.buy_replace.clicked.connect(self.buy_group)
        self.buy_replace.setProperty("style", "btn-success")

        if self.ground_object.purchasable:
            if self.total_value > 0:
                self.actionLayout.addWidget(self.sell_all_button)
            self.actionLayout.addWidget(self.buy_replace)

        if self.cp.captured and self.ground_object.purchasable:
            self.mainLayout.addLayout(self.actionLayout)
        self.setLayout(self.mainLayout)

    def doLayout(self):

        self.update_total_value()
        self.intelBox = QGroupBox("Units :")
        self.intelLayout = QGridLayout()
        i = 0
        for g in self.ground_object.groups:
            for unit in g.units:
                self.intelLayout.addWidget(
                    QLabel(f"<b>Unit {str(unit.display_name)}</b>"), i, 0
                )

                if not unit.alive and unit.repairable and self.cp.captured:
                    price = unit.unit_type.price if unit.unit_type else 0
                    repair = QPushButton(f"Repair [{price}M]")
                    repair.setProperty("style", "btn-success")
                    repair.clicked.connect(
                        lambda u=unit, p=price: self.repair_unit(u, p)
                    )
                    self.intelLayout.addWidget(repair, i, 1)
                i += 1

        stretch = QVBoxLayout()
        stretch.addStretch()
        self.intelLayout.addLayout(stretch, i, 0)

        self.buildingBox = QGroupBox("Buildings :")
        self.buildingsLayout = QGridLayout()

        j = 0
        total_income = 0
        received_income = 0
        for static in self.ground_object.statics:
            if static not in FORTIFICATION_BUILDINGS:
                self.buildingsLayout.addWidget(
                    QBuildingInfo(static, self.ground_object), j / 3, j % 3
                )
                j = j + 1

            if self.ground_object.category in REWARDS.keys():
                total_income += REWARDS[self.ground_object.category]
                if static.alive:
                    received_income += REWARDS[self.ground_object.category]
            else:
                logging.warning(self.ground_object.category + " not in REWARDS")

        self.financesBox = QGroupBox("Finances: ")
        self.financesBoxLayout = QGridLayout()
        self.financesBoxLayout.addWidget(
            QLabel("Available: " + str(total_income) + "M"), 2, 1
        )
        self.financesBoxLayout.addWidget(
            QLabel("Receiving: " + str(received_income) + "M"), 2, 2
        )

        # Orientation Box
        self.orientationBox = QGroupBox("Orientation :")
        self.orientationBoxLayout = QHBoxLayout()

        heading_image = QLabel()
        heading_image.setPixmap(
            ICONS["heading"].transformed(
                QTransform().rotate(self.ground_object.heading.degrees)
            )
        )
        self.orientationBoxLayout.addWidget(heading_image)
        self.headingLabel = QLabel("Heading:")
        self.orientationBoxLayout.addWidget(self.headingLabel)
        self.headingSelector = QSpinBox()
        self.headingSelector.setEnabled(False)  # Disable for now
        self.headingSelector.setMinimum(0)
        self.headingSelector.setMaximum(360)
        self.headingSelector.setValue(self.ground_object.heading.degrees)
        self.orientationBoxLayout.addWidget(self.headingSelector)
        if self.cp.captured:
            # TODO Let the user choose the heading with the SpinBox
            self.headingSelector.setEnabled(False)
            self.head_to_conflict_button = QPushButton("Head to conflict")
            heading = (
                self.game.theater.heading_to_conflict_from(self.ground_object.position)
                or self.ground_object.heading
            )
            self.head_to_conflict_button.clicked.connect(
                lambda: self.rotate_tgo(heading)
            )
            self.orientationBoxLayout.addWidget(self.head_to_conflict_button)
        else:
            self.headingSelector.setEnabled(False)

        # Set the layouts
        self.financesBox.setLayout(self.financesBoxLayout)
        self.buildingBox.setLayout(self.buildingsLayout)
        self.intelBox.setLayout(self.intelLayout)
        self.orientationBox.setLayout(self.orientationBoxLayout)

    def do_refresh_layout(self):
        try:
            for i in reversed(range(self.mainLayout.count())):
                item = self.mainLayout.itemAt(i)
                if item is not None and item.widget() is not None:
                    item.widget().setParent(None)
            self.sell_all_button.setParent(None)
            self.buy_replace.setParent(None)
            self.actionLayout.setParent(None)

            self.doLayout()
            if isinstance(self.ground_object, BuildingGroundObject):
                self.mainLayout.addWidget(self.buildingBox)
            else:
                self.mainLayout.addWidget(self.intelBox)
                self.mainLayout.addWidget(self.orientationBox)

            self.actionLayout = QHBoxLayout()
            if self.total_value > 0:
                self.actionLayout.addWidget(self.sell_all_button)
            self.actionLayout.addWidget(self.buy_replace)

            if self.cp.captured and self.ground_object.purchasable:
                self.mainLayout.addLayout(self.actionLayout)
        except Exception as e:
            logging.exception(e)
        self.update_total_value()

    def update_total_value(self):
        if not self.ground_object.purchasable:
            return
        self.total_value = self.ground_object.value
        if self.sell_all_button is not None:
            self.sell_all_button.setText("Disband (+$" + str(self.total_value) + "M)")

    def repair_unit(self, unit, price):
        if self.game.blue.budget > price:
            self.game.blue.budget -= price
            unit.alive = True
            GameUpdateSignal.get_instance().updateGame(self.game)

            # Remove destroyed units in the vicinity
            destroyed_units = self.game.get_destroyed_units()
            for d in destroyed_units:
                p = Point(d["x"], d["z"], self.game.theater.terrain)
                if p.distance_to_point(unit.position) < 15:
                    destroyed_units.remove(d)
                    logging.info("Removed destroyed units " + str(d))
            logging.info(f"Repaired unit: {unit.unit_name}")

        self.update_game()

    def rotate_tgo(self, heading: Heading) -> None:
        self.ground_object.rotate(heading)
        self.do_refresh_layout()

    def sell_all(self):
        self.update_total_value()
        self.game.blue.budget += self.total_value
        self.ground_object.groups = []
        self.update_game()

    def buy_group(self) -> None:
        self.subwindow = QGroundObjectBuyMenu(
            self, self.ground_object, self.game, self.total_value
        )
        if self.subwindow.exec_():
            self.update_game()

    def update_game(self) -> None:
        events = GameUpdateEvents()
        events.update_tgo(self.ground_object)
        if any(
            package.target == self.ground_object
            for package in self.game.ato_for(player=False).packages
        ):
            # Replan if the tgo was a target of the redfor
            self.game.initialize_turn(events, for_red=True, for_blue=False)
        EventStream.put_nowait(events)
        GameUpdateSignal.get_instance().updateGame(self.game)
        # Refresh the dialog
        self.do_refresh_layout()
Esempio n. 15
0
class QFlightSlotEditor(QGroupBox):

    changed = Signal()

    def __init__(self, flight, game, planner):
        super(QFlightSlotEditor, self).__init__("Slots")
        self.flight = flight
        self.game = game
        self.planner = planner
        self.available = self.planner.get_available_aircraft()
        if self.flight.unit_type not in self.available:
            max = self.flight.count
        else:
            max = self.flight.count + self.available[self.flight.unit_type]
        if max > 4:
            max = 4

        layout = QGridLayout()

        self.aircraft_count = QLabel("Aircraft count :")
        self.aircraft_count_spinner = QSpinBox()
        self.aircraft_count_spinner.setMinimum(1)
        self.aircraft_count_spinner.setMaximum(max)
        self.aircraft_count_spinner.setValue(flight.count)
        self.aircraft_count_spinner.valueChanged.connect(
            self._changed_aircraft_count)

        self.client_count = QLabel("Client slots count :")
        self.client_count_spinner = QSpinBox()
        self.client_count_spinner.setMinimum(0)
        self.client_count_spinner.setMaximum(max)
        self.client_count_spinner.setValue(flight.client_count)
        self.client_count_spinner.valueChanged.connect(
            self._changed_client_count)

        if not self.flight.unit_type.flyable:
            self.client_count_spinner.setValue(0)
            self.client_count_spinner.setEnabled(False)

        layout.addWidget(self.aircraft_count, 0, 0)
        layout.addWidget(self.aircraft_count_spinner, 0, 1)

        layout.addWidget(self.client_count, 1, 0)
        layout.addWidget(self.client_count_spinner, 1, 1)

        self.setLayout(layout)

    def _changed_aircraft_count(self):
        self.flight.count = int(self.aircraft_count_spinner.value())
        self.changed.emit()
        # TODO check if enough aircraft are available

    def _changed_client_count(self):
        self.flight.client_count = int(self.client_count_spinner.value())
        self._cap_client_count()
        self.changed.emit()

    def _cap_client_count(self):
        if self.flight.client_count > self.flight.count:
            self.flight.client_count = self.flight.count
            self.client_count_spinner.setValue(self.flight.client_count)
Esempio n. 16
0
class GradientWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(GradientWidget, self).__init__(parent)
        self.levels_spin = QSpinBox()
        self.levels_spin.setRange(-1, 16)
        self.levels_spin.setSpecialValueText(self.tr('Auto'))
        self.levels_spin.setValue(-1)
        self.invert_check = QCheckBox(self.tr('Invert'))
        self.abs_check = QCheckBox(self.tr('Absolute'))

        self.grad_viewer = ImageViewer(image, image)
        self.image = image
        self.process()

        self.levels_spin.valueChanged.connect(self.process)
        self.invert_check.toggled.connect(self.process)
        self.abs_check.toggled.connect(self.process)

        top_layout = QHBoxLayout()
        top_layout.addWidget(QLabel(self.tr('Levels:')))
        top_layout.addWidget(self.levels_spin)
        top_layout.addWidget(self.invert_check)
        top_layout.addWidget(self.abs_check)
        top_layout.addStretch()

        main_layout = QVBoxLayout()
        main_layout.addLayout(top_layout)
        main_layout.addWidget(self.grad_viewer)

        self.setLayout(main_layout)

    def process(self):
        intensity = self.levels_spin.value()
        invert = self.invert_check.isChecked()
        absolute = self.abs_check.isChecked()
        self.levels_spin.setEnabled(not absolute)
        self.invert_check.setEnabled(not absolute)

        gray = cv.cvtColor(self.image, cv.COLOR_BGR2GRAY)
        diff_x = cv.Scharr(gray, cv.CV_32F, 1, 0)
        diff_y = cv.Scharr(gray, cv.CV_32F, 0, 1)
        diff_z = cv.normalize(np.abs(diff_x + diff_y), None, 0, 255,
                              cv.NORM_MINMAX)
        diff_z = cv.LUT(diff_z.astype(np.uint8), create_lut(0, 90))
        grad_x = +diff_x if invert else -diff_x
        grad_y = +diff_y if invert else -diff_y
        grad_z = diff_z

        if not absolute:
            min_x, max_x, _, _ = cv.minMaxLoc(grad_x)
            lim_x = max(abs(min_x), abs(max_x))
            grad_x = (grad_x / lim_x + 1) * 127
            min_y, max_y, _, _ = cv.minMaxLoc(grad_y)
            lim_y = max(abs(min_y), abs(max_y))
            grad_y = (grad_y / lim_y + 1) * 127
        else:
            grad_x = cv.normalize(np.abs(grad_x), None, 0, 255, cv.NORM_MINMAX)
            grad_y = cv.normalize(np.abs(grad_y), None, 0, 255, cv.NORM_MINMAX)
        grad_x = grad_x.astype(np.uint8)
        grad_y = grad_y.astype(np.uint8)

        if intensity >= 0 and not absolute:
            max_intensity = self.levels_spin.maximum()
            low = 127 - (max_intensity - intensity)
            high = 127 + (max_intensity - intensity)
            lut_xy = create_lut(low, high)
            grad_x = cv.LUT(grad_x, lut_xy)
            grad_y = cv.LUT(grad_y, lut_xy)
        else:
            grad_x = cv.equalizeHist(grad_x)
            grad_y = cv.equalizeHist(grad_y)
        gradient = np.stack((grad_z, grad_x, grad_y), axis=2)
        self.grad_viewer.update_processed(gradient)
Esempio n. 17
0
class MainWindow(QMainWindow):
    def __init__(self, vehicle_ctl: VehicleCtl,
                 image_stream_server: ImageStreamServer):
        QMainWindow.__init__(self)

        self._vehicle_ctl = vehicle_ctl
        self._image_stream_server = image_stream_server

        # Our popup window for setting trim
        self._trim_window = None

        self.setMinimumSize(QSize(1000, 500))
        self.setWindowTitle("Rotor Client")

        central_widget = QWidget()
        self.setCentralWidget(central_widget)

        # Need to allow the central widget to get focus so the key presses are caught correctly
        central_widget.setFocusPolicy(QtCore.Qt.ClickFocus)

        # Create all the buttons and widgets
        self.create_gui()

        # Create the image viewer
        self._image_viewer = ImageViewer(self._image_stream_server)

        # Connect all the push button signals
        self.add_gui_listeners()

        # Set the widgets in the grid layout
        self.add_widgets_to_screen(central_widget)

        # Give the central widget focus so the key presses work
        central_widget.setFocus()

    def game_controller_calibration_dialog(self):
        self._game_controller_config_window = GameControllerCalibrationDialog()
        self._game_controller_config_window.show()
        self._game_controller_config_window.calibration_complete_response = lambda calibration_data: self.game_controller_calibrated_from_window(
            calibration_data)

    def game_controller_calibrated_from_window(self, calibration_data):
        self._game_controller_config_window.close()

        config_handler = ConfigHandler.get_instance()
        config_handler.set_config_value('game_controller_calibration',
                                        calibration_data.to_json())

        self.game_controller_calibrated(calibration_data)

    def game_controller_calibrated(self, calibration_data):
        logging.info("CONTROLLER WAS CALIBRATED!  " +
                     str(calibration_data.to_json()))
        self._game_controller = GameController(inputs.devices.gamepads[0],
                                               calibration_data)
        self._game_controller.add_event_response(
            'ABS_HAT0X', self.game_controller_direction_pad_response)
        self._game_controller.add_event_response(
            'ABS_RZ', self.game_controller_right_trigger_response)
        self._game_controller.add_event_response(
            'ABS_Z', self.game_controller_left_trigger_response)
        self._game_controller.add_event_response(
            'ABS_X', self.game_controller_left_stick_x)
        self._game_controller.add_event_response(
            'BTN_EAST', self.game_controller_b_button_response)
        self._game_controller.add_event_response(
            'BTN_TR', self.game_controller_right_bumper_response)
        self._game_controller.start()

    def game_controller_left_stick_x(self, state):
        self._vehicle_ctl.set_steering(
            state / self._game_controller.get_calibration().joystick_boundary)

    def game_controller_direction_pad_response(self, state):
        if state == -1:
            self.left_pressed()
        elif state == 1:
            self.right_pressed()
        else:
            self._vehicle_ctl.set_steering(0.0)

    def game_controller_b_button_response(self, state):
        if state == 1:
            self.backward_pressed()
        else:
            self.backward_released()

    def game_controller_right_bumper_response(self, state):
        if state == 0:
            self.change_gear()

    def game_controller_right_trigger_response(self, state):
        acc_value = state / self._game_controller.get_calibration(
        ).right_trigger_max
        if self._vehicle_ctl.get_gear() == Gear.DRIVE:
            self._vehicle_ctl.set_accelerator(acc_value)
        elif self._vehicle_ctl.get_gear() == Gear.REVERSE:
            acc_value *= -1
            self._vehicle_ctl.set_accelerator(acc_value)

    def game_controller_left_trigger_response(self, state):
        acc_value = state / self._game_controller.get_calibration(
        ).right_trigger_max
        acc_value *= -1
        if self._vehicle_ctl.get_gear() == Gear.DRIVE:
            self._vehicle_ctl.set_accelerator(acc_value)
        elif self._vehicle_ctl.get_gear() == Gear.REVERSE:
            acc_value *= -1
            self._vehicle_ctl.set_accelerator(acc_value)

    def forward_pressed(self):
        if self._vehicle_ctl.get_gear() is Gear.REVERSE:
            self._vehicle_ctl.set_accelerator(-1.0)
        elif self._vehicle_ctl.get_gear() is Gear.DRIVE:
            self._vehicle_ctl.set_accelerator(1.0)

    def forward_released(self):
        self._vehicle_ctl.set_accelerator(0.0)

    def backward_pressed(self):
        if self._vehicle_ctl.get_gear() is Gear.REVERSE:
            self._vehicle_ctl.set_accelerator(1.0)
        elif self._vehicle_ctl.get_gear() is Gear.DRIVE:
            self._vehicle_ctl.set_accelerator(-1.0)

    def backward_released(self):
        self._vehicle_ctl.set_accelerator(0.0)

    def right_pressed(self):
        self._vehicle_ctl.set_steering(1.0)

    def right_released(self):
        self._vehicle_ctl.set_steering(0.0)

    def left_pressed(self):
        self._vehicle_ctl.set_steering(-1.0)

    def left_released(self):
        self._vehicle_ctl.set_steering(0.0)

    def show_trim_window(self):

        # Pull in the trim from the vehicle to populate the trim window
        trim = self._vehicle_ctl.get_trim()
        self._trim_window = TrimDialog(trim)
        self._trim_window.setGeometry(QtCore.QRect(100, 100, 400, 200))
        self._trim_window.show()

        # After things have been trimmed, update our command so we can send updated trim values
        self._trim_window.trim_changed.connect(self.update_trim_from_dialog)

    def update_trim_from_dialog(self):
        trim = self._trim_window.get_trim()
        self._vehicle_ctl.send_trim(trim)

    def ip_changed(self, ip):

        port = self._sb_port.value()
        self._vehicle_ctl.set_endpoint(ip, port)

    def proxy_address_changed(self, address):
        self._vehicle_ctl.set_proxy(address,
                                    self._vehicle_ctl.vehicle_proxy_port())

    def proxy_port_changed(self, port):
        self._vehicle_ctl.set_proxy(self._vehicle_ctl.vehicle_proxy_address(),
                                    port)

    def use_proxy_toggled(self, state):
        self._le_proxy_address.setEnabled(state)
        self._sb_proxy_port.setEnabled(state)
        if state:
            self._vehicle_ctl.enable_proxy()
        else:
            self._vehicle_ctl.disable_proxy()

    def port_changed(self, port):
        ip = self._le_ip.text()
        self._vehicle_ctl.set_endpoint(ip, port)

    def mode_changed(self, index):
        mode_int = self._cbo_mode.currentData()
        mode = Mode()
        mode.set_mode(mode_int)

        self._vehicle_ctl.set_mode(mode)

    def restart_stream(self):

        self._vehicle_ctl.restart_stream()

    def change_gear(self):
        self._vehicle_ctl.toggle_fw_bw()
        self._lbl_gear.setText('<b style="color: black;">' +
                               self._vehicle_ctl.get_gear().value + "</b>")

    def keyPressEvent(self, e):
        if e.isAutoRepeat():
            return super().keyReleaseEvent(e)

        if e.key() == QtCore.Qt.Key_Up or e.key() == QtCore.Qt.Key_W:
            self.forward_pressed()
        if e.key() == QtCore.Qt.Key_Left or e.key() == QtCore.Qt.Key_A:
            self.left_pressed()
        if e.key() == QtCore.Qt.Key_Down or e.key() == QtCore.Qt.Key_S:
            self.backward_pressed()
        if e.key() == QtCore.Qt.Key_Right or e.key() == QtCore.Qt.Key_D:
            self.right_pressed()

        return super().keyPressEvent(e)

    def keyReleaseEvent(self, e):
        if e.isAutoRepeat():
            return super().keyReleaseEvent(e)

        if e.key() == QtCore.Qt.Key_Up or e.key() == QtCore.Qt.Key_W:
            self.forward_released()
        elif e.key() == QtCore.Qt.Key_Left or e.key() == QtCore.Qt.Key_A:
            self.left_released()
        elif e.key() == QtCore.Qt.Key_Down or e.key() == QtCore.Qt.Key_S:
            self.backward_released()
        elif e.key() == QtCore.Qt.Key_Right or e.key() == QtCore.Qt.Key_D:
            self.right_released()
        elif e.key() == QtCore.Qt.Key_R:
            self.change_gear()

        return super().keyReleaseEvent(e)

    def send_trim(self):
        self._vehicle_ctl.send_trim(self.trim)

    def create_gui(self):
        buttonHeight = 100
        self._forward_btn = QPushButton("ACC", self)
        self._brake_btn = QPushButton("BRAKE", self)
        self._left_btn = QPushButton("LEFT", self)
        self._right_btn = QPushButton("RIGHT", self)

        self._forward_btn.setFixedHeight(buttonHeight)
        self._brake_btn.setFixedHeight(buttonHeight)
        self._left_btn.setFixedHeight(buttonHeight)
        self._right_btn.setFixedHeight(buttonHeight)

        self._trim_btn = QPushButton("Set Trim", self)
        self._trim_btn.clicked.connect(self.show_trim_window)
        self._le_ip = QLineEdit(self._vehicle_ctl.vehicle_ip(), self)
        self._le_ip.textChanged.connect(self.ip_changed)
        self._lbl_ip = QLabel("Ip:")
        self._sb_port = QSpinBox(self)
        self._sb_port.setMaximum(99999)
        self._sb_port.setValue(self._vehicle_ctl.vehicle_port())
        self._sb_port.valueChanged.connect(self.port_changed)
        self._lbl_port = QLabel("Port:")
        self._lbl_mode = QLabel("Mode:")
        self._cbo_mode = QComboBox(self)
        self._lbl_proxy_address = QLabel("Proxy:")
        self._le_proxy_address = QLineEdit(
            self._vehicle_ctl.vehicle_proxy_address(), self)
        self._lbl_proxy_port = QLabel("Proxy Port:")

        self._lbl_gear = QLabel('<b style="color: black;">' +
                                self._vehicle_ctl.get_gear().value + "</b>")
        f = self._lbl_gear.font()
        f.setPointSizeF(100)
        self._lbl_gear.setFont(f)
        self._lbl_gear.setAlignment(Qt.AlignCenter)

        self._btn_change_gear = QPushButton("Shift Gear")

        self._sb_proxy_port = QSpinBox(self)
        self._sb_proxy_port.setMaximum(99999)
        self._sb_proxy_port.setValue(self._vehicle_ctl.vehicle_proxy_port())

        self._cbo_mode.addItem("NORMAL", int(ModeType.NORMAL))
        self._cbo_mode.addItem("TRAIN", int(ModeType.TRAIN))
        self._cbo_mode.addItem("AUTO", int(ModeType.AUTO))
        self._btn_restart = QPushButton("Restart Stream")
        self._cb_proxy = QCheckBox()
        self._lbl_use_proxy = QLabel("Use Proxy")
        self._cb_proxy.setChecked(self._vehicle_ctl.is_using_proxy())
        self._le_proxy_address.setEnabled(self._vehicle_ctl.is_using_proxy())
        self._sb_proxy_port.setEnabled(self._vehicle_ctl.is_using_proxy())

    def add_gui_listeners(self):
        self._forward_btn.pressed.connect(self.forward_pressed)
        self._forward_btn.released.connect(self.forward_released)
        self._brake_btn.pressed.connect(self.backward_pressed)
        self._brake_btn.released.connect(self.backward_released)
        self._right_btn.pressed.connect(self.right_pressed)
        self._right_btn.released.connect(self.right_released)
        self._left_btn.pressed.connect(self.left_pressed)
        self._left_btn.released.connect(self.left_released)
        self._cbo_mode.activated.connect(self.mode_changed)
        self._btn_restart.pressed.connect(self.restart_stream)
        self._cb_proxy.toggled.connect(self.use_proxy_toggled)
        self._le_proxy_address.textChanged.connect(self.proxy_address_changed)
        self._sb_proxy_port.valueChanged.connect(self.proxy_port_changed)
        self._btn_change_gear.released.connect(self.change_gear)

    def add_widgets_to_screen(self, cw):
        grid_layout = QGridLayout(cw)

        controls_layout = QGridLayout()
        controls_layout.setAlignment(Qt.AlignVCenter)
        grid_layout.addLayout(controls_layout, 0, 0, 2, 3)

        controls_layout.addWidget(self._forward_btn, 0, 1)
        controls_layout.addWidget(self._left_btn, 1, 0)
        controls_layout.addWidget(self._brake_btn, 1, 1)
        controls_layout.addWidget(self._right_btn, 1, 2)

        grid_layout.addWidget(self._lbl_ip, 2, 0)
        grid_layout.addWidget(self._le_ip, 2, 1, 1,
                              2)  # Stretch the line edit into two cells
        grid_layout.addWidget(self._lbl_port, 3, 0)
        grid_layout.addWidget(self._sb_port, 3, 1, 1,
                              2)  # Stretch the spinbox into two cells
        grid_layout.addWidget(self._lbl_use_proxy, 4, 0)
        grid_layout.addWidget(self._cb_proxy, 4, 1)
        grid_layout.addWidget(self._lbl_proxy_address, 5, 0)
        grid_layout.addWidget(self._le_proxy_address, 5, 1, 1, 2)
        grid_layout.addWidget(self._lbl_proxy_port, 6, 0)
        grid_layout.addWidget(self._sb_proxy_port, 6, 1, 1, 2)
        grid_layout.addWidget(self._lbl_mode, 7, 0)
        grid_layout.addWidget(self._cbo_mode, 7, 1, 1, 2)
        grid_layout.addWidget(self._image_viewer, 0, 3, 5, 1)
        grid_layout.addWidget(self._btn_restart, 5, 3)

        vehicle_layout = QVBoxLayout()
        grid_layout.addLayout(vehicle_layout, 0, 4)
        vehicle_layout.addWidget(self._lbl_gear)
        vehicle_layout.addWidget(self._btn_change_gear)
        vehicle_layout.addWidget(self._trim_btn)
Esempio n. 18
0
class GradientWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(GradientWidget, self).__init__(parent)
        self.intensity_spin = QSpinBox()
        self.intensity_spin.setRange(0, 100)
        self.intensity_spin.setValue(95)
        self.intensity_spin.setSuffix(self.tr(" %"))
        self.intensity_spin.setToolTip(self.tr("Tonality compression amount"))
        self.blue_combo = QComboBox()
        self.blue_combo.addItems([
            self.tr("None"),
            self.tr("Flat"),
            self.tr("Abs"),
            self.tr("Norm")
        ])
        self.blue_combo.setCurrentIndex(2)
        self.blue_combo.setToolTip(self.tr("Blue component inclusion mode"))
        self.invert_check = QCheckBox(self.tr("Invert"))
        self.invert_check.setToolTip(self.tr("Reverse lighting direction"))
        self.equalize_check = QCheckBox(self.tr("Equalize"))
        self.equalize_check.setToolTip(self.tr("Apply histogram equalization"))

        self.image = image
        self.viewer = ImageViewer(self.image, self.image)
        self.dx, self.dy = cv.spatialGradient(
            cv.cvtColor(self.image, cv.COLOR_BGR2GRAY))
        self.process()

        self.intensity_spin.valueChanged.connect(self.process)
        self.blue_combo.currentIndexChanged.connect(self.process)
        self.invert_check.stateChanged.connect(self.process)
        self.equalize_check.stateChanged.connect(self.process)

        top_layout = QHBoxLayout()
        top_layout.addWidget(QLabel(self.tr("Intensity:")))
        top_layout.addWidget(self.intensity_spin)
        top_layout.addWidget(QLabel(self.tr("Blue channel:")))
        top_layout.addWidget(self.blue_combo)
        top_layout.addWidget(self.invert_check)
        top_layout.addWidget(self.equalize_check)
        top_layout.addStretch()

        main_layout = QVBoxLayout()
        main_layout.addLayout(top_layout)
        main_layout.addWidget(self.viewer)

        self.setLayout(main_layout)

    def process(self):
        start = time()
        intensity = int(self.intensity_spin.value() / 100 * 127)
        invert = self.invert_check.isChecked()
        equalize = self.equalize_check.isChecked()
        self.intensity_spin.setEnabled(not equalize)
        blue_mode = self.blue_combo.currentIndex()
        if invert:
            dx = (-self.dx).astype(np.float32)
            dy = (-self.dy).astype(np.float32)
        else:
            dx = (+self.dx).astype(np.float32)
            dy = (+self.dy).astype(np.float32)
        dx_abs = np.abs(dx)
        dy_abs = np.abs(dy)
        red = ((dx / np.max(dx_abs) * 127) + 127).astype(np.uint8)
        green = ((dy / np.max(dy_abs) * 127) + 127).astype(np.uint8)
        if blue_mode == 0:
            blue = np.zeros_like(red)
        elif blue_mode == 1:
            blue = np.full_like(red, 255)
        elif blue_mode == 2:
            blue = norm_mat(dx_abs + dy_abs)
        elif blue_mode == 3:
            blue = norm_mat(np.linalg.norm(cv.merge((red, green)), axis=2))
        else:
            blue = None
        gradient = cv.merge([blue, green, red])
        if equalize:
            gradient = equalize_img(gradient)
        elif intensity > 0:
            gradient = cv.LUT(gradient, create_lut(intensity, intensity))
        self.viewer.update_processed(gradient)
        self.info_message.emit(
            self.tr(f"Luminance Gradient = {elapsed_time(start)}"))
class AddRelationshipClassesDialog(GetObjectClassesMixin, AddItemsDialog):
    """A dialog to query user's preferences for new relationship classes."""
    def __init__(self,
                 parent,
                 db_mngr,
                 *db_maps,
                 object_class_one_name=None,
                 force_default=False):
        """
        Args:
            parent (SpineDBEditor)
            db_mngr (SpineDBManager)
            *db_maps: DiffDatabaseMapping instances
            object_class_one_name (str): default object_class name
            force_default (bool): if True, defaults are non-editable
        """
        super().__init__(parent, db_mngr, *db_maps)
        self.setWindowTitle("Add relationship classes")
        self.model = EmptyRowModel(self)
        self.model.force_default = force_default
        self.table_view.setModel(self.model)
        self.dimension_count_widget = QWidget(self)
        layout = QHBoxLayout(self.dimension_count_widget)
        layout.addWidget(QLabel("Number of dimensions"))
        self.spin_box = QSpinBox(self)
        self.spin_box.setMinimum(1)
        layout.addWidget(self.spin_box)
        layout.addStretch()
        self.layout().addWidget(self.dimension_count_widget, 0, 0, 1, -1)
        self.layout().addWidget(self.table_view, 1, 0)
        self.layout().addWidget(self.remove_rows_button, 2, 0)
        self.layout().addWidget(self.button_box, 3, 0, -1, -1)
        self.remove_rows_button.setIcon(
            QIcon(":/icons/menu_icons/cubes_minus.svg"))
        self.table_view.setItemDelegate(
            ManageRelationshipClassesDelegate(self))
        self.number_of_dimensions = 1
        self.connect_signals()
        self.model.set_horizontal_header_labels([
            'object_class name (1)', 'relationship_class name', 'description',
            'databases'
        ])
        self.db_map_obj_cls_lookup = self.make_db_map_obj_cls_lookup()
        if object_class_one_name:
            default_db_maps = [
                db_map for db_map, names in self.db_map_obj_cls_lookup.items()
                if object_class_one_name in names
            ]
            db_names = ",".join([
                db_name for db_name, db_map in self.keyed_db_maps.items()
                if db_map in default_db_maps
            ])
        else:
            db_names = ",".join(list(self.keyed_db_maps.keys()))
        self.model.set_default_row(**{
            'object_class name (1)': object_class_one_name,
            'databases': db_names
        })
        self.model.clear()

    def connect_signals(self):
        """Connect signals to slots."""
        super().connect_signals()
        self.spin_box.valueChanged.connect(self._handle_spin_box_value_changed)

    @Slot(int)
    def _handle_spin_box_value_changed(self, i):
        self.spin_box.setEnabled(False)
        if i > self.number_of_dimensions:
            self.insert_column()
        elif i < self.number_of_dimensions:
            self.remove_column()
        self.spin_box.setEnabled(True)
        self.resize_window_to_columns()

    def insert_column(self):
        column = self.number_of_dimensions
        self.number_of_dimensions += 1
        column_name = "object_class name ({0})".format(
            self.number_of_dimensions)
        self.model.insertColumns(column, 1)
        self.model.insert_horizontal_header_labels(column, [column_name])
        self.table_view.resizeColumnToContents(column)

    def remove_column(self):
        self.number_of_dimensions -= 1
        column = self.number_of_dimensions
        self.model.header.pop(column)
        self.model.removeColumns(column, 1)

    @Slot("QModelIndex", "QModelIndex", "QVector")
    def _handle_model_data_changed(self, top_left, bottom_right, roles):
        if Qt.EditRole not in roles:
            return
        top = top_left.row()
        left = top_left.column()
        bottom = bottom_right.row()
        right = bottom_right.column()
        for row in range(top, bottom + 1):
            for column in range(left, right + 1):
                if column >= self.number_of_dimensions:
                    break
            else:
                col_data = lambda j: self.model.index(row, j).data()  # pylint: disable=cell-var-from-loop
                obj_cls_names = [
                    col_data(j) for j in range(self.number_of_dimensions)
                    if col_data(j)
                ]
                if len(obj_cls_names) == 1:
                    relationship_class_name = obj_cls_names[0] + "__"
                else:
                    relationship_class_name = "__".join(obj_cls_names)
                self.model.setData(
                    self.model.index(row, self.number_of_dimensions),
                    relationship_class_name)

    @Slot()
    def accept(self):
        """Collect info from dialog and try to add items."""
        db_map_data = dict()
        name_column = self.model.horizontal_header_labels().index(
            "relationship_class name")
        description_column = self.model.horizontal_header_labels().index(
            "description")
        db_column = self.model.horizontal_header_labels().index("databases")
        for i in range(self.model.rowCount() -
                       1):  # last row will always be empty
            row_data = self.model.row_data(i)
            relationship_class_name = row_data[name_column]
            if not relationship_class_name:
                self.parent().msg_error.emit(
                    "Relationship class missing at row {}".format(i + 1))
                return
            description = row_data[description_column]
            pre_item = {
                'name': relationship_class_name,
                'description': description
            }
            db_names = row_data[db_column]
            if db_names is None:
                db_names = ""
            for db_name in db_names.split(","):
                if db_name not in self.keyed_db_maps:
                    self.parent().msg_error.emit(
                        "Invalid database {0} at row {1}".format(
                            db_name, i + 1))
                    return
                db_map = self.keyed_db_maps[db_name]
                object_classes = self.db_map_obj_cls_lookup[db_map]
                object_class_id_list = list()
                for column in range(
                        name_column):  # Leave 'name' column outside
                    object_class_name = row_data[column]
                    if object_class_name not in object_classes:
                        self.parent().msg_error.emit(
                            "Invalid object_class '{}' for db '{}' at row {}".
                            format(object_class_name, db_name, i + 1))
                        return
                    object_class_id = object_classes[object_class_name]["id"]
                    object_class_id_list.append(object_class_id)
                item = pre_item.copy()
                item['object_class_id_list'] = object_class_id_list
                db_map_data.setdefault(db_map, []).append(item)
        if not db_map_data:
            self.parent().msg_error.emit("Nothing to add")
            return
        self.db_mngr.add_relationship_classes(db_map_data)
        super().accept()
class PredefinedModelsWidget(QWidget):
    def __init__(self, predefined_models_window, parent: "QWidget" = None):
        super().__init__(parent)

        # Model picker size (left)
        self._predefined_models_window = predefined_models_window

        self._predefined_models_group = QGroupBox("Predefined Models:")
        self._predefined_models_layout = QHBoxLayout()
        self._predefined_models_layout.setContentsMargins(0, 0, 0, 0)
        self._predefined_models_group.setLayout(self._predefined_models_layout)
        self._predefined_models_layout.addWidget(
            self._predefined_models_window)

        # Description Side (right)
        self._model_name = QLabel("")

        self._include_top = QCheckBox("Include")
        self._include_top.setChecked(True)

        self._shape_textbox = QLineEdit("(224, 224, 3)")
        self._shape_textbox.setEnabled(False)

        self._classes_intbox = QSpinBox()
        self._classes_intbox.setMinimum(2)
        self._classes_intbox.setMaximum(999999)
        self._classes_intbox.setValue(1000)

        self._weights_combobox = QComboBox()
        self._weights_combobox.addItem("Imagenet", "imagenet")
        self._weights_combobox.addItem("None", None)

        # Add widgets to layout
        self._description_group = QGroupBox("Description:")
        self._description_layout = QFormLayout()

        self._description_group.setLayout(self._description_layout)

        self._description_layout.addRow("Name:", self._model_name)
        self._description_layout.addRow("Include Top:", self._include_top)
        self._description_layout.addRow("Input Shape:", self._shape_textbox)
        self._description_layout.addRow("Classes:", self._classes_intbox)
        self._description_layout.addRow("Weights:", self._weights_combobox)

        self._main_layout = QHBoxLayout()
        self._main_layout.addWidget(self._predefined_models_group)
        self._main_layout.addWidget(self._description_group)

        self.setLayout(self._main_layout)

        sp_left = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        sp_left.setHorizontalStretch(1)

        self._predefined_models_group.setSizePolicy(sp_left)

        sp_right = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        sp_right.setHorizontalStretch(2.5)

        self._description_group.setSizePolicy(sp_right)

        self._include_top.stateChanged.connect(
            lambda: self._update_enabled_widgets())
        self._weights_combobox.currentIndexChanged[int].connect(
            lambda: self._update_enabled_widgets())

        self._predefined_models_window.selected_model_changed.connect(
            self._update_description_labels)

        self._update_enabled_widgets()

    def get_model(self) -> Optional["Model"]:
        try:
            LOGGER.debug("Include Top: %s", self._include_top.isChecked())
            LOGGER.debug("Classes: %s", self._classes_intbox.value())
            LOGGER.debug("Weights: %s", self._weights_combobox.currentData())

            if not self._include_top.isChecked():
                input_shape = tuple(
                    map(
                        int,
                        re.sub("[()]", "",
                               self._shape_textbox.text()).split(",")))

                LOGGER.debug("Input tuple: %s", input_shape)

                return self._predefined_models_window.get_selected_model(
                )["loader"](
                    include_top=False,
                    input_shape=input_shape,
                    weights=self._weights_combobox.currentData(),
                )

            return self._predefined_models_window.get_selected_model(
            )["loader"](
                include_top=True,
                classes=self._classes_intbox.value(),
                weights=self._weights_combobox.currentData(),
            )

        except TypeError as err:
            LOGGER.exception(err)
            return None

    def get_image_transformations(self) -> List[Callable]:
        try:
            transformations = self._predefined_models_window.get_selected_model(
            )["transformations"]

            return transformations

        except KeyError as err:
            LOGGER.exception(err)
            return None

    def _update_description_labels(self, model_desc: dict):
        self._model_name.setText(model_desc["name"])

    def _update_enabled_widgets(self):
        self._shape_textbox.setEnabled(not self._include_top.isChecked())

        if (self._include_top.isChecked()
                and self._weights_combobox.currentText() == "None"):
            self._classes_intbox.setEnabled(True)
        else:
            self._classes_intbox.setEnabled(False)

    def sizeHint(self) -> "QSize":
        return QSize(400, 170)
Esempio n. 21
0
class NoiseWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(NoiseWidget, self).__init__(parent)

        self.mode_combo = QComboBox()
        self.mode_combo.addItems([
            self.tr('Median'),
            self.tr('Gaussian'),
            self.tr('BoxBlur'),
            self.tr('Bilateral'),
            self.tr('NonLocal')
        ])

        self.radius_spin = QSpinBox()
        self.radius_spin.setRange(1, 10)
        self.radius_spin.setSuffix(self.tr(' px'))
        self.radius_spin.setValue(1)

        self.sigma_spin = QSpinBox()
        self.sigma_spin.setRange(1, 200)
        self.sigma_spin.setValue(3)

        self.levels_spin = QSpinBox()
        self.levels_spin.setRange(0, 255)
        self.levels_spin.setSpecialValueText(self.tr('Equalized'))
        self.levels_spin.setValue(32)

        self.gray_check = QCheckBox(self.tr('Grayscale'))
        self.denoised_check = QCheckBox(self.tr('Denoised'))

        self.image = image
        self.viewer = ImageViewer(self.image, self.image)
        self.process()

        params_layout = QHBoxLayout()
        params_layout.addWidget(QLabel(self.tr('Mode:')))
        params_layout.addWidget(self.mode_combo)
        params_layout.addWidget(QLabel(self.tr('Radius:')))
        params_layout.addWidget(self.radius_spin)
        params_layout.addWidget(QLabel(self.tr('Sigma:')))
        params_layout.addWidget(self.sigma_spin)
        params_layout.addWidget(QLabel(self.tr('Levels:')))
        params_layout.addWidget(self.levels_spin)
        params_layout.addWidget(self.gray_check)
        params_layout.addWidget(self.denoised_check)
        params_layout.addStretch()

        main_layout = QVBoxLayout()
        main_layout.addLayout(params_layout)
        main_layout.addWidget(self.viewer)
        self.setLayout(main_layout)

        self.mode_combo.currentTextChanged.connect(self.process)
        self.radius_spin.valueChanged.connect(self.process)
        self.sigma_spin.valueChanged.connect(self.process)
        self.levels_spin.valueChanged.connect(self.process)
        self.gray_check.stateChanged.connect(self.process)
        self.denoised_check.stateChanged.connect(self.process)

    def process(self):
        start = time()
        grayscale = self.gray_check.isChecked()
        if grayscale:
            original = cv.cvtColor(self.image, cv.COLOR_BGR2GRAY)
        else:
            original = self.image
        radius = self.radius_spin.value()
        kernel = radius * 2 + 1
        sigma = self.sigma_spin.value()
        choice = self.mode_combo.currentText()
        if choice == self.tr('Median'):
            self.sigma_spin.setEnabled(False)
            denoised = cv.medianBlur(original, kernel)
        elif choice == self.tr('Gaussian'):
            self.sigma_spin.setEnabled(False)
            denoised = cv.GaussianBlur(original, (kernel, kernel), 0)
        elif choice == self.tr('BoxBlur'):
            self.sigma_spin.setEnabled(False)
            denoised = cv.blur(original, (kernel, kernel))
        elif choice == self.tr('Bilateral'):
            self.sigma_spin.setEnabled(True)
            denoised = cv.bilateralFilter(original, kernel, sigma, sigma)
        elif choice == self.tr('NonLocal'):
            if grayscale:
                denoised = cv.fastNlMeansDenoising(original, None, kernel)
            else:
                denoised = cv.fastNlMeansDenoisingColored(
                    original, None, kernel, kernel)
        else:
            denoised = None

        if self.denoised_check.isChecked():
            self.levels_spin.setEnabled(False)
            result = denoised
        else:
            self.levels_spin.setEnabled(True)
            noise = cv.absdiff(original, denoised)
            levels = self.levels_spin.value()
            if levels == 0:
                if grayscale:
                    result = cv.equalizeHist(noise)
                else:
                    result = equalize_img(noise)
            else:
                result = cv.LUT(noise, create_lut(0, 255 - levels))
        if grayscale:
            result = cv.cvtColor(result, cv.COLOR_GRAY2BGR)
        self.viewer.update_processed(result)
        self.info_message.emit(
            self.tr('Noise estimation = {}'.format(elapsed_time(start))))
Esempio n. 22
0
class QFlightSlotEditor(QGroupBox):

    changed = Signal()

    def __init__(self, package_model: PackageModel, flight: Flight,
                 game: Game):
        super().__init__("Slots")
        self.package_model = package_model
        self.flight = flight
        self.game = game
        self.inventory = self.game.aircraft_inventory.for_control_point(
            flight.from_cp)
        available = self.inventory.available(self.flight.unit_type)
        max_count = self.flight.count + available
        if max_count > 4:
            max_count = 4

        layout = QGridLayout()

        self.aircraft_count = QLabel("Aircraft count:")
        self.aircraft_count_spinner = QSpinBox()
        self.aircraft_count_spinner.setMinimum(1)
        self.aircraft_count_spinner.setMaximum(max_count)
        self.aircraft_count_spinner.setValue(flight.count)
        self.aircraft_count_spinner.valueChanged.connect(
            self._changed_aircraft_count)

        self.client_count = QLabel("Client slots count:")
        self.client_count_spinner = QSpinBox()
        self.client_count_spinner.setMinimum(0)
        self.client_count_spinner.setMaximum(max_count)
        self.client_count_spinner.setValue(flight.client_count)
        self.client_count_spinner.valueChanged.connect(
            self._changed_client_count)

        if not self.flight.unit_type.flyable:
            self.client_count_spinner.setValue(0)
            self.client_count_spinner.setEnabled(False)

        layout.addWidget(self.aircraft_count, 0, 0)
        layout.addWidget(self.aircraft_count_spinner, 0, 1)

        layout.addWidget(self.client_count, 1, 0)
        layout.addWidget(self.client_count_spinner, 1, 1)

        self.setLayout(layout)

    def _changed_aircraft_count(self):
        self.game.aircraft_inventory.return_from_flight(self.flight)
        old_count = self.flight.count
        self.flight.count = int(self.aircraft_count_spinner.value())
        try:
            self.game.aircraft_inventory.claim_for_flight(self.flight)
        except ValueError:
            # The UI should have prevented this, but if we ran out of aircraft
            # then roll back the inventory change.
            difference = self.flight.count - old_count
            available = self.inventory.available(self.flight.unit_type)
            logging.error(
                f"Could not add {difference} additional aircraft to "
                f"{self.flight} because {self.flight.from_cp} has only "
                f"{available} {self.flight.unit_type} remaining")
            self.flight.count = old_count
            self.game.aircraft_inventory.claim_for_flight(self.flight)
        self.changed.emit()

    def _changed_client_count(self):
        self.flight.client_count = int(self.client_count_spinner.value())
        self._cap_client_count()
        self.package_model.update_tot()
        self.changed.emit()

    def _cap_client_count(self):
        if self.flight.client_count > self.flight.count:
            self.flight.client_count = self.flight.count
            self.client_count_spinner.setValue(self.flight.client_count)
class StatisticsOptions(QWidget):
    polymorphic_states = {
      'Regression': {'dtext': 'Tipo de Regressão:', 'xtext': 'Selecione a coluna dos valores correspondentes à variável independente:', 'ytext': 'Selecione a coluna dos valores correspondentes à variável dependente:', 'dropdown': ['Linear', 'Exponencial', 'Logarítmica', 'Potencial', 'Polinomial'], 'ctext':''},
      'Statistics': {'dtext': 'Tipo de análise estatística:', 'xtext': 'Selecione a coluna dos valores para realizar a análise:', 'ytext': '', 'dropdown': ['Média aritmética', 'Mediana', 'Moda', 'Variância Pop.', 'Variância Am.', 'Desvio Padrão Pop.', 'Desvio Padrão Am.', 'Máximo', 'Mínimo', 'Amplitude', 'Quartil', 'Percentil'], 'ctext':''},
      'Histogram':  {'dtext': '', 'xtext': 'Selecione a coluna com os valores:', 'ytext': '', 'dropdown': [], 'ctext':''},
      'Boxplot':    {'dtext': 'Orientação do gráfico:', 'ctext': 'Selecione as colunas onde se encontram as séries para o Boxplot (i.e. B, B:C, A:C:F:G):', 'ytext': '', 'dropdown': ['Vertical', 'Horizontal'], 'xtext':''},
    }
    ready2calculate = Signal(bool)

    def __init__(self, _mode='Regression'):
        super().__init__()

        self.mode = _mode

        self.subtitle = QLabel(str(_mode))

        self.dropdown_text = QLabel(self.polymorphic_states[self.mode]['dtext'])
        self.dropdown_text.setWordWrap(True)
        self.dropdown = Dropdown(self.polymorphic_states[self.mode]['dropdown'])

        self.x_column_text = QLabel(self.polymorphic_states[self.mode]['xtext'])
        self.x_column_text.setWordWrap(True)
        self.x_column = QLineEdit()

        self.y_column_text = QLabel(self.polymorphic_states[self.mode]['ytext'])
        self.y_column_text.setWordWrap(True)
        self.y_column = QLineEdit()

        self.column_range_text = QLabel(self.polymorphic_states[self.mode]['ctext'])
        self.column_range_text.setWordWrap(True)
        self.column_range = QLineEdit()

        self.output_text = QLabel('Select Output:')
        self.output_text.setWordWrap(True)
        self.table_button = QRadioButton('Tabela (Planilha)')
        self.plot_button = QRadioButton('Gráfico (Plot)')
        self.output_destination_text = QLabel('Selecione a coluna onde deve-se armazenar os resultados:')
        self.output_destination_text.setWordWrap(True)
        self.output_destination = QLineEdit()
        self.run_button = QPushButton('Começar Análise')
        self.selected_output = ''

        self.degree_l = QLabel('Ordem:')
        self.degree = QSpinBox()
        self.degree.setRange(1, 6)

        self.quartile_l = QLabel('Quartil:')
        self.quartile = QSpinBox()
        self.quartile.setRange(1, 4)

        self.percentile_l = QLabel('Percentil:')
        self.percentile = QSpinBox()
        self.percentile.setRange(1, 100)

        self.default_degree_stylesheet = self.degree.styleSheet()
        self.default_quartile_stylesheet = self.quartile.styleSheet()
        self.default_percentile_stylesheet = self.percentile.styleSheet()

        self.degree.setDisabled(True)

        self.results_l = QLabel('Resultados da análise: ')
        self.results = QTextEdit()

        self.payload = []

        self.buildLayout()
        self.connections()
        self.initialState()
        self.setStyleSheet('color:white; font-family: Bahnschrift SemiLight Condensed; font-size: 14px;')

        self.x_column.setStyleSheet('background-color: white; color: black')
        self.y_column.setStyleSheet('background-color: white; color: black')
        self.column_range.setStyleSheet('background-color: white; color: black')
        self.results.setStyleSheet('background-color: white; color: black')


    def buildLayout(self):
        layout = QFormLayout()
        if len(self.dropdown_text.text()) > 0:
            layout.addWidget(self.dropdown_text)
            layout.addWidget(self.dropdown)
        if len(self.x_column_text.text()) > 0:
            layout.addWidget(self.x_column_text)
            layout.addWidget(self.x_column)
        if len(self.y_column_text.text()) > 0:
            layout.addWidget(self.y_column_text)
            layout.addWidget(self.y_column)
        if len(self.column_range_text.text()) > 0:
            layout.addWidget(self.column_range_text)
            layout.addWidget(self.column_range)
        if self.mode == 'Statistics':
            layout.addWidget(self.quartile_l)
            layout.addWidget(self.quartile)
            layout.addWidget(self.percentile_l)
            layout.addWidget(self.percentile)
        if self.mode == 'Regression':
            layout.addWidget(self.degree_l)
            layout.addWidget(self.degree)
        layout.addWidget(self.run_button)
        if self.mode != 'Boxplot' and self.mode != "Histogram":
            layout.addWidget(self.results_l)
            layout.addWidget(self.results)

        self.setLayout(layout)

    def initialState(self):
        self.output_destination.setDisabled(True)

    def connections(self):
        self.plot_button.clicked.connect(self.plotSelected)
        self.table_button.clicked.connect(self.tableSelected)
        self.run_button.clicked.connect(self.collectPayload)
        self.dropdown.currentTextChanged.connect(self.enableDegreeBox)

    def columnRangeDecomposition(self, text):
        try:
            return text.split(sep=':')
        except Exception:
            print('A problem happened in decomposing the column ranges. Probable bad user input.')

    def plotSelected(self):
        self.output_destination.setDisabled(True)
        self.selected_output = 'Plot'

    def enableDegreeBox(self, text):
        if text == 'Polinomial':
            self.degree.setStyleSheet('background-color: white; color: black')
            self.degree.setEnabled(True)
        else:
            self.degree.setStyleSheet(self.default_degree_stylesheet)
            self.degree.setDisabled(True)

        if text == 'Quartil':
            self.quartile.setStyleSheet('background-color: white; color: black')
            self.quartile.setEnabled(True)
        else:
            self.quartile.setStyleSheet(self.default_degree_stylesheet)
            self.quartile.setDisabled(True)

        if text == 'Percentil':
            self.percentile.setStyleSheet('background-color: white; color: black')
            self.percentile.setEnabled(True)
        else:
            self.percentile.setStyleSheet(self.default_degree_stylesheet)
            self.percentile.setDisabled(True)


    def tableSelected(self):
        self.output_destination.setDisabled(False)
        self.selected_output = 'Table'

    def collectPayload(self):
        if len(self.column_range_text.text()) > 0:
            a = self.columnRangeDecomposition(self.column_range.text())
            b = 'V'
        else:
            a = None
            b = self.y_column.text()
        payload = {
            'calculate': self.dropdown.currentText(),
            'x_column': self.x_column.text(),
            'y_column': b,
            'z_column': None,
            'column_range': a,
            'output_selection': self.selected_output,
            'output_column': self.output_destination.text()
        }
        self.payload = payload
        self.ready2calculate.emit(True)
Esempio n. 24
0
class Widget(QWidget):

    cinema_url_label_text = "粘贴独播库的连续剧/综艺/动漫 URL: "
    movie_url_label_text = "粘贴独播库的电影 URL: "

    cinema_dest_label_text = "输入连续剧/综艺/动漫名 (用来命名下载的目录): "
    movie_dest_label_text = "输入电影名 (用来命名下载的文件): "

    def __init__(self):
        QWidget.__init__(self)

        self.q = None
        self.pool = None

        self.top = QHBoxLayout()
        self.top.setMargin(10)

        self.radioButtonMov = QRadioButton("电影")
        self.radioButtonCinema = QRadioButton("连续剧/综艺/动漫")

        self.top.addWidget(self.radioButtonMov)
        self.top.addWidget(self.radioButtonCinema)

        self.middle = QVBoxLayout()
        self.middle.setMargin(10)

        self.url_label = QLabel()
        self.url = QLineEdit()
        self.url_label.setBuddy(self.url)
        self.middle.addWidget(self.url_label)
        self.middle.addWidget(self.url)

        self.browse_folder_label = QLabel("下载到:")
        self.browseFolder = QPushButton("选择目录")
        self.browse_folder_label.setBuddy(self.browseFolder)
        self.middle.addWidget(self.browse_folder_label)
        self.middle.addWidget(self.browseFolder)
        self.browse_folder_value = ""

        self.dest_file_label = QLabel()
        # "输入电影/电视剧名 (用来命名下载的文件/目录): " title set by choose_movie_widgets() later
        self.folder_or_filename = QLineEdit()
        self.dest_file_label.setBuddy(self.folder_or_filename)
        self.middle.addWidget(self.dest_file_label)
        self.middle.addWidget(self.folder_or_filename)

        self.bk_cinemae_spin_from = 1
        self.bk_cinemae_spin_to = 1
        self.fromEpSpinBox = QSpinBox()
        self.fromEpSpinBox.setMinimum(1)
        self.fromEpSpinBox.setMaximum(2147483647)
        self.fromEpLabel = QLabel("&从第几集开始下载:")
        self.fromEpLabel.setBuddy(self.fromEpSpinBox)

        self.toEpSpinBox = QSpinBox()
        self.toEpSpinBox.setMinimum(1)
        self.toEpSpinBox.setMaximum(2147483647)
        self.toEpLabel = QLabel("&到第几集停止下载:")
        self.toEpLabel.setBuddy(self.toEpSpinBox)

        self.cinema_ly = QHBoxLayout()
        #self.cinema_ly.setMargin(10)
        self.cinema_ly.addWidget(self.fromEpLabel)
        self.cinema_ly.addWidget(self.fromEpSpinBox)
        self.cinema_ly.addWidget(self.toEpLabel)
        self.cinema_ly.addWidget(self.toEpSpinBox)
        self.middle.addLayout(self.cinema_ly)

        self.proxy_label = QLabel("(如有)代理:")
        self.proxy = QLineEdit()
        self.proxy_label.setBuddy(self.proxy)
        self.middle.addWidget(self.proxy_label)
        self.middle.addWidget(self.proxy)

        self.add = QPushButton("开始下载")
        self.add.setEnabled(False)
        self.middle.addWidget(self.add)

        self.stop_me = QPushButton("停止下载")
        self.stop_me.setEnabled(False)
        self.middle.addWidget(self.stop_me)

        self.log_area = QPlainTextEdit()
        self.log_area.setReadOnly(True)
        self.log_area.setMaximumBlockCount(1000)
        self.middle.addWidget(self.log_area)

        #self.table_view.setSizePolicy(size)
        #self.layout.addWidget(self.table)
        self.layout = QVBoxLayout()
        self.layout.addLayout(self.top)
        self.layout.addLayout(self.middle)
        self.setLayout(self.layout)

        self.radioButtonMov.toggled.connect(self.choose_movie_widgets)
        self.radioButtonCinema.toggled.connect(self.choose_cinema_widgets)
        self.url.textChanged[str].connect(self.check_disable_download)
        self.browseFolder.clicked.connect(self.add_folder)
        self.folder_or_filename.textChanged[str].connect(
            self.check_disable_download)
        self.add.clicked.connect(self.start_download)
        self.stop_me.clicked.connect(self.stop_download)

        self.radioButtonMov.setChecked(
            True)  #set default only after .connect above

        # TESTING PURPOSE
        '''
        self.radioButtonMov.setChecked(False)
        self.url.setText('https://www.duboku.net/voddetail-969.html')
        self.browse_folder_value = 'C:/Users/Administrator/Documents/duboku'
        self.folder_or_filename.setText('初恋')
        '''

        #set current process (not queue that one) log handler:
        logger = logging.getLogger(__name__)
        handler2 = LoggerWriter()
        logger.addHandler(handler2)
        logger.setLevel(logging.INFO)  #DEBUG
        handler2.emitter.sigLog.connect(self.log_area.appendPlainText)
        sys.stdout = handler2  #LoggerWriter()
        #sys.stderr = handler2 #Seems no difference
        #handler2.emitter.sigLog.emit('hihi')

    @Slot()
    def choose_movie_widgets(self):

        if self.radioButtonMov.isChecked():

            self.url_label.setText(self.movie_url_label_text)
            self.dest_file_label.setText(self.movie_dest_label_text)

            self.fromEpLabel.setDisabled(True)
            self.toEpLabel.setDisabled(True)

            self.fromEpSpinBox.setDisabled(True)
            self.toEpSpinBox.setDisabled(True)

            self.bk_cinemae_spin_from = self.fromEpSpinBox.value()
            self.bk_cinemae_spin_to = self.toEpSpinBox.value()
            self.fromEpSpinBox.setValue(1)
            self.toEpSpinBox.setValue(1)

    @Slot()
    def choose_cinema_widgets(self):

        if self.radioButtonCinema.isChecked():

            self.url_label.setText(self.cinema_url_label_text)
            self.dest_file_label.setText(self.cinema_dest_label_text)

            self.fromEpLabel.setEnabled(True)
            self.toEpLabel.setEnabled(True)

            self.fromEpSpinBox.setEnabled(True)
            self.toEpSpinBox.setEnabled(True)

            self.fromEpSpinBox.setValue(self.bk_cinemae_spin_from)
            self.toEpSpinBox.setValue(self.bk_cinemae_spin_to)

    @Slot()
    def add_folder(self, s):

        #fname = QFileDialog.getOpenFileName(self, 'Open file', "c:\'", "Image files (*.jpg *.gif)")
        #fname = QFileDialog.getOpenFileName(self, 'Open file', '', QFileDialog.ShowDirsOnly)
        fname = QFileDialog.getExistingDirectory(self, '选择下载至什么目录', '',
                                                 QFileDialog.ShowDirsOnly)
        #print('repr: ' + repr(fname))
        if fname and fname.strip():
            fname = fname.strip()
            self.browse_folder_value = fname
            #if getOpenFileName, will return ('/home/xiaobai/Pictures/disco.jpg', 'Image files (*.jpg *.gif)')
            #, while if getExistingDirectory, will return single path string only
            self.browseFolder.setText(fname)
            self.check_disable_download(fname)
        #else:
        #    print('User cancel')

    @Slot()
    def check_disable_download(self, s):

        if self.url.text().strip(
        ) and self.browse_folder_value and self.folder_or_filename.text():
            self.add.setEnabled(True)
        else:
            self.add.setEnabled(False)

    def task_done(self, retVal):
        self.add.setEnabled(True)
        self.stop_me.setEnabled(False)

    @Slot()
    def stop_download(self):
        if self.q:
            self.q.close()
        if self.pool:
            self.pool.terminate()
        self.add.setEnabled(True)
        self.stop_me.setEnabled(False)
        print('下载停止。')

    @Slot()
    def start_download(self):

        if self.fromEpSpinBox.value() > self.toEpSpinBox.value():
            self.log_area.setPlainText('[!] 从第几集必须小于或等于到第几集。')
            return

        #No need worry click twice too fast, it seems already handle by PySide2
        self.add.setEnabled(False)
        self.stop_me.setEnabled(True)
        self.log_area.clear()

        dest_full_path = os.path.join(self.browse_folder_value,
                                      self.folder_or_filename.text())
        '''
        print('dest_full_path: ' + repr(dest_full_path))
        print('self.url.text(): ' + repr(self.url.text()))
        print('self.fromEpSpinBox.value(): ' + repr(self.fromEpSpinBox.value()))
        print('self.toEpSpinBox.value(): ' + repr(self.toEpSpinBox.value()))
        '''

        import duboku_console

        #Windows can't set like that bcoz not update for args.url, must put explicitly
        #duboku_console.redirect_stdout_to_custom_stdout(arg_url, ...etc, LoggerWriter())

        #failed other process
        handler = LogHandlerOtherProcess()
        handler.emitter.sigLog.connect(self.log_area.appendPlainText)
        ''' #ref current process:
        logger = logging.getLogger(__name__)
        handler2 = LoggerWriter()
        logger.addHandler(handler2)
        logger.setLevel(logging.DEBUG)
        handler2.emitter.sigLog.connect(self.log_area.appendPlainText)
        sys.stdout = handler2 #LoggerWriter()
        #handler2.emitter.sigLog.emit('hihi')
        '''

        #handler = LoggerWriter()
        #handler.emitter.sigLog.connect(self.log_area.appendPlainText)

        self.q = multiprocessing.Queue()
        self.ql = QueueListener(self.q, handler)
        self.ql.start()

        self.pool = multiprocessing.Pool(1, worker_init, [self.q])

        if self.radioButtonMov.isChecked():
            self.pool.apply_async(duboku_console.main,
                                  args=(None, dest_full_path,
                                        self.fromEpSpinBox.value(),
                                        self.toEpSpinBox.value(),
                                        self.url.text().strip(),
                                        LoggerWriterOtherProcess(), False,
                                        self.proxy.text()),
                                  callback=self.task_done)
        else:
            self.pool.apply_async(duboku_console.main,
                                  args=(dest_full_path, None,
                                        self.fromEpSpinBox.value(),
                                        self.toEpSpinBox.value(),
                                        self.url.text().strip(),
                                        LoggerWriterOtherProcess(), False,
                                        self.proxy.text()),
                                  callback=self.task_done)
Esempio n. 25
0
class MixedDistributionChart(QDialog):
    def __init__(self, parent=None, show_mode=True, toolbar=False, use_animation=False):
        flags = Qt.Window | Qt.WindowTitleHint | Qt.CustomizeWindowHint | Qt.WindowCloseButtonHint
        super().__init__(parent=parent, f=flags)
        self.setWindowTitle(self.tr("Mixed Distribution Chart"))
        self.figure = plt.figure(figsize=(4, 3))
        self.axes = self.figure.subplots()
        self.canvas = FigureCanvas(self.figure)
        self.toolbar = NavigationToolbar(self.canvas, self)
        self.main_layout = QGridLayout(self)
        self.main_layout.addWidget(self.toolbar, 0, 0, 1, 2)
        self.main_layout.addWidget(self.canvas, 1, 0, 1, 2)
        if not toolbar:
            self.toolbar.hide()
        self.supported_scales = [("log-linear", self.tr("Log-linear")),
                                 ("log", self.tr("Log")),
                                 ("phi", self.tr("φ")),
                                 ("linear", self.tr("Linear"))]

        self.scale_label = QLabel(self.tr("Scale"))
        self.scale_combo_box = QComboBox()
        self.scale_combo_box.addItems([name for key, name in self.supported_scales])
        self.scale_combo_box.currentIndexChanged.connect(self.update_chart)
        self.main_layout.addWidget(self.scale_label, 2, 0)
        self.main_layout.addWidget(self.scale_combo_box, 2, 1)
        self.interval_label = QLabel(self.tr("Interval [ms]"))
        self.interval_input = QSpinBox()
        self.interval_input.setRange(0, 10000)
        self.interval_input.setValue(30)
        self.interval_input.valueChanged.connect(self.update_animation)
        self.main_layout.addWidget(self.interval_label, 3, 0)
        self.main_layout.addWidget(self.interval_input, 3, 1)
        self.repeat_check_box = QCheckBox(self.tr("Repeat"))
        self.repeat_check_box.setChecked(False)
        self.repeat_check_box.stateChanged.connect(self.update_animation)
        self.save_button = QPushButton(self.tr("Save"))
        self.save_button.clicked.connect(self.save_animation)
        self.main_layout.addWidget(self.repeat_check_box, 4, 0)
        self.main_layout.addWidget(self.save_button, 4, 1)
        self.show_mode = show_mode
        self.animation = None
        self.last_model = None
        self.last_result = None

        if not use_animation:
            self.interval_label.setVisible(False)
            self.interval_input.setVisible(False)
            self.repeat_check_box.setVisible(False)
            self.save_button.setVisible(False)

        self.normal_msg = QMessageBox(parent=self)
        self.file_dialog = QFileDialog(parent=self)

    @property
    def scale(self) -> str:
        index = self.scale_combo_box.currentIndex()
        key, name = self.supported_scales[index]
        return key

    @property
    def transfer(self) -> typing.Callable:
        if self.scale == "log-linear":
            return lambda classes_φ: convert_φ_to_μm(classes_φ)
        elif self.scale == "log":
            return lambda classes_φ: np.log(convert_φ_to_μm(classes_φ))
        elif self.scale == "phi":
            return lambda classes_φ: classes_φ
        elif self.scale == "linear":
            return lambda classes_φ: convert_φ_to_μm(classes_φ)

    @property
    def xlabel(self) -> str:
        if self.scale == "log-linear":
            return self.tr("Grain-size [μm]")
        elif self.scale == "log":
            return self.tr("Ln(grain-size in μm)")
        elif self.scale == "phi":
            return self.tr("Grain-size [φ]")
        elif self.scale == "linear":
            return self.tr("Grain-size [μm]")

    @property
    def ylabel(self) -> str:
        return self.tr("Frequency")

    @property
    def xlog(self) -> bool:
        if self.scale == "log-linear":
            return True
        else:
            return False

    @property
    def interval(self) -> float:
        return self.interval_input.value()

    @property
    def repeat(self) -> bool:
        return self.repeat_check_box.isChecked()

    def show_demo(self):
        demo_model = get_demo_view_model()
        self.show_model(demo_model)

    def update_chart(self):
        if self.last_model is not None:
            self.show_model(self.last_model)
        elif self.last_result is not None:
            self.show_result(self.last_result)

    def update_animation(self):
        if self.last_result is not None:
            self.show_result(self.last_result)

    def show_model(self, model: SSUViewModel, quick=False):
        if self.animation is not None:
            self.animation._stop()
            self.animation = None
        if not quick:
            self.last_result = None

            self.last_model = model
            self.interval_label.setEnabled(False)
            self.interval_input.setEnabled(False)
            self.repeat_check_box.setEnabled(False)
            self.save_button.setEnabled(False)

            self.axes.clear()
            x = self.transfer(model.classes_φ)
            if self.xlog:
                self.axes.set_xscale("log")
            self.axes.set_title(model.title)
            self.axes.set_xlabel(self.xlabel)
            self.axes.set_ylabel(self.ylabel)
            self.target = self.axes.plot(x, model.target, c="#ffffff00", marker=".", ms=8, mfc="black", mew=0.0, label=self.tr("Target"))[0]
            # scatter can not be modified from the tool bar
            # self.target = self.axes.scatter(x, model.target, c="black", s=1)
            self.axes.set_xlim(x[0], x[-1])
            self.axes.set_ylim(0.0, round(np.max(model.target)*1.2, 2))
            self.mixed = self.axes.plot(x, model.mixed, c="black", label=self.tr("Mixed"))[0]
            self.components = [self.axes.plot(x, distribution*fraction, c=plt.get_cmap()(i), label=model.component_prefix+str(i+1))[0] for i, (distribution, fraction) in enumerate(zip(model.distributions, model.fractions))]
            if self.show_mode:
                modes = [self.transfer(model.classes_φ[np.unravel_index(np.argmax(distribution), distribution.shape)])  for distribution in model.distributions]
                colors = [plt.get_cmap()(i) for i in range(model.n_components)]
                self.vlines = self.axes.vlines(modes, 0.0, round(np.max(model.target)*1.2, 2), colors=colors)
            if model.n_components < 6:
                self.axes.legend(loc="upper left")
            self.figure.tight_layout()
            self.canvas.draw()
        else:
            self.mixed.set_ydata(model.mixed)
            for comp, distribution, fraction in zip(self.components, model.distributions, model.fractions):
                comp.set_ydata(distribution*fraction)
            if self.show_mode:
                modes = [self.transfer(model.classes_φ[np.unravel_index(np.argmax(distribution), distribution.shape)])  for distribution in model.distributions]
                self.vlines.set_offsets(modes)
            self.canvas.draw()

    def show_result(self, result: SSUResult):
        if self.animation is not None:
            self.animation._stop()
            self.animation = None
        self.last_model = None
        self.last_result = result
        self.interval_label.setEnabled(True)
        self.interval_input.setEnabled(True)
        self.repeat_check_box.setEnabled(True)
        self.save_button.setEnabled(True)

        models = iter(result.view_models)
        first = next(models)
        x = self.transfer(first.classes_φ)
        self.axes.cla()
        if self.xlog:
            self.axes.set_xscale("log")
        self.axes.set_title(first.title)
        self.axes.set_xlabel(self.xlabel)
        self.axes.set_ylabel(self.ylabel)
        self.target = self.axes.plot(x, first.target, c="#ffffff00", marker=".", ms=8, mfc="black", mew=0.0)[0]
        self.axes.set_xlim(x[0], x[-1])
        self.axes.set_ylim(0.0, round(np.max(first.target)*1.2, 2))
        self.figure.tight_layout()
        # self.canvas.draw()
        colors = [plt.get_cmap()(i) for i in range(first.n_components)]
        def init():
            model = first
            self.mixed = self.axes.plot(x, model.mixed, c="black")[0]
            self.components = [self.axes.plot(x, distribution*fraction, c=plt.get_cmap()(i))[0] for i, (distribution, fraction) in enumerate(zip(model.distributions, model.fractions))]
            if self.show_mode:
                modes = [self.transfer(model.classes_φ[np.unravel_index(np.argmax(distribution), distribution.shape)])  for distribution in model.distributions]
                self.vlines = self.axes.vlines(modes, 0.0, round(np.max(model.target)*1.2, 2), colors=colors)
            return self.mixed, self.vlines, *self.components
        def animate(current):
            model = current
            self.mixed.set_ydata(current.mixed)
            for line, distribution, fraction in zip(self.components, model.distributions, model.fractions):
                line.set_ydata(distribution*fraction)
            if self.show_mode:
                self.vlines.remove()
                modes = [self.transfer(model.classes_φ[np.unravel_index(np.argmax(distribution), distribution.shape)])  for distribution in model.distributions]
                self.vlines = self.axes.vlines(modes, 0.0, round(np.max(model.target)*1.2, 2), colors=colors)
            return self.mixed, self.vlines, *self.components
        self.animation = FuncAnimation(self.figure, animate, frames=models, init_func=init,
                                       interval=self.interval, blit=True,
                                       repeat=self.repeat, repeat_delay=3.0, save_count=result.n_iterations)

    def save_animation(self):
        if self.last_result is not None:
            filename, format_str = self.file_dialog.getSaveFileName(self, self.tr("Save the animation of this SSU result"), None, self.tr("MPEG-4 Video File (*.mp4);;Graphics Interchange Format (*.gif)"))
            if filename is None or filename == "":
                return
            progress = QProgressDialog(self)
            progress.setRange(0, 100)
            progress.setLabelText(self.tr("Saving Animation [{0} Frames]").format(self.last_result.n_iterations))
            canceled = False
            def save_callback(i, n):
                if progress.wasCanceled():
                    nonlocal canceled
                    canceled = True
                    raise StopIteration()
                progress.setValue((i+1)/n*100)
                QCoreApplication.processEvents()
            self.show_result(self.last_result)
            # plt.rcParams["savefig.dpi"] = 120.0
            if "*.gif" in format_str:
                if not ImageMagickWriter.isAvailable():
                    self.normal_msg.setWindowTitle(self.tr("Error"))
                    self.normal_msg.setText(self.tr("ImageMagick is not installed, please download and install it from its offical website (https://imagemagick.org/index.php)."))
                    self.normal_msg.exec_()
                else:
                    self.animation.save(filename, writer="imagemagick", fps=30, progress_callback=save_callback)
            elif "*.mp4" in format_str:
                if not FFMpegWriter.isAvailable():
                    self.normal_msg.setWindowTitle(self.tr("Error"))
                    self.normal_msg.setText(self.tr("FFMpeg is not installed, please download and install it from its offical website (https://ffmpeg.org/)."))
                    self.normal_msg.exec_()
                else:
                    self.animation.save(filename, writer="ffmpeg", fps=30, progress_callback=save_callback)
            # plt.rcParams["savefig.dpi"] = 300.0
            if not canceled:
                progress.setValue(100)
class RenameOptionsView(QWidget):
    """View responsible for holding renaming options.
    
    Attributes:
        layout (QVBoxLayout): Main layout of view.
        frame_layout (QVBoxLayout: Layout of frame which holds options.
        frame (QFrame): Frame surrounding options.
        prefix_h_layout (QHBoxLayout): Layout holding prefix options.
        complete_rename_h_layout (QHBoxLayout): Layout holding complete rename options.
        search_and_replace_h_layout (QHBoxLayout): Layout holding search and replace options.
        renumber_h_layout (QHBoxLayout): Layout holding renumber options.
        remove_ext_h_layout (QHBoxLayout): Layout holding remove options.
        change_ext_h_layout (QHBoxLayout): Layout holding change extension options.
        create_backup_h_layout (QHBoxLayout): Layout holding backup options.
        preview_h_layout (QHBoxLayout): Layout holding preview options.
        start_lbl (QLabel): Label for renumbering start.
        padding_lbl (QLabel): Label for renumbering padding.
        add_prefix_cb (QCheckBox): Used to signify the user wants to add a prefix to the renaming.
        prefix (QLineEdit): prefix to add.
        complete_rename_cb (QCheckBox): Used to signify the user wants to completely rename the file.
        new_name (QLineEdit): New name used when renaming.
        search_and_replace_cb (QCheckBox): Used to signify the user wants to partially rename files.
        find (QLineEdit): When searching and replacing this is what the user wants to search for.
        replace (QLineEdit): When searching and replacing this is what the user wants to replace with.
        renumber_cb (QCheckBox): Used to signify the user wants to renumber while renaming.
        start_num (QSpinBox): Number to start with when renumbering files.
        padding (QComboBox): Padding to apply to renaming when renumbering files.
        dot_cb (QCheckBox): When checked a dot will be used to separate the renumber from the name.
        remove_ext_cb (QCheckBox): Used to signify the user wants to remove extensions when renaming.
        backup_files_cb (QCheckBox): Used to signify the user wants to backup old files before renaming.
        change_ext_cb (QCheckBox): Used to signify the user wants to change the extension while renaming.
        change_ext (QLineEdit): New extension to add to the renamed file.
        preview_cb (QCheckBox): Used to signify the user wants to preview the rename before renaming.
    """
    def __init__(self):
        super(RenameOptionsView, self).__init__()
        self.layout = QVBoxLayout()
        self.frame_layout = QVBoxLayout()
        self.options_lbl = QLabel(prefs.OPTIONS)
        self.frame = QFrame()
        self.prefix_h_layout = QHBoxLayout()
        self.complete_rename_h_layout = QHBoxLayout()
        self.search_and_replace_h_layout = QHBoxLayout()
        self.renumber_h_layout = QHBoxLayout()
        self.remove_ext_h_layout = QHBoxLayout()
        self.change_ext_h_layout = QHBoxLayout()
        self.create_backup_h_layout = QHBoxLayout()
        self.preview_h_layout = QHBoxLayout()
        self.start_lbl = QLabel(prefs.START_NUM)
        self.padding_lbl = QLabel(prefs.PADDING)
        self.add_prefix_cb = QCheckBox(prefs.PREFIX)
        self.prefix = QLineEdit(prefs.PREFIX_DEFAULT)
        self.complete_rename_cb = QCheckBox(prefs.COMPLETE_RENAME)
        self.new_name = QLineEdit(prefs.COMPLETE_RENAME_DEFAULT)
        self.search_and_replace_cb = QCheckBox(prefs.SEARCH_AND_REPLACE)
        self.find = QLineEdit(prefs.SEARCH_AND_REPLACE_DEFAULT)
        self.replace = QLineEdit(prefs.REPLACE_WITH_DEFAULT)
        self.renumber_cb = QCheckBox(prefs.RENUMBER)
        self.start_num = QSpinBox()
        self.padding = QComboBox()
        self.dot_cb = QCheckBox(prefs.USE_DOT)
        self.remove_ext_cb = QCheckBox(prefs.REMOVE_EXT)
        self.backup_files_cb = QCheckBox(prefs.BACKUP)
        self.change_ext_cb = QCheckBox(prefs.CHANGE_EXT)
        self.change_ext = QLineEdit(prefs.CHANGE_EXT_DEFAULT)
        self.preview_cb = QCheckBox(prefs.PREVIEW)

        self._configure()

    def _configure(self) -> None:
        """Configure the RenameOptionsView."""
        self.frame.setLayout(self.frame_layout)
        self.frame.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken)
        self.layout.addWidget(self.options_lbl)
        self.layout.addWidget(self.frame)
        self.add_prefix_cb.setToolTip(prefs.PREFIX_TOOLTIP)
        self.prefix.setDisabled(True)
        self.prefix.setMaximumWidth(prefs.PREFIX_WIDTH)
        self.prefix.setMinimumWidth(prefs.PREFIX_WIDTH)
        self.complete_rename_cb.setToolTip(prefs.COMPLETE_RENAME_TOOLTIP)
        self.new_name.setDisabled(True)
        self.new_name.setMaximumWidth(prefs.NEW_NAME_WIDTH)
        self.new_name.setMinimumWidth(prefs.NEW_NAME_WIDTH)
        self.search_and_replace_cb.setToolTip(prefs.SEARCH_AND_REPLACE_TOOLTIP)
        self.find.setDisabled(True)
        self.find.setMinimumWidth(prefs.FIND_WIDTH)
        self.find.setMaximumWidth(prefs.FIND_WIDTH)
        self.replace.setDisabled(True)
        self.replace.setMaximumWidth(prefs.REPLACE_WIDTH)
        self.replace.setMinimumWidth(prefs.REPLACE_WIDTH)
        self.renumber_cb.setToolTip(prefs.RENUMBER_TOOLTIP)
        self.start_num.setToolTip(prefs.START_NUM_TOOLTIP)
        self.start_num.setDisabled(True)
        self.start_num.setValue(prefs.START_NUM_DEFAULT)
        self.start_num.setMinimumWidth(prefs.START_NUM_MIN_WIDTH)
        self.padding.setToolTip(prefs.PADDING_TOOLTIP)
        self.padding.setDisabled(True)
        self.padding.addItems([str(x) for x in range(10)])
        self.padding.setCurrentIndex(4)
        self.padding.setMinimumWidth(prefs.PADDING_MIN_WIDTH)
        self.dot_cb.setToolTip(prefs.USE_DOT_TOOLTIP)
        self.dot_cb.setDisabled(True)
        self.dot_cb.setChecked(True)
        self.dot_cb.setMinimumWidth(prefs.DOT_WIDTH)
        self.dot_cb.setMaximumWidth(prefs.DOT_WIDTH)
        self.remove_ext_cb.setToolTip(prefs.REMOVE_EXT_TOOLTIP)
        self.change_ext.setToolTip(prefs.CHANGE_EXT_TOOLTIP)
        self.change_ext.setDisabled(True)
        self.backup_files_cb.setToolTip(prefs.BACKUP_TOOLTIP)
        self.backup_files_cb.setChecked(True)
        self.preview_cb.setToolTip(prefs.PREVIEW_TOOLTIP)
        self.preview_cb.setChecked(True)

        self.prefix_h_layout.addWidget(self.add_prefix_cb)
        self.prefix_h_layout.addWidget(self.prefix)
        self.frame_layout.addLayout(self.prefix_h_layout)

        self.complete_rename_h_layout.addWidget(self.complete_rename_cb)
        self.complete_rename_h_layout.addWidget(self.new_name)
        self.frame_layout.addLayout(self.complete_rename_h_layout)

        self.search_and_replace_h_layout.addWidget(self.search_and_replace_cb)
        self.search_and_replace_h_layout.addWidget(self.find)
        self.search_and_replace_h_layout.addWidget(self.replace)
        self.frame_layout.addLayout(self.search_and_replace_h_layout)

        self.renumber_h_layout.addWidget(self.renumber_cb)
        self.renumber_h_layout.addStretch(1)
        self.renumber_h_layout.addWidget(self.start_lbl)
        self.renumber_h_layout.addWidget(self.start_num)
        self.renumber_h_layout.addSpacerItem(QSpacerItem(*prefs.SPACER_SIZE))
        self.renumber_h_layout.addWidget(self.padding_lbl)
        self.renumber_h_layout.addWidget(self.padding)
        self.renumber_h_layout.addSpacerItem(QSpacerItem(*prefs.SPACER_SIZE))
        self.renumber_h_layout.addWidget(self.dot_cb)
        self.frame_layout.addLayout(self.renumber_h_layout)

        self.change_ext_h_layout.addWidget(self.change_ext_cb)
        self.change_ext_h_layout.addWidget(self.change_ext)
        self.frame_layout.addLayout(self.change_ext_h_layout)

        self.remove_ext_h_layout.addWidget(self.remove_ext_cb)
        self.frame_layout.addLayout(self.remove_ext_h_layout)

        self.create_backup_h_layout.addWidget(self.backup_files_cb)
        self.frame_layout.addLayout(self.create_backup_h_layout)

        self.preview_h_layout.addWidget(self.preview_cb)
        self.frame_layout.addLayout(self.preview_h_layout)

        self.frame_layout.addSpacerItem(QSpacerItem(*prefs.SPACER_SIZE))

        self.setLayout(self.layout)

    def disable_change_ext(self) -> None:
        """Disable change extension."""
        self.change_ext.setDisabled(True)

    def disable_dot(self) -> None:
        """Disable dot checkbox."""
        self.dot_cb.setDisabled(True)

    def disable_find(self) -> None:
        """Disable find."""
        self.find.setDisabled(True)

    def disable_new_name(self) -> None:
        """Disable new name."""
        print("disable new name")
        self.new_name.setDisabled(True)

    def disable_padding(self) -> None:
        """Disable padding."""
        self.padding.setDisabled(True)

    def disable_prefix(self) -> None:
        """Disable prefix."""
        self.prefix.setDisabled(True)

    def disable_start_num(self) -> None:
        """Disable start num."""
        self.start_num.setDisabled(True)

    def disable_replace(self) -> None:
        """Disable replace."""
        self.replace.setDisabled(True)

    def enable_change_ext(self) -> None:
        """Disable change extension."""
        self.change_ext.setDisabled(False)

    def enable_dot(self) -> None:
        """Enable dot checkbox."""
        self.dot_cb.setEnabled(True)

    def enable_find(self) -> None:
        """Enable find."""
        self.find.setEnabled(True)

    def enable_new_name(self) -> None:
        """Enable new name."""
        print("enable new name.")
        self.new_name.setEnabled(True)

    def enable_padding(self) -> None:
        """Enable padding."""
        self.padding.setEnabled(True)

    def enable_prefix(self) -> None:
        """Enable prefix."""
        self.prefix.setEnabled(True)

    def enable_replace(self) -> None:
        """Enable replace."""
        self.replace.setEnabled(True)

    def enable_start_num(self) -> None:
        """Enable start num."""
        self.start_num.setEnabled(True)

    def get_add_prefix(self) -> bool:
        """Return if end user wants to add a prefix and it is not the default value."""
        result = self.get_prefix_checked()
        if result and self.get_prefix() == prefs.PREFIX_DEFAULT:
            result = False
        return result

    def get_do_backup(self) -> bool:
        """Return if end user wants to backup files."""
        return self.backup_files_cb.isChecked()

    def get_change_ext(self) -> bool:
        """Return if the change extension checkbox is checked."""
        return self.change_ext_cb.isChecked()

    def get_do_complete_rename(self) -> bool:
        """Get if end user wants to completely rename."""
        return self.complete_rename_cb.isChecked()

    def get_dot(self) -> str:
        """Return dot string based on end users configuration.

        Note:
            If the end user has not enable using dot separators an empty string will be returned.
        """
        return "." if self.get_do_dot() else ""

    def get_do_dot(self) -> bool:
        """Return if the end user wants to use dot separators when renaming."""
        return self.dot_cb.isChecked()

    def get_do_change_ext(self) -> bool:
        """Return if the end user wants to change the extension."""
        result = self.change_ext_cb.isChecked()
        if self.get_new_ext() == prefs.CHANGE_EXT_DEFAULT:
            return False
        return result

    def get_do_padding(self) -> bool:
        """Return if the end user wants to add padding."""
        return False if self.get_padding() == 0 else True

    def get_do_preview(self) -> bool:
        """Return if the end user wants to preview changes."""
        return self.preview_cb.isChecked()

    def get_do_rename(self) -> bool:
        """Return if end user wants to rename the full item and it is not the default value."""
        result = self.complete_rename_cb.isChecked()
        if result and self.get_new_name() == prefs.COMPLETE_RENAME_DEFAULT:
            result = False
        return result

    def get_do_renumber(self) -> bool:
        """Return if the end user wants to renumber."""
        return self.renumber_cb.isChecked()

    def get_do_search(self) -> bool:
        """Return if end user wants to perform a search and replace AND it is not the default values respectfully.

        Note:
            If you only want to know if search and replace is checked use get_search_and_replace.
        """
        result = self.search_and_replace_cb.isChecked()
        if result and (self.get_find() == prefs.SEARCH_AND_REPLACE_DEFAULT
                       or self.get_replace() == prefs.REPLACE_WITH_DEFAULT):
            result = False
        return result

    def get_do_search_and_replace(self) -> bool:
        """Return if end user wants to perform a search and replace."""
        return self.search_and_replace_cb.isChecked()

    def get_find(self) -> str:
        """Return find value."""
        return str(self.find.text())

    def get_new_ext(self) -> str:
        """Return new ext."""
        return str(self.change_ext.text())

    def get_new_name(self) -> str:
        """Return new_name value."""
        return str(self.new_name.text())

    def get_padding(self) -> int:
        """Return the current padding value."""
        return int(self.padding.currentText())

    def get_prefix_checked(self) -> bool:
        """Return if the prefix checkbox is checked."""
        return self.add_prefix_cb.isChecked()

    def get_prefix(self) -> str:
        """Return the current prefix value end user has entered."""
        return str(self.prefix.text())

    def get_remove_ext(self) -> bool:
        """Return if end user has checked the remove extension checkbox."""
        return self.remove_ext_cb.isChecked()

    def get_replace(self) -> str:
        """Return the current replace value end user has entered."""
        return str(self.replace.text())

    def get_start_num(self) -> int:
        """Return start number from view."""
        return int(self.start_num.value())

    def set_change_ext_style(self, style: str) -> None:
        """Set style of change extension.

        Args:
            style: Style sheet applied to change extension.
        """
        self.change_ext.setStyleSheet(style)

    def set_disabled(self) -> None:
        """Disable View."""
        self.setDisabled(True)

    def set_enable(self) -> None:
        """Enable View."""
        self.setEnabled(True)

    def set_find(self, value: str) -> None:
        """Set the value of find.

        Args:
            value: Value applied to find
        """
        self.find.setText(value)

    def set_find_style(self, style: str) -> None:
        """Set style of find.

        Args:
            style: Style sheet applied to find.
        """
        self.find.setStyleSheet(style)

    def set_new_name(self, value: str) -> None:
        """Set the value of new name.

        Args:
            value: Value applied to new_name
        """
        self.new_name.setText(value)

    def set_new_name_style(self, style: str) -> None:
        """Set style of new_name.
        
        Args:
            style: Style sheet applied to new_name.
        """
        self.new_name.setStyleSheet(style)

    def set_prefix(self, value: str) -> None:
        """Set the value of prefix.

        Args:
            value: Value applied to prefix
        """
        self.prefix.setText(value)

    def set_prefix_style(self, style: str) -> None:
        """Set style of prefix.

        Args:
            style: Style sheet applied to prefix.
        """
        self.prefix.setStyleSheet(style)

    def set_remove_ext(self, state: bool) -> None:
        """Set the remove_ext checkbox as checked or unchecked.

        Args:
            state: Check state of remove_ext.
        """
        self.remove_ext_cb.setCheckState(Qt.Checked if state else Qt.Unchecked)

    def set_replace(self, value: str) -> None:
        """Set the value of replace.

        Args:
            value: Value applied to replace
        """
        self.replace.setText(value)

    def set_replace_style(self, style: str) -> None:
        """Set style of replace.

        Args:
            style: Style sheet applied to replace.
        """
        self.replace.setStyleSheet(style)
Esempio n. 27
0
    class Config(SignalNode.Config):
        """Config widget displayed for BandpassFilter."""
        def __init__(self, parent=None):
            super().__init__(parent=parent)

            # Upper bound ----------------------------------------------------------------------------------------------
            self.lower_bound_enable = QCheckBox()
            self.lower_bound_enable.setChecked(True)
            self.lower_bound_enable.stateChanged.connect(self.updateModel)

            self.lower_bound = QDoubleSpinBox()
            self.lower_bound.valueChanged.connect(self.updateModel)
            self.lower_bound.setMinimum(0)
            self.lower_bound.setMaximum(250)
            self.lower_bound.setSuffix(" Hz")

            layout = QHBoxLayout()
            layout.setContentsMargins(0, 0, 0, 0)
            lower_bound_widget = QWidget()
            lower_bound_widget.setContentsMargins(0, 0, 0, 0)
            lower_bound_widget.setLayout(layout)
            layout.addWidget(self.lower_bound_enable)
            layout.addWidget(self.lower_bound)

            # Lower bound ----------------------------------------------------------------------------------------------
            self.upper_bound_enable = QCheckBox()
            self.upper_bound_enable.setChecked(True)
            self.upper_bound_enable.stateChanged.connect(self.updateModel)

            self.upper_bound = QDoubleSpinBox()
            self.upper_bound.valueChanged.connect(self.updateModel)
            self.upper_bound.setMinimum(0)
            self.upper_bound.setMaximum(250)
            self.upper_bound.setSuffix(" Hz")

            layout = QHBoxLayout()
            layout.setContentsMargins(0, 0, 0, 0)
            upper_bound_widget = QWidget()
            upper_bound_widget.setContentsMargins(0, 0, 0, 0)
            upper_bound_widget.setLayout(layout)
            layout.addWidget(self.upper_bound_enable)
            layout.addWidget(self.upper_bound)

            # Filter type and length -----------------------------------------------------------------------------------
            self.filter_type = QComboBox()
            for name in BandpassFilter.filter_name_to_type:
                self.filter_type.addItem(name)
            self.filter_type.currentTextChanged.connect(self.updateModel)

            self.filter_length = QSpinBox()
            self.filter_length.setMinimum(2)
            self.filter_length.setMaximum(1000000)
            self.filter_length.setValue(1000)
            self.filter_length.valueChanged.connect(self.updateModel)

            self.filter_order = QSpinBox()
            self.filter_order.setRange(1, 4)
            self.filter_order.valueChanged.connect(self.updateModel)

            # ----------------------------------------------------------------------------------------------------------
            layout = QFormLayout()
            layout.addRow("Lower bound:", lower_bound_widget)
            layout.addRow("Upper bound:", upper_bound_widget)
            layout.addRow("Filter type:", self.filter_type)
            layout.addRow("Filter order:", self.filter_order)
            layout.addRow("Filter length:", self.filter_length)
            self.setLayout(layout)

        def updateModel(self):
            n = self.node()
            if n is None:
                return

            if self.lower_bound_enable.isChecked():
                lower_bound = self.lower_bound.value()
            else:
                lower_bound = None

            if self.upper_bound_enable.isChecked():
                upper_bound = self.upper_bound.value()
            else:
                upper_bound = None

            filter_type = n.filter_name_to_type[self.filter_type.currentText()]
            filter_length = self.filter_length.value()
            filter_order = self.filter_order.value()

            n.setLowerBound(lower_bound)
            n.setUpperBound(upper_bound)
            n.setFilterType(filter_type)
            n.setFilterLength(filter_length)
            n.setFilterOrder(filter_order)

        def updateView(self):
            n = self.node()
            if n is None:
                return

            # Prevent view fields from emitting signals while they are updated
            self.lower_bound.blockSignals(True)
            self.upper_bound.blockSignals(True)
            self.filter_type.blockSignals(True)
            self.filter_length.blockSignals(True)
            self.filter_order.blockSignals(True)

            if n.upperBound() is None:
                self.upper_bound_enable.setChecked(False)
            else:
                self.upper_bound_enable.setChecked(True)
                self.upper_bound.setValue(n.upperBound())

            if n.lowerBound() is None:
                self.lower_bound_enable.setChecked(False)
            else:
                self.lower_bound_enable.setChecked(True)
                self.lower_bound.setValue(n.lowerBound())

            self.filter_type.setCurrentText(
                n.filter_type_to_name[n.filterType()])
            self.filter_length.setValue(n.filterLength())
            self.filter_order.setValue(n.filterOrder())

            # Release the block and call adjust
            self.lower_bound.blockSignals(False)
            self.upper_bound.blockSignals(False)
            self.filter_type.blockSignals(False)
            self.filter_length.blockSignals(False)
            self.filter_order.blockSignals(False)
            self._adjust()

        def _adjust(self):
            """Adjust displayed values and limits in response to changes."""
            # Enable spinbox widgets based on their checkbox
            self.lower_bound.setEnabled(self.lower_bound_enable.isChecked())
            self.upper_bound.setEnabled(self.upper_bound_enable.isChecked())

            # Adjust min and max so that lower_bound is never higher than upper_bound
            if self.lower_bound_enable.isChecked():
                self.upper_bound.setMinimum(self.lower_bound.value())
            else:
                self.upper_bound.setMinimum(0)

            if self.upper_bound_enable.isChecked():
                self.lower_bound.setMaximum(self.upper_bound.value())
            else:
                self.lower_bound.setMaximum(250)

            if self.filter_type.currentText() == "Butterworth":
                self.filter_order.setEnabled(True)
            else:
                self.filter_order.setEnabled(False)
Esempio n. 28
0
class SSUResolverPanel(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent=parent, f=Qt.Window)
        self.setWindowTitle(self.tr("SSU Resolver"))
        self.distribution_types = [
            (DistributionType.Normal, self.tr("Normal")),
            (DistributionType.Weibull, self.tr("Weibull")),
            (DistributionType.SkewNormal, self.tr("Skew Normal"))
        ]
        self.load_dataset_dialog = LoadDatasetDialog(parent=self)
        self.load_dataset_dialog.dataset_loaded.connect(self.on_dataset_loaded)
        self.classic_setting = ClassicResolverSettingWidget(parent=self)
        self.neural_setting = NNResolverSettingWidget(parent=self)
        self.manual_panel = ManualFittingPanel(parent=self)
        self.manual_panel.manual_fitting_finished.connect(
            self.on_fitting_succeeded)
        self.async_worker = AsyncWorker()
        self.async_worker.background_worker.task_succeeded.connect(
            self.on_fitting_succeeded)
        self.async_worker.background_worker.task_failed.connect(
            self.on_fitting_failed)
        self.normal_msg = QMessageBox(self)
        self.dataset = None
        self.task_table = {}
        self.task_results = {}
        self.failed_task_ids = []
        self.__continuous_flag = False
        self.init_ui()

    def init_ui(self):
        self.setAttribute(Qt.WA_StyledBackground, True)
        self.main_layout = QGridLayout(self)
        # self.main_layout.setContentsMargins(0, 0, 0, 0)
        # control group
        self.control_group = QGroupBox(self.tr("Control"))
        self.control_layout = QGridLayout(self.control_group)
        self.resolver_label = QLabel(self.tr("Resolver"))
        self.resolver_combo_box = QComboBox()
        self.resolver_combo_box.addItems(["classic", "neural"])
        self.control_layout.addWidget(self.resolver_label, 0, 0)
        self.control_layout.addWidget(self.resolver_combo_box, 0, 1)
        self.load_dataset_button = QPushButton(qta.icon("fa.database"),
                                               self.tr("Load Dataset"))
        self.load_dataset_button.clicked.connect(self.on_load_dataset_clicked)
        self.configure_fitting_button = QPushButton(
            qta.icon("fa.gears"), self.tr("Configure Fitting Algorithm"))
        self.configure_fitting_button.clicked.connect(
            self.on_configure_fitting_clicked)
        self.control_layout.addWidget(self.load_dataset_button, 1, 0)
        self.control_layout.addWidget(self.configure_fitting_button, 1, 1)
        self.distribution_label = QLabel(self.tr("Distribution Type"))
        self.distribution_combo_box = QComboBox()
        self.distribution_combo_box.addItems(
            [name for _, name in self.distribution_types])
        self.component_number_label = QLabel(self.tr("N<sub>components</sub>"))
        self.n_components_input = QSpinBox()
        self.n_components_input.setRange(1, 10)
        self.n_components_input.setValue(3)
        self.control_layout.addWidget(self.distribution_label, 2, 0)
        self.control_layout.addWidget(self.distribution_combo_box, 2, 1)
        self.control_layout.addWidget(self.component_number_label, 3, 0)
        self.control_layout.addWidget(self.n_components_input, 3, 1)

        self.n_samples_label = QLabel(self.tr("N<sub>samples</sub>"))
        self.n_samples_display = QLabel(self.tr("Unknown"))
        self.control_layout.addWidget(self.n_samples_label, 4, 0)
        self.control_layout.addWidget(self.n_samples_display, 4, 1)
        self.sample_index_label = QLabel(self.tr("Sample Index"))
        self.sample_index_input = QSpinBox()
        self.sample_index_input.valueChanged.connect(
            self.on_sample_index_changed)
        self.sample_index_input.setEnabled(False)
        self.control_layout.addWidget(self.sample_index_label, 5, 0)
        self.control_layout.addWidget(self.sample_index_input, 5, 1)
        self.sample_name_label = QLabel(self.tr("Sample Name"))
        self.sample_name_display = QLabel(self.tr("Unknown"))
        self.control_layout.addWidget(self.sample_name_label, 6, 0)
        self.control_layout.addWidget(self.sample_name_display, 6, 1)

        self.manual_test_button = QPushButton(qta.icon("fa.sliders"),
                                              self.tr("Manual Test"))
        self.manual_test_button.setEnabled(False)
        self.manual_test_button.clicked.connect(self.on_manual_test_clicked)
        self.load_reference_button = QPushButton(qta.icon("mdi.map-check"),
                                                 self.tr("Load Reference"))
        self.load_reference_button.clicked.connect(
            lambda: self.reference_view.load_dump(mark_ref=True))
        self.control_layout.addWidget(self.manual_test_button, 7, 0)
        self.control_layout.addWidget(self.load_reference_button, 7, 1)

        self.single_test_button = QPushButton(qta.icon("fa.play-circle"),
                                              self.tr("Single Test"))
        self.single_test_button.setEnabled(False)
        self.single_test_button.clicked.connect(self.on_single_test_clicked)
        self.continuous_test_button = QPushButton(
            qta.icon("mdi.playlist-play"), self.tr("Continuous Test"))
        self.continuous_test_button.setEnabled(False)
        self.continuous_test_button.clicked.connect(
            self.on_continuous_test_clicked)
        self.control_layout.addWidget(self.single_test_button, 8, 0)
        self.control_layout.addWidget(self.continuous_test_button, 8, 1)

        self.test_previous_button = QPushButton(
            qta.icon("mdi.skip-previous-circle"), self.tr("Test Previous"))
        self.test_previous_button.setEnabled(False)
        self.test_previous_button.clicked.connect(
            self.on_test_previous_clicked)
        self.test_next_button = QPushButton(qta.icon("mdi.skip-next-circle"),
                                            self.tr("Test Next"))
        self.test_next_button.setEnabled(False)
        self.test_next_button.clicked.connect(self.on_test_next_clicked)
        self.control_layout.addWidget(self.test_previous_button, 9, 0)
        self.control_layout.addWidget(self.test_next_button, 9, 1)

        # chart group
        self.chart_group = QGroupBox(self.tr("Chart"))
        self.chart_layout = QGridLayout(self.chart_group)
        self.result_chart = MixedDistributionChart(show_mode=True,
                                                   toolbar=False)
        self.chart_layout.addWidget(self.result_chart, 0, 0)

        # table group
        self.table_group = QGroupBox(self.tr("Table"))
        self.reference_view = ReferenceResultViewer()
        self.result_view = FittingResultViewer(self.reference_view)
        self.result_view.result_marked.connect(
            lambda result: self.reference_view.add_references([result]))
        self.table_tab = QTabWidget()
        self.table_tab.addTab(self.result_view, qta.icon("fa.cubes"),
                              self.tr("Result"))
        self.table_tab.addTab(self.reference_view, qta.icon("fa5s.key"),
                              self.tr("Reference"))
        self.result_layout = QGridLayout(self.table_group)
        self.result_layout.addWidget(self.table_tab, 0, 0)

        # pack all group
        self.splitter1 = QSplitter(Qt.Orientation.Vertical)
        self.splitter1.addWidget(self.control_group)
        self.splitter1.addWidget(self.chart_group)
        self.splitter2 = QSplitter(Qt.Orientation.Horizontal)
        self.splitter2.addWidget(self.splitter1)
        self.splitter2.addWidget(self.table_group)
        self.main_layout.addWidget(self.splitter2, 0, 0)

    @property
    def distribution_type(self) -> DistributionType:
        distribution_type, _ = self.distribution_types[
            self.distribution_combo_box.currentIndex()]
        return distribution_type

    @property
    def n_components(self) -> int:
        return self.n_components_input.value()

    def show_message(self, title: str, message: str):
        self.normal_msg.setWindowTitle(title)
        self.normal_msg.setText(message)
        self.normal_msg.exec_()

    def show_info(self, message: str):
        self.show_message(self.tr("Info"), message)

    def show_warning(self, message: str):
        self.show_message(self.tr("Warning"), message)

    def show_error(self, message: str):
        self.show_message(self.tr("Error"), message)

    def on_load_dataset_clicked(self):
        self.load_dataset_dialog.show()

    def on_dataset_loaded(self, dataset: GrainSizeDataset):
        self.dataset = dataset
        self.n_samples_display.setText(str(dataset.n_samples))
        self.sample_index_input.setRange(1, dataset.n_samples)
        self.sample_index_input.setEnabled(True)
        self.manual_test_button.setEnabled(True)
        self.single_test_button.setEnabled(True)
        self.continuous_test_button.setEnabled(True)
        self.test_previous_button.setEnabled(True)
        self.test_next_button.setEnabled(True)

    def on_configure_fitting_clicked(self):
        if self.resolver_combo_box.currentText() == "classic":
            self.classic_setting.show()
        else:
            self.neural_setting.show()

    def on_sample_index_changed(self, index):
        self.sample_name_display.setText(self.dataset.samples[index - 1].name)

    def generate_task(self, query_ref=True):
        sample_index = self.sample_index_input.value() - 1
        sample = self.dataset.samples[sample_index]

        resolver = self.resolver_combo_box.currentText()
        if resolver == "classic":
            setting = self.classic_setting.setting
        else:
            setting = self.neural_setting.setting

        query = self.reference_view.query_reference(sample)  # type: SSUResult
        if not query_ref or query is None:
            task = SSUTask(sample,
                           self.distribution_type,
                           self.n_components,
                           resolver=resolver,
                           resolver_setting=setting)
        else:
            keys = ["mean", "std", "skewness"]
            # reference = [{key: comp.logarithmic_moments[key] for key in keys} for comp in query.components]
            task = SSUTask(
                sample,
                query.distribution_type,
                query.n_components,
                resolver=resolver,
                resolver_setting=setting,
                # reference=reference)
                initial_guess=query.last_func_args)
        return task

    def on_fitting_succeeded(self, fitting_result: SSUResult):
        # update chart
        self.result_chart.show_model(fitting_result.view_model)
        self.result_view.add_result(fitting_result)
        self.task_results[fitting_result.task.uuid] = fitting_result
        if self.__continuous_flag:
            if self.sample_index_input.value() == self.dataset.n_samples:
                self.on_continuous_test_clicked()
            else:
                self.sample_index_input.setValue(
                    self.sample_index_input.value() + 1)
                self.do_test()
                return
        self.manual_test_button.setEnabled(True)
        self.single_test_button.setEnabled(True)
        self.continuous_test_button.setEnabled(True)
        self.test_previous_button.setEnabled(True)
        self.test_next_button.setEnabled(True)

    def on_fitting_failed(self, failed_info: str, task: SSUTask):
        self.failed_task_ids.append(task.uuid)
        if self.__continuous_flag:
            self.on_continuous_test_clicked()
        self.manual_test_button.setEnabled(True)
        self.single_test_button.setEnabled(True)
        self.continuous_test_button.setEnabled(True)
        self.test_previous_button.setEnabled(True)
        self.test_next_button.setEnabled(True)
        self.show_error(failed_info)

    def do_test(self):
        self.manual_test_button.setEnabled(False)
        self.single_test_button.setEnabled(False)
        self.test_previous_button.setEnabled(False)
        self.test_next_button.setEnabled(False)
        if not self.__continuous_flag:
            self.continuous_test_button.setEnabled(False)
        task = self.generate_task()
        self.task_table[task.uuid] = task
        self.async_worker.execute_task(task)

    def on_manual_test_clicked(self):
        task = self.generate_task(query_ref=False)
        self.manual_panel.setup_task(task)
        self.manual_panel.show()

    def on_single_test_clicked(self):
        self.do_test()

    def on_continuous_test_clicked(self):
        if self.__continuous_flag:
            self.__continuous_flag = not self.__continuous_flag
            self.continuous_test_button.setText(self.tr("Continuous Test"))
        else:
            self.continuous_test_button.setText(self.tr("Cancel"))
            self.__continuous_flag = not self.__continuous_flag
            self.do_test()

    def on_test_previous_clicked(self):
        current = self.sample_index_input.value()
        if current == 1:
            return
        self.sample_index_input.setValue(current - 1)
        self.do_test()

    def on_test_next_clicked(self):
        current = self.sample_index_input.value()
        if current == self.dataset.n_samples:
            return
        self.sample_index_input.setValue(current + 1)
        self.do_test()
Esempio n. 29
0
class ElaWidget(ToolWidget):
    def __init__(self, image, parent=None):
        super(ElaWidget, self).__init__(parent)

        self.quality_spin = QSpinBox()
        self.quality_spin.setRange(0, 100)
        self.quality_spin.setSuffix(self.tr(' %'))
        self.quality_spin.setToolTip(self.tr('JPEG reference quality level'))
        self.scale_spin = QSpinBox()
        self.scale_spin.setRange(1, 100)
        self.scale_spin.setSuffix(' %')
        self.scale_spin.setToolTip(self.tr('Output multiplicative gain'))
        self.contrast_spin = QSpinBox()
        self.contrast_spin.setRange(0, 100)
        self.contrast_spin.setSuffix(' %')
        self.contrast_spin.setToolTip(self.tr('Output tonality compression'))
        self.equalize_check = QCheckBox(self.tr('Equalized'))
        self.equalize_check.setToolTip(self.tr('Apply histogram equalization'))
        self.gray_check = QCheckBox(self.tr('Grayscale'))
        self.gray_check.setToolTip(self.tr('Desaturated output'))
        default_button = QPushButton(self.tr('Default'))
        default_button.setToolTip(self.tr('Revert to default parameters'))

        params_layout = QHBoxLayout()
        params_layout.addWidget(QLabel(self.tr('Quality:')))
        params_layout.addWidget(self.quality_spin)
        params_layout.addWidget(QLabel(self.tr('Scale:')))
        params_layout.addWidget(self.scale_spin)
        params_layout.addWidget(QLabel(self.tr('Contrast:')))
        params_layout.addWidget(self.contrast_spin)
        params_layout.addWidget(self.equalize_check)
        params_layout.addWidget(self.gray_check)
        params_layout.addWidget(default_button)
        params_layout.addStretch()

        self.image = image
        self.original = image.astype(np.float32) / 255
        self.viewer = ImageViewer(self.image, self.image)
        self.default()

        self.quality_spin.valueChanged.connect(self.process)
        self.scale_spin.valueChanged.connect(self.process)
        self.contrast_spin.valueChanged.connect(self.process)
        self.equalize_check.stateChanged.connect(self.process)
        self.gray_check.stateChanged.connect(self.process)
        default_button.clicked.connect(self.default)

        main_layout = QVBoxLayout()
        main_layout.addLayout(params_layout)
        main_layout.addWidget(self.viewer)
        self.setLayout(main_layout)

    def process(self):
        start = time()
        quality = self.quality_spin.value()
        scale = self.scale_spin.value() / 20
        contrast = int(self.contrast_spin.value() / 100 * 128)
        equalize = self.equalize_check.isChecked()
        grayscale = self.gray_check.isChecked()
        self.scale_spin.setEnabled(not equalize)
        self.contrast_spin.setEnabled(not equalize)
        compressed = compress_img(self.image, quality).astype(np.float32) / 255
        difference = cv.absdiff(self.original, compressed)
        if equalize:
            ela = equalize_img((difference * 255).astype(np.uint8))
        else:
            ela = cv.convertScaleAbs(cv.sqrt(difference) * 255, None, scale)
            ela = cv.LUT(ela, create_lut(contrast, contrast))
        if grayscale:
            ela = desaturate(ela)
        self.viewer.update_processed(ela)
        self.info_message.emit(
            self.tr('Error Level Analysis = {}'.format(elapsed_time(start))))

    def default(self):
        self.blockSignals(True)
        self.equalize_check.setChecked(False)
        self.gray_check.setChecked(False)
        self.quality_spin.setValue(75)
        self.scale_spin.setValue(50)
        self.contrast_spin.setValue(20)
        self.process()
        self.blockSignals(False)
Esempio n. 30
0
class OscGui(QWidget):
    triggerEnable = 0
    ADCEnable = 0

    def __init__(self, device):
        QWidget.__init__(self)
        self.setWindowIcon(QIcon("icon/silabslogo.png"))

        self.device = device
        screen = QDesktopWidget()
        self.m_width = screen.width()
        self.m_height = screen.height()
        self.resize(self.m_width, self.m_height)
        self.showMaximized()

        self.setWindowTitle("Silabs")
        self.setObjectName("mainWindow")
        self.setStyleSheet("#mainWindow{background-color:rgb(54, 56, 60);}")

        self.layout = QtWidgets.QHBoxLayout()
        self.layout.setContentsMargins(self.m_width / 200, self.m_width / 200,
                                       self.m_width / 200, self.m_width / 20)
        self.layout.setSpacing(10)

        self.create_left_frame()
        self.create_right_frame()

        self.layout.setStretch(0, 3)
        self.layout.setStretch(1, 1)

        self.setLayout(self.layout)

        if self.device:
            logging.debug("device name:" + str(self.device))
            self.readThread = USBReadThread(self.device)
            self.readThread.updateWaveForm.connect(self.update_canvas)
            self.readThread.updateFrequency.connect(self.update_frequency)
            self.readThread.singleTrigger.connect(self.single_trigger_event)
            self.readThread.start()

            self.frequencyGet = Protocol.PREAMBLE.value \
                + Protocol.FREQUENCY_GET.value \
                + '\x00'  # '\xAA' + '\x41' + '\x00'
            self.setThread = USBWriteThread(self.device, self.frequencyGet)
            self.setThread.start()

    def create_left_frame(self):
        self.leftlayout = QtWidgets.QVBoxLayout()
        self.leftlayout.setContentsMargins(self.m_width / 200,
                                           self.m_width / 200,
                                           self.m_width / 200,
                                           self.m_width / 200)

        self.canvasFrame = CanvasFrame()
        # self.canvasFrame.setFrameStyle(QtWidgets.QFrame.StyledPanel | QtWidgets.QFrame.Plain)
        self.canvasFrame.setStyleSheet(
            "border-radius:10px;background-color:rgb(40, 38, 39);")
        self.leftlayout.addWidget(self.canvasFrame)

        self.navigationBarFrame = QtWidgets.QFrame()
        self.navigationBarFrame.setObjectName("NBF")
        self.navigationBarFrame.setStyleSheet(
            "#NBF{border-radius:10px;"
            "background-color:rgb(200, 200, 200);}")
        self.navigationBarLayout = QtWidgets.QVBoxLayout(
            self.navigationBarFrame)
        self.playBarLayout = QtWidgets.QHBoxLayout(self.navigationBarFrame)
        self.playBarLayout.setSpacing(self.m_width / 40)

        self.playBarLayout.addStretch(1)

        self.zoomInButton = QtWidgets.QPushButton()
        self.zoomInButton.setObjectName("zoomInButton")
        self.zoomInButton.setMaximumSize(self.m_width / 40, self.m_width / 40)
        self.zoomInButton.setMinimumSize(self.m_width / 40, self.m_width / 40)
        self.zoomInButton.setStyleSheet(
            "QPushButton{border-radius:25px;"
            "border-image:url(icon/ZoomIn.png);}"
            "QPushButton:hover{border-radius:25px;"
            "border-image:url(icon/ZoomIn2.png);"
            "background-colora:rgb(50, 50, 50,0);}")

        self.zoomInButton.clicked.connect(self.zoom_in_event)
        self.playBarLayout.addWidget(self.zoomInButton)

        self.zoomOutButton = QtWidgets.QPushButton()
        self.zoomOutButton.setObjectName("zoomOutButton")
        self.zoomOutButton.setMaximumSize(self.m_width / 40, self.m_width / 40)
        self.zoomOutButton.setMinimumSize(self.m_width / 40, self.m_width / 40)
        self.zoomOutButton.setIcon(QIcon("icon/ZoomOut.png"))
        self.zoomOutButton.setIconSize(
            QSize(self.m_width / 40, self.m_width / 40))
        self.zoomOutButton.setStyleSheet(
            "QPushButton{border-radius:%dpx;}"
            "QPushButton:hover{border:1 solid red;"
            "border-radius:%dpx;"
            "background-color:rgb(250, 100, 100);}" %
            (self.m_width / 80, self.m_width / 80))
        self.zoomOutButton.clicked.connect(self.zoom_out_event)
        self.playBarLayout.addWidget(self.zoomOutButton)

        self.playButton = QtWidgets.QPushButton()
        self.playButton.setObjectName("playButton")
        self.playButton.setFixedSize(self.m_width / 20, self.m_width / 20)
        # self.playButton.setStyleSheet("border-radius:%dpx;" % self.m_width/40)
        self.playButton.setStyleSheet("QPushButton{border:none;"
                                      "border-radius:%dpx;"
                                      "background-color:"
                                      "rgb(200, 100, 100);}"
                                      "QPushButton:hover{border:0;"
                                      "border-radius:%dpx;"
                                      "background-color:rgb(250, 100, 100);}" %
                                      (self.m_width / 40, self.m_width / 40))
        self.playButton.clicked.connect(self.play_button_event)
        self.playBarLayout.addWidget(self.playButton)

        self.triggerLayout = QtWidgets.QHBoxLayout(self.navigationBarFrame)
        self.triggerLayout.setContentsMargins(0, 0, 0, 0)
        self.triggerLayout.setSpacing(1)

        self.triggerEnable = 0
        self.triggerButton = QtWidgets.QPushButton(self.navigationBarFrame)
        # self.triggerButton.setObjectName("triggerButton")
        self.triggerButton.setFixedSize(self.m_width / 12, self.m_height / 20)
        self.triggerButton.setFont(QFont("New Time Roman", 10))
        self.triggerButton.setText("Single Trigger")
        self.triggerButton.setStyleSheet(
            "QPushButton{border-top-left-radius:5px;"
            "border-bottom-left-radius: 5px;"
            "background-color:rgba(100, 100, 100,255);"
            "color:rgb(200, 200, 200);}"
            "QPushButton:hover{color: rgb(100, 200, 100);font-weight:bold}")
        self.triggerButton.clicked.connect(self.trigger_event)
        self.triggerLayout.addWidget(self.triggerButton)

        self.triggerValue = 0
        self.triggerSpinBox = QSpinBox(self.navigationBarFrame)
        self.triggerSpinBox.setFixedSize(self.m_width / 10, self.m_height / 20)
        self.triggerSpinBox.setMaximum(3300)
        self.triggerSpinBox.setMinimum(1)
        self.triggerSpinBox.setFont(QFont("New Time Roman", 10))
        self.triggerSpinBox.setStyleSheet(
            "QSpinBox{border-top-right-radius:5px;"
            "border-bottom-left-right: 5px;"
            "background-color:rgb(100, 100, 100);"
            "color:rgb(200, 200, 200);}"
            "QSpinBox:drop{subcontrol-origin: padding;"
            "subcontrol-position: top right;"
            "width: 50px;border-left-style:solid;"
            "border-top-right-radius: 3px;"
            "border-bottom-right-radius: 3px;"
            "border-left: 2px solid gray;"
            "background-color: rgba(100, 25, 100, 0);}")
        self.triggerSpinBox.setMinimumWidth(30)
        self.triggerLayout.addWidget(self.triggerSpinBox)
        self.playBarLayout.addLayout(self.triggerLayout)

        self.playBarLayout.addStretch(1)
        self.navigationBarLayout.addLayout(self.playBarLayout)

        self.navigationBarLine = QtWidgets.QFrame(self.navigationBarFrame)
        self.navigationBarLine.setAutoFillBackground(True)
        self.navigationBarLine.setFixedHeight(1)
        self.navigationBarLine.setStyleSheet(
            "background-color:rgb(150, 150, 150);")
        self.navigationBarLayout.addWidget(self.navigationBarLine)
        # self.navigationBarLayout.addStretch(1)
        self.leftlayout.addWidget(self.navigationBarFrame)
        self.leftlayout.setStretch(0, 5)
        self.leftlayout.setStretch(1, 1)
        self.leftlayout.setStretch(2, 1)
        self.leftlayout.setSpacing(self.m_width / 40)
        self.layout.addLayout(self.leftlayout)

    def create_right_frame(self):

        self.rightlayout = QtWidgets.QVBoxLayout()
        self.rightlayout.setContentsMargins(self.m_width / 200,
                                            self.m_width / 200,
                                            self.m_width / 200,
                                            self.m_width / 200)

        self.dialogFrame = QtWidgets.QFrame()
        self.dialogFrame.setObjectName("dialogFrame")
        # self.dialogFrame.setAutoFillBackground(True)
        # self.dialogFrame.setStyleSheet("#dialogFrame{border-radius:10px;"
        #                                "background-color:rgb(255, 100, 100);}")
        self.dialogFrame.setStyleSheet("#dialogFrame{border-radius:10px;"
                                       "background-color:rgb(10, 10, 10);}")
        self.dialoglayout = QtWidgets.QVBoxLayout(self.dialogFrame)
        self.dialoglayout.setContentsMargins(0, self.m_width / 40, 0,
                                             self.m_width /
                                             40)  # left, top, right, bottom
        self.dialoglayout.setSpacing(self.m_width / 40)
        self.dialoglayout.addStretch(2)

        self.ledLayout = QtWidgets.QHBoxLayout(self.dialogFrame)

        self.ledLayout.addStretch(1)

        self.redLedState = 0
        self.redLedSwitch = QtWidgets.QPushButton(self.dialogFrame)
        self.redLedSwitch.setObjectName("redLedSwitch")
        self.redLedSwitch.setIcon(QIcon("icon/switchOFF.png"))
        self.redLedSwitch.setIconSize(
            QSize(self.m_width / 40, self.m_width / 40 / 1.75))
        self.redLedSwitch.setFixedSize(self.m_width / 40,
                                       self.m_width / 40 / 1.75)
        self.redLedSwitch.setStyleSheet("#redLedSwitch{border:none;}")
        self.redLedSwitch.clicked.connect(self.red_led_switch_event)
        self.ledLayout.addWidget(self.redLedSwitch)

        self.ledLayout.addStretch(1)

        self.greenLedState = 0
        self.greenLedSwitch = QtWidgets.QPushButton(self.dialogFrame)
        self.greenLedSwitch.setObjectName("greenLedSwitch")
        self.greenLedSwitch.setIcon(QIcon("icon/switchOFF.png"))
        self.greenLedSwitch.setIconSize(
            QSize(self.m_width / 40, self.m_width / 40 / 1.75))
        self.greenLedSwitch.setFixedSize(self.m_width / 40,
                                         self.m_width / 40 / 1.75)
        self.greenLedSwitch.setStyleSheet("#greenLedSwitch{border:none;}")
        self.greenLedSwitch.clicked.connect(self.green_led_switch_event)
        self.ledLayout.addWidget(self.greenLedSwitch)

        self.ledLayout.addStretch(1)

        self.blueLedState = 0
        self.blueLedSwitch = QtWidgets.QPushButton(self.dialogFrame)
        self.blueLedSwitch.setObjectName("blueLedSwitch")
        self.blueLedSwitch.setIcon(QIcon("icon/switchOFF.png"))
        self.blueLedSwitch.setIconSize(
            QSize(self.m_width / 40, self.m_width / 40 / 1.75))
        self.blueLedSwitch.setFixedSize(self.m_width / 40,
                                        self.m_width / 40 / 1.75)
        self.blueLedSwitch.setStyleSheet("#blueLedSwitch{border:none;}")
        self.blueLedSwitch.clicked.connect(self.blue_led_switch_event)
        self.ledLayout.addWidget(self.blueLedSwitch)

        self.ledLayout.addStretch(1)
        self.dialoglayout.addLayout(self.ledLayout)

        self.dialoglayout.addStretch(1)

        self.dialogLine = QtWidgets.QFrame(self.dialogFrame)
        self.dialogLine.setAutoFillBackground(True)
        self.dialogLine.setFixedHeight(1)
        self.dialogLine.setStyleSheet("background-color:rgb(50, 50, 50);")
        self.dialoglayout.addWidget(self.dialogLine)

        self.channelLayout = QtWidgets.QHBoxLayout(self.dialogFrame)
        self.channelLayout.setSpacing(0)
        self.channelLayout.setContentsMargins(self.m_width / 100, 0,
                                              self.m_width / 100, 0)
        # self.channelLayout.addStretch(1)

        self.channel1Enable = 0
        self.channel1Button = QPushButton(self.dialogFrame)
        self.channel1Button.setFixedHeight(self.m_width / 40)
        self.channel1Button.setStyleSheet(
            "QPushButton{border:1px solid rgb(200,200,200);"
            "border-top-left-radius:5px;"
            "border-bottom-left-radius: 5px;"
            "background-color:rgba(100, 100, 100,0);"
            "color:rgb(200, 200, 200);"
            "padding: 1px 20px;}"
            "QPushButton:hover{font-weight:bold;}")
        self.channel1Button.setFont(QFont("New Time Roman", 10))
        self.channel1Button.setText("Channel_1")
        self.channel1Button.clicked.connect(self.channel1_button_event)
        self.channelLayout.addWidget(self.channel1Button)

        self.channel2Enable = 0
        self.channel2Button = QPushButton(self.dialogFrame)
        self.channel2Button.setFixedHeight(self.m_width / 40)
        self.channel2Button.setStyleSheet(
            "QPushButton{border:1px solid rgb(200,200,200);"
            "border-top-right-radius: 5px;"
            "border-bottom-right-radius:5px;"
            "background-color:rgba(100, 100, 100,0);"
            "color:rgb(200, 200, 200);"
            "padding: 1px 20px;}"
            "QPushButton:hover{font-weight:bold;}")
        self.channel2Button.setFont(QFont("New Time Roman", 10))
        self.channel2Button.setText("Channel_2")
        self.channel2Button.clicked.connect(self.channel2_button_event)
        self.channelLayout.addWidget(self.channel2Button)
        # self.channelLayout.addStretch(1)

        self.dialoglayout.addLayout(self.channelLayout)

        self.dialogLine2 = QtWidgets.QFrame(self.dialogFrame)
        self.dialogLine2.setAutoFillBackground(True)
        self.dialogLine2.setFixedHeight(1)
        self.dialogLine2.setStyleSheet("background-color:rgb(50, 50, 50);")
        self.dialoglayout.addWidget(self.dialogLine2)

        self.configutatorLayout = QtWidgets.QVBoxLayout(self.dialogFrame)
        self.configutatorLayout.setContentsMargins(20, 0, 20, 0)
        self.configutatorLayout.setSpacing(self.m_width / 100)

        self.frenquencyComboBox = QtWidgets.QComboBox()
        self.frenquencyComboBox.setObjectName("frenquencyComboBox")
        self.frenquencyComboBox.setFixedHeight(self.m_width / 40)
        self.frenquencyComboBox.setFont(QFont("New Time Roman", 10))
        self.frenquencyComboBox.setStyleSheet(
            "QComboBox{border-radius:5px;"
            "background-color:rgb(200, 200, 200);"
            "color:rgb(0, 0, 0);"
            "padding: 1px 20px;}"
            "QComboBox:drop-down{subcontrol-origin: padding;"
            "subcontrol-position: top right;"
            "width: 50px;border-left-style:solid;"
            "border-top-right-radius: 3px;"
            "border-bottom-right-radius: 3px;"
            "border-left: 2px solid gray;"
            "background-color: rgba(100, 100, 100, 0);}"
            "QComboBox:down-arrow{border-image:url(icon/arrow-1.png);}")
        self.frenquencyComboBox.addItem("4Hz")
        self.frenquencyComboBox.addItem("10Hz")
        self.frenquencyComboBox.addItem("100Hz")
        self.frenquencyComboBox.addItem("1000Hz")
        self.frenquencyComboBox.setCurrentText("1000Hz")
        self.frenquencyComboBox.setFont(QFont("New Time Roman", 10))

        self.configutatorLayout.addWidget(self.frenquencyComboBox)

        self.setButton = QPushButton(self.dialogFrame)
        self.setButton.setObjectName("setButton")
        self.setButton.setFixedHeight(self.m_width / 40)
        self.setButton.setStyleSheet(
            "QPushButton{border-radius:%dpx;"
            "background-color:rgb(150, 255, 150);"
            "color:rgb(0, 0, 0);"
            "text-align: center center;}"
            "QPushButton:hover{background-color:"
            "rgb(100, 255, 100);color:rgb(255, 100, 100);"
            "font-size:20px}" % (self.m_width / 80))
        self.setButton.setFont(QFont("New Time Roman", 12, QFont.Bold))
        self.setButton.setText("set")
        self.setButton.clicked.connect(self.set_button_event)
        self.setButton.setEnabled(True)
        self.configutatorLayout.addWidget(self.setButton)

        self.dialoglayout.addLayout(self.configutatorLayout)
        self.dialoglayout.addStretch(1)

        self.rightlayout.addWidget(self.dialogFrame)

        self.stateFrame = QtWidgets.QFrame()
        self.stateFrame.setObjectName("stateFrame")
        # self.dialogFrame.setAutoFillBackground(True)
        self.stateFrame.setStyleSheet(
            "QFrame{border:2px solid rgb(200, 200, 200);"
            "border-radius:10px;"
            "background-color:rgb(200, 200, 200);}")
        self.statelayout = QtWidgets.QGridLayout(self.stateFrame)
        self.statelayout.setContentsMargins(self.m_width / 40,
                                            self.m_width / 40,
                                            self.m_width / 40,
                                            self.m_width / 40)
        self.enableLabelKey = QLabel(self.stateFrame)
        self.enableLabelKey.setText("state:")
        self.enableLabelKey.setFont(QFont("New Time Roman", 10, QFont.Bold))
        self.statelayout.addWidget(self.enableLabelKey, 0, 0)
        self.enableLabelValue = QLabel(self.stateFrame)
        self.enableLabelValue.setText("Stop")
        self.enableLabelValue.setFont(QFont("New Time Roman", 10, QFont.Bold))
        self.statelayout.addWidget(self.enableLabelValue, 0, 1)

        self.frequencyLabelKey = QLabel(self.stateFrame)
        self.frequencyLabelKey.setText("frequency:")
        self.frequencyLabelKey.setFont(QFont("New Time Roman", 10, QFont.Bold))
        self.statelayout.addWidget(self.frequencyLabelKey, 1, 0)
        self.frequencyLabelValue = QLabel(self.stateFrame)
        self.frequencyLabelValue.setText(
            str(self.canvasFrame.frequency) + "Hz")
        self.frequencyLabelValue.setFont(
            QFont("New Time Roman", 10, QFont.Bold))
        self.statelayout.addWidget(self.frequencyLabelValue, 1, 1)

        self.bitModeLabelKey = QLabel(self.stateFrame)
        self.bitModeLabelKey.setText("BitMode:")
        self.bitModeLabelKey.setFont(QFont("New Time Roman", 10, QFont.Bold))
        self.statelayout.addWidget(self.bitModeLabelKey, 2, 0)
        self.bitModeLabelValue = QLabel(self.stateFrame)
        self.bitModeLabelValue.setText("8 bit")
        self.bitModeLabelValue.setFont(QFont("New Time Roman", 10, QFont.Bold))
        self.statelayout.addWidget(self.bitModeLabelValue, 2, 1)

        self.rightlayout.addWidget(self.stateFrame)

        self.rightlayout.addStretch(1)

        self.layout.addLayout(self.rightlayout)

    def trigger_event(self):
        if self.device is None:
            logging.error("no device!!!")
            return
        if self.triggerEnable:
            self.triggerButton.setStyleSheet(
                "QPushButton{border-top-left-radius:5px;"
                "border-bottom-left-radius: 5px;"
                "background-color:rgba(100, 100, 100,255);}"
                "QPushButton:hover{color: rgb(100, 200, 100);font-weight:bold}"
            )
            self.triggerEnable = 0
            self.triggerValue = 0
            self.readThread.triggerEnable = 0
            self.readThread.triggerValue = 0
            self.triggerSpinBox.setEnabled(True)
            self.triggerSpinBox.setStyleSheet(
                "QSpinBox{border-top-right-radius:5px;"
                "border-bottom-left-right: 5px;"
                "background-color:rgb(100, 100, 100);"
                "color:rgb(200, 200, 200);}")

        else:
            self.triggerButton.setStyleSheet(
                "QPushButton{border:1px solid rgb(200,200,200);"
                "border-top-left-radius:5px;"
                "border-bottom-left-radius: 5px;"
                "background-color:rgba(100, 200, 100);}"
                "QPushButton:hover{color: rgb(100, 100, 100);font-weight:bold}"
            )
            self.triggerEnable = 1
            self.triggerValue = self.triggerSpinBox.value()
            self.readThread.triggerEnable = 1
            self.readThread.triggerValue = self.triggerValue
            self.triggerSpinBox.setEnabled(False)
            self.triggerSpinBox.setStyleSheet(
                "QSpinBox{border-top-right-radius:5px;"
                "border-bottom-left-right: 5px;"
                "background-color:rgb(150, 150, 150);}")
        logging.debug("triggerButtonEvent:" +
                      str(self.readThread.triggerEnable))

    def zoom_in_event(self):
        if self.canvasFrame.scaleRatio == 1:
            self.canvasFrame.scaleRatio = 1
        else:
            self.canvasFrame.scaleRatio = self.canvasFrame.scaleRatio - 1
        self.canvasFrame.update()
        logging.debug("zoom_in_event, scaleRatio= " +
                      str(self.canvasFrame.scaleRatio))

    def zoom_out_event(self):
        if self.canvasFrame.scaleRatio > 5:
            self.canvasFrame.scaleRatio = 6
        else:
            self.canvasFrame.scaleRatio = self.canvasFrame.scaleRatio + 1
        self.canvasFrame.update()
        logging.debug("zoom_out_event, scaleRatio= " +
                      str(self.canvasFrame.scaleRatio))

    def play_button_event(self):
        logging.debug("playButtonEvent")
        if self.device is None:
            logging.error("no device!!!")
            return

        if self.ADCEnable:
            self.channel1Button.setEnabled(True)
            self.channel2Button.setEnabled(True)
            self.playButton.setStyleSheet(
                "QPushButton{border-radius:%dpx;"
                "background-color:rgb(200, 100, 100);}"
                "QPushButton:hover{border:0;"
                "border-radius:%dpx;"
                "background-color:rgb(250, 100, 100);}" %
                (self.m_width / 40, self.m_width / 40))
            self.command = Protocol.PREAMBLE.value \
                + Protocol.ENABLE_ADC.value \
                + '\x01' \
                + Protocol.DISABLE.value  # '\xAA'+'\xF1'+'\x01'+'\x00'
            self.playthread = USBWriteThread(self.device, self.command)
            self.playthread.start()
            self.ADCEnable = 0
            self.enableLabelValue.setText("Stop")
            self.setButton.setStyleSheet(
                "QPushButton{border-radius:%dpx;"
                "background-color:rgb(150, 255, 150);"
                "color:rgb(0, 0, 0);"
                "text-align: center center;}"
                "QPushButton:hover{background-color:rgb(100, 255, 100);"
                "color:rgb(255, 100, 100);"
                "font-size:20px;}" % (self.m_width / 80))
            self.setButton.setEnabled(True)

            self.canvasFrame.dragEnable = True
        else:
            if self.channel1Enable == 0 and self.channel2Enable == 0:
                return

            if self.canvasFrame.frequency == 1000:
                self.freq = Protocol.FREQUENCY_1000HZ.value
            elif self.canvasFrame.frequency == 100:
                self.freq = Protocol.FREQUENCY_100HZ.value
            elif self.canvasFrame.frequency == 10:
                self.freq = Protocol.FREQUENCY_10HZ.value
            elif self.canvasFrame.frequency == 4:
                self.freq = Protocol.FREQUENCY_4HZ.value
            else:
                self.freq = Protocol.FREQUENCY_1000HZ.value

            self.frequencyCommand = Protocol.PREAMBLE.value \
                + Protocol.FREQUENCY_SET.value \
                + '\x01' \
                + self.freq  # '\xAA' + '\x43' + '\x01' + '\x03'
            self.frequencyThread = USBWriteThread(self.device,
                                                  self.frequencyCommand)
            self.frequencyThread.start()

            self.channel1Button.setEnabled(False)
            self.channel2Button.setEnabled(False)
            self.playButton.setStyleSheet(
                "QPushButton{border-radius:%dpx;"
                "background-color:rgb(100, 200, 100);}"
                "QPushButton:hover{border:0;"
                "border-radius:%dpx;"
                "background-color:rgb(100, 250, 100);}" %
                (self.m_width / 40, self.m_width / 40))
            self.command = Protocol.PREAMBLE.value \
                + Protocol.ENABLE_ADC.value \
                + '\x01' \
                + Protocol.ENABLE.value  # '\xAA'+'\xF1'+'\x01'+'\x01'
            self.playthread = USBWriteThread(self.device, self.command)
            self.playthread.start()
            self.ADCEnable = 1
            self.enableLabelValue.setText("Runing")

            self.setButton.setStyleSheet("QPushButton{border-radius:%dpx;"
                                         "background-color:rgb(150, 150, 150);"
                                         "color:rgb(0, 0, 0);"
                                         "text-align: center center;}" %
                                         (self.m_width / 80))
            self.setButton.setEnabled(False)
            self.canvasFrame.dragEnable = False
            self.canvasFrame.dragBias = 0
            self.canvasFrame.dragBias_t = 0

    def red_led_switch_event(self):
        if self.device is None:
            logging.error("no device!!!")
            return
        logging.debug("redled is pressed")
        if self.redLedState:
            self.redLedSwitch.setIcon(QIcon("icon/switchOFF.png"))
            self.redLedState = 0
            self.ledCommand = Protocol.PREAMBLE.value \
                + Protocol.LED_SET.value \
                + '\x02' \
                + Protocol.LED_RED.value \
                + Protocol.LED_OFF.value  # '\xAA' + '\x13' + '\x02' + '\x01' + '\x00'
        else:
            self.redLedSwitch.setIcon(QIcon("icon/switchRedOn.png"))
            self.redLedState = 1
            self.ledCommand = Protocol.PREAMBLE.value \
                + Protocol.LED_SET.value \
                + '\x02' + Protocol.LED_RED.value \
                + Protocol.LED_ON.value  # '\xAA' + '\x13' + '\x02' + '\x01' + '\x01'

        self.ledThread = USBWriteThread(self.device, self.ledCommand)
        self.ledThread.start()

    def green_led_switch_event(self):
        if self.device is None:
            logging.error("no device!!!")
            return
        logging.debug("greenled is pressed")
        if self.greenLedState:
            self.greenLedSwitch.setIcon(QIcon("icon/switchOFF.png"))
            self.greenLedState = 0
            self.ledCommand = Protocol.PREAMBLE.value \
                + Protocol.LED_SET.value \
                + '\x02' \
                + Protocol.LED_GREEN.value \
                + Protocol.LED_OFF.value  # '\xAA' + '\x13' + '\x02' + '\x02' + '\x00'

        else:
            self.greenLedSwitch.setIcon(QIcon("icon/switchGreenOn.png"))
            self.greenLedState = 1
            self.ledCommand = Protocol.PREAMBLE.value \
                + Protocol.LED_SET.value \
                + '\x02' \
                + Protocol.LED_GREEN.value \
                + Protocol.LED_ON.value  # '\xAA' + '\x13' + '\x02' + '\x02' + '\x01'
        self.ledThread = USBWriteThread(self.device, self.ledCommand)
        self.ledThread.start()

    def blue_led_switch_event(self):
        if self.device is None:
            logging.error("no device!!!")
            return
        logging.debug("blueled is pressed")
        if self.blueLedState:
            self.blueLedSwitch.setIcon(QIcon("icon/switchOFF.png"))
            self.blueLedState = 0
            self.ledCommand = Protocol.PREAMBLE.value \
                + Protocol.LED_SET.value \
                + '\x02' \
                + Protocol.LED_BLUE.value \
                + Protocol.LED_OFF.value  # '\xAA' + '\x13' + '\x02' + '\x03' + '\x00'
        else:
            self.blueLedSwitch.setIcon(QIcon("icon/switchBlueOn.png"))
            self.blueLedState = 1
            self.ledCommand = Protocol.PREAMBLE.value \
                + Protocol.LED_SET.value \
                + '\x02' \
                + Protocol.LED_BLUE.value \
                + Protocol.LED_ON.value  # '\xAA' + '\x13' + '\x02' + '\x03' + '\x01'
        self.ledThread = USBWriteThread(self.device, self.ledCommand)
        self.ledThread.start()

    def channel1_button_event(self):
        if self.device is None:
            logging.error("no device!!!")
            return
        if self.channel1Enable:
            del self.canvasFrame.Channel1List[:]
            self.command = Protocol.PREAMBLE.value \
                + Protocol.ENABLE_CHANNEL.value \
                + '\x02' \
                + Protocol.CHANNEL1.value \
                + Protocol.DISABLE.value  # '\xAA'+'\xF1'+'\x01'+'\x00'
            self.channel1thread = USBWriteThread(self.device, self.command)
            self.channel1thread.start()
            self.channel1Enable = 0
            self.canvasFrame.channel1Enable = 0

            self.channel1Button.setStyleSheet(
                "QPushButton{border:1px solid rgb(200,200,200);"
                "border-top-left-radius:5px;"
                "border-bottom-left-radius: 5px;"
                "background-color:rgba(100, 100, 100,0);"
                "color:rgb(200, 200, 200);"
                "padding: 1px 20px;}"
                "QPushButton:hover{font-weight:bold;}")

            logging.debug("channel1 disable")

        else:
            self.command = Protocol.PREAMBLE.value \
                           + Protocol.ENABLE_CHANNEL.value \
                           + '\x02' \
                           + Protocol.CHANNEL1.value \
                           + Protocol.ENABLE.value  # '\xAA'+'\xF1'+'\x01'+'\x00'
            self.channel1thread = USBWriteThread(self.device, self.command)
            self.channel1thread.start()
            self.channel1Enable = 1
            self.canvasFrame.channel1Enable = 1
            self.channel1Button.setStyleSheet(
                "QPushButton{border:1px solid rgb(200,200,200);"
                "border-top-left-radius:5px;"
                "border-bottom-left-radius: 5px;"
                "background-color:rgba(200, 100, 100,255);"
                "color:rgb(200, 200, 200);"
                "padding: 1px 20px;}"
                "QPushButton:hover{font-weight:bold;}")

            logging.debug("channel1 enable")

    def channel2_button_event(self):
        if self.device is None:
            logging.error("no device!!!")
            return
        if self.channel2Enable:
            del self.canvasFrame.Channel2List[:]
            self.command2 = Protocol.PREAMBLE.value \
                + Protocol.ENABLE_CHANNEL.value \
                + '\x02' \
                + Protocol.CHANNEL2.value \
                + Protocol.DISABLE.value  # '\xAA'+'\xF1'+'\x01'+'\x00'
            self.channel2thread = USBWriteThread(self.device, self.command2)
            self.channel2thread.start()
            self.channel2Enable = 0
            self.canvasFrame.channel2Enable = 0
            self.channel2Button.setStyleSheet(
                "QPushButton{border:1px solid rgb(200,200,200);"
                "border-top-right-radius:5px;"
                "border-bottom-right-radius: 5px;"
                "background-color:rgba(100, 100, 100,0);"
                "color:rgb(200, 200, 200);"
                "padding: 1px 20px;}"
                "QPushButton:hover{font-weight:bold;}")
            logging.debug("channel2 disable")

        else:
            self.command2 = Protocol.PREAMBLE.value \
                           + Protocol.ENABLE_CHANNEL.value \
                           + '\x02' \
                           + Protocol.CHANNEL2.value \
                           + Protocol.ENABLE.value  # '\xAA'+'\xF1'+'\x01'+'\x00'
            self.channel2thread = USBWriteThread(self.device, self.command2)
            self.channel2thread.start()
            self.channel2Enable = 1
            self.canvasFrame.channel2Enable = 1
            self.channel2Button.setStyleSheet(
                "QPushButton{border:1px solid rgb(200,200,200);"
                "border-top-right-radius:5px;"
                "border-bottom-right-radius: 5px;"
                "background-color:rgba(0, 200, 255,255);"
                "color:rgb(200, 200, 200);"
                "padding: 1px 20px;}"
                "QPushButton:hover{font-weight:bold;}")

            logging.debug("channel2 enable")

    def set_button_event(self):
        if self.device is None:
            logging.error("no device!!!")
            return
        logging.debug("setButton is pressed" +
                      str(self.frenquencyComboBox.currentIndex()) + '+' +
                      self.frenquencyComboBox.currentText())

        if self.frenquencyComboBox.currentText() == '1000Hz':
            self.canvasFrame.frequency = 1000
            self.readThread.frequency = 1000
        elif self.frenquencyComboBox.currentText() == '100Hz':
            self.canvasFrame.frequency = 100
            self.readThread.frequency = 100

        elif self.frenquencyComboBox.currentText() == '10Hz':
            self.canvasFrame.frequency = 10
            self.readThread.frequency = 10

        elif self.frenquencyComboBox.currentText() == '4Hz':
            self.canvasFrame.frequency = 4
            self.readThread.frequency = 4

        else:
            logging.warning("error frequency value:" +
                            self.frenquencyComboBox.currentText())

        self.frequencyLabelValue.setText(self.frenquencyComboBox.currentText())

    def update_canvas(self, state):
        logging.debug("update_canvas:" + state)
        self.canvasFrame.update()

    def update_frequency(self, frequency):
        logging.debug("update_frequency")
        if self.readThread:
            self.frequencyLabelValue.setText(str(frequency) + "(HZ)")
            if frequency == 0:
                logging.warning("receive wrong frequency:0")
            else:
                self.canvasFrame.frequency = frequency

    def single_trigger_event(self, state):
        logging.debug("single_trigger_event:" + state)
        if self.ADCEnable == 0:
            return
        self.command = Protocol.PREAMBLE.value \
            + Protocol.ENABLE_ADC.value \
            + '\x01' \
            + Protocol.DISABLE.value  # '\xAA' + '\xF2' + '\x01' + '\x00'
        self.playThread = USBWriteThread(self.device, self.command)
        self.playThread.start()
        self.ADCEnable = 0
        self.enableLabelValue.setText("Stop")
        self.playButton.setStyleSheet("QPushButton{border:none;"
                                      "border-radius:%dpx;"
                                      "background-color:rgb(200, 100, 100);}"
                                      "QPushButton:hover{border:0;"
                                      "border-radius:%dpx;"
                                      "background-color:rgb(250, 100, 100);}" %
                                      (self.m_width / 40, self.m_width / 40))
        self.setButton.setStyleSheet(
            "QPushButton{border-radius:%dpx;"
            "background-color:rgb(150, 255, 150);"
            "color:rgb(0, 0, 0);"
            "text-align: center center;}"
            "QPushButton:hover{background-color:rgb(100, 255, 100);"
            "color:rgb(255, 100, 100);"
            "font-size:20px}" % (self.m_width / 80))
        self.setButton.setEnabled(True)
        self.channel1Button.setEnabled(True)
        self.channel2Button.setEnabled(True)
        logging.debug("trigger!!! sample stop")

    def closeEvent(self, *args, **kwargs):
        logging.debug("this closeEvent -------------")
        if self.device:
            self.device.close()
            self.readThread.terminate()
            self.readThread.wait()

    def __del__(self):
        logging.debug("this del -------------")