Exemple #1
0
 def testFloatSignal(self):
     foo1 = QDoubleSpinBox()
     foo2 = QDoubleSpinBox()
     foo1.valueChanged[float].connect(foo2.setValue)
     foo2.valueChanged[float].connect(foo1.setValue)
     foo1.setValue(0.42)
     self.assertEqual(foo1.value(), foo2.value())
    def initUI(self):

        QToolTip.setFont(QFont('SansSerif', 12))
        
        Title = QLabel('Выберите параметры обучения нейросети')
        Title.setToolTip('Для корректной работы функций обучения и оптимизации \n'
                         'в каталоге с программой должны находится подкаталоги \n'
                         'train, val, test. В каждом из этих каталогов должно \n'
                         'быть столько подкаталогов с изображениями, сколько \n'
                         'необходимо распознавать классов')
        Title1 = QLabel('Выберите параметры исследования изображения')
        Title1.setToolTip('Для корректной работы функции классификации и локализации \n'
                          'изображения для исследования и модель нейросети должны \n'
                          'находиться в одном каталоге с программой, формат изображения \n'
                          '.jpg, формат модели нейросети .h5, указывать формат в полях не нужно')
        TitleEp = QLabel('Эпохи:')
        TitleEp.setToolTip('Эпоха — один «проход» данных через нейросеть. \n'
                           'Изменение этого параметра позволяет избежать \n'
                           'недообученности или переобученности нейросети')
        TitleBa = QLabel('Размер мини-выборки:')
        TitleBa.setToolTip('Количество изображений загружаемых в нейросеть '
                           'за раз')
        TitleTr = QLabel('Количество изображений для обучения:')
        TitleTr.setToolTip('Количество изображений во всех подкаталогах '
                           'каталога train')
        TitleVa = QLabel('Количество изображений для проверки:')
        TitleVa.setToolTip('Количество изображений во всех подкаталогах '
                           'каталога val')
        TitleTe = QLabel('Количество изображений для тестирования:')
        TitleTe.setToolTip('Количество изображений во всех подкаталогах '
                           'каталога test')
        TitleSc = QLabel('Масштабирование пирамиды изображений:')
        TitleSc.setToolTip('Коэффициент масштабирования изображения')
        TitleSs = QLabel('Шаг скользящего окна:')
        TitleSs.setToolTip('Расстояние в пикселях, на которое смещается \n'
                           'окно классификатора по изображению за одну итерацию')
        TitleNi = QLabel('Имя изображения для исследования:')
        TitleNi.setToolTip('Наименование изображения без расширения. \n'
                           'Изображение должно иметь формат jpg и \n'
                           'находится в одном каталоге с программой, иначе \n'
                           'необходимо указывать полный путь до изображения')
        TitleNm = QLabel('Имя модели нейросети:')
        TitleNm.setToolTip('Наименование модели нейросети без расширения. \n'
                           'Модель должна иметь формат h5 и находится \n'
                           'в одном каталоге с программой, иначе необходимо \n'
                           'указывать полный путь до модели нейросети')
        TitleCl = QLabel('Количество классов:')
        
        self.InputEpochs = QSpinBox(self)
        self.InputEpochs.setRange(5,50)
        self.InputEpochs.setValue(10)

        self.InputBatch = QSpinBox(self)
        self.InputBatch.setRange(5,100)
        self.InputBatch.setValue(15)

        self.InputTrain = QSpinBox(self)
        self.InputTrain.setRange(100,100000)
        self.InputTrain.setValue(1050)

        self.InputValidation = QSpinBox(self)
        self.InputValidation.setRange(100,100000)
        self.InputValidation.setValue(225)

        self.InputTest = QSpinBox(self)
        self.InputTest.setRange(100,100000)
        self.InputTest.setValue(225)

        self.InputScale = QDoubleSpinBox(self)
        self.InputScale.setRange(1.1,5)
        self.InputScale.setValue(1.5)

        self.InputStep = QSpinBox(self)
        self.InputStep.setRange(1,150)
        self.InputStep.setValue(30)

        self.InputClass = QSpinBox(self)
        self.InputClass.setRange(3,20)
        self.InputClass.setValue(3)
        
        self.ImageName = QLineEdit("ImageName", self)
        self.ImageName.setMaxLength(20)

        self.ModelName = QLineEdit("TestModel", self)
        self.ModelName.setMaxLength(20)
        
        btn = QPushButton('Обучить нейросеть', self)
        btn.setToolTip('В результате обучения модель нейросети '
                       'будет сохранена в каталоге с программой')
        btn.resize(btn.sizeHint())
        btn.clicked.connect(self.buttonClicked)
        
        btn1 = QPushButton('Оптимизировать нейросеть', self)
        btn1.setToolTip('В результате оптимизации 3 лучшие модели '
                        'будут сохранены в каталоге с программой')
        btn1.resize(btn1.sizeHint())
        btn1.clicked.connect(self.buttonClicked1)
        
        btn2 = QPushButton('Поиск и распознавание', self)
        btn2.resize(btn2.sizeHint())
        btn2.clicked.connect(self.buttonClicked2)

        grid = QGridLayout(self)

        grid.setSpacing(10)

        grid.addWidget(Title, 1, 0, 1, 4)
        grid.addWidget(TitleEp, 2, 0)
        grid.addWidget(TitleBa, 3, 0)
        grid.addWidget(TitleCl, 4, 0)
        grid.addWidget(self.InputEpochs, 2, 1)
        grid.addWidget(self.InputBatch, 3, 1)
        grid.addWidget(self.InputClass, 4, 1)
        grid.addWidget(TitleTr, 2, 2)
        grid.addWidget(TitleVa, 3, 2)
        grid.addWidget(TitleTe, 4, 2)
        grid.addWidget(self.InputTrain, 2, 3)
        grid.addWidget(self.InputValidation, 3, 3)
        grid.addWidget(self.InputTest, 4, 3)
        grid.addWidget(btn, 5, 0, 1, 2)
        grid.addWidget(btn1, 5, 2, 1, 2)
        
        grid.addWidget(Title1, 6, 0, 1, 4)
        grid.addWidget(TitleSc, 7, 0)
        grid.addWidget(self.InputScale, 7, 1)
        grid.addWidget(TitleSs, 7, 2)
        grid.addWidget(self.InputStep, 7, 3)
        grid.addWidget(TitleNi, 8, 0)
        grid.addWidget(self.ImageName, 8, 1)
        grid.addWidget(TitleNm, 8, 2)
        grid.addWidget(self.ModelName, 8, 3)
        grid.addWidget(btn2, 9, 1, 1, 2)
        
        self.setLayout(grid)
        
        self.setWindowTitle('Система поиска и распознавания сорных растений')
        self.setWindowIcon(QIcon('icon.png'))
        self.show()
Exemple #3
0
    def __init__(self) -> None:
        """SCOUTS Constructor. Defines all aspects of the GUI."""

        # ###
        # ### Main Window setup
        # ###

        # Inherits from QMainWindow
        super().__init__()
        self.rootdir = get_project_root()
        self.threadpool = QThreadPool()
        # Sets values for QMainWindow
        self.setWindowTitle("SCOUTS")
        self.setWindowIcon(
            QIcon(
                os.path.abspath(os.path.join(self.rootdir, 'src',
                                             'scouts.ico'))))
        # Creates StackedWidget as QMainWindow's central widget
        self.stacked_pages = QStackedWidget(self)
        self.setCentralWidget(self.stacked_pages)
        # Creates Widgets for individual "pages" and adds them to the StackedWidget
        self.main_page = QWidget()
        self.samples_page = QWidget()
        self.gating_page = QWidget()
        self.pages = (self.main_page, self.samples_page, self.gating_page)
        for page in self.pages:
            self.stacked_pages.addWidget(page)
        # ## Sets widget at program startup
        self.stacked_pages.setCurrentWidget(self.main_page)

        # ###
        # ### MAIN PAGE
        # ###

        # Main page layout
        self.main_layout = QVBoxLayout(self.main_page)

        # Title section
        # Title
        self.title = QLabel(self.main_page)
        self.title.setText('SCOUTS - Single Cell Outlier Selector')
        self.title.setStyleSheet(self.style['title'])
        self.title.adjustSize()
        self.main_layout.addWidget(self.title)

        # ## Input section
        # Input header
        self.input_header = QLabel(self.main_page)
        self.input_header.setText('Input settings')
        self.input_header.setStyleSheet(self.style['header'])
        self.main_layout.addChildWidget(self.input_header)
        self.input_header.adjustSize()
        self.main_layout.addWidget(self.input_header)
        # Input frame
        self.input_frame = QFrame(self.main_page)
        self.input_frame.setFrameShape(QFrame.StyledPanel)
        self.input_frame.setLayout(QFormLayout())
        self.main_layout.addWidget(self.input_frame)
        # Input button
        self.input_button = QPushButton(self.main_page)
        self.input_button.setStyleSheet(self.style['button'])
        self.set_icon(self.input_button, 'x-office-spreadsheet')
        self.input_button.setObjectName('input')
        self.input_button.setText(' Select input file (.xlsx or .csv)')
        self.input_button.clicked.connect(self.get_path)
        # Input path box
        self.input_path = QLineEdit(self.main_page)
        self.input_path.setObjectName('input_path')
        self.input_path.setStyleSheet(self.style['line edit'])
        # Go to sample naming page
        self.samples_button = QPushButton(self.main_page)
        self.samples_button.setStyleSheet(self.style['button'])
        self.set_icon(self.samples_button, 'preferences-other')
        self.samples_button.setText(' Name samples...')
        self.samples_button.clicked.connect(self.goto_samples_page)
        # Go to gating page
        self.gates_button = QPushButton(self.main_page)
        self.gates_button.setStyleSheet(self.style['button'])
        self.set_icon(self.gates_button, 'preferences-other')
        self.gates_button.setText(' Gating && outlier options...')
        self.gates_button.clicked.connect(self.goto_gates_page)
        # Add widgets above to input frame Layout
        self.input_frame.layout().addRow(self.input_button, self.input_path)
        self.input_frame.layout().addRow(self.samples_button)
        self.input_frame.layout().addRow(self.gates_button)

        # ## Analysis section
        # Analysis header
        self.analysis_header = QLabel(self.main_page)
        self.analysis_header.setText('Analysis settings')
        self.analysis_header.setStyleSheet(self.style['header'])
        self.analysis_header.adjustSize()
        self.main_layout.addWidget(self.analysis_header)
        # Analysis frame
        self.analysis_frame = QFrame(self.main_page)
        self.analysis_frame.setFrameShape(QFrame.StyledPanel)
        self.analysis_frame.setLayout(QVBoxLayout())
        self.main_layout.addWidget(self.analysis_frame)
        # Cutoff text
        self.cutoff_text = QLabel(self.main_page)
        self.cutoff_text.setText('Type of outlier to select:')
        self.cutoff_text.setToolTip(
            'Choose whether to select outliers using the cutoff value from a reference\n'
            'sample (OutR) or by using the cutoff value calculated for each sample\n'
            'individually (OutS)')
        self.cutoff_text.setStyleSheet(self.style['label'])
        # Cutoff button group
        self.cutoff_group = QButtonGroup(self)
        # Cutoff by sample
        self.cutoff_sample = QRadioButton(self.main_page)
        self.cutoff_sample.setText('OutS')
        self.cutoff_sample.setObjectName('sample')
        self.cutoff_sample.setStyleSheet(self.style['radio button'])
        self.cutoff_sample.setChecked(True)
        self.cutoff_group.addButton(self.cutoff_sample)
        # Cutoff by reference
        self.cutoff_reference = QRadioButton(self.main_page)
        self.cutoff_reference.setText('OutR')
        self.cutoff_reference.setObjectName('ref')
        self.cutoff_reference.setStyleSheet(self.style['radio button'])
        self.cutoff_group.addButton(self.cutoff_reference)
        # Both cutoffs
        self.cutoff_both = QRadioButton(self.main_page)
        self.cutoff_both.setText('both')
        self.cutoff_both.setObjectName('sample ref')
        self.cutoff_both.setStyleSheet(self.style['radio button'])
        self.cutoff_group.addButton(self.cutoff_both)
        # Markers text
        self.markers_text = QLabel(self.main_page)
        self.markers_text.setStyleSheet(self.style['label'])
        self.markers_text.setText('Show results for:')
        self.markers_text.setToolTip(
            'Individual markers: for each marker, select outliers\n'
            'Any marker: select cells that are outliers for AT LEAST one marker'
        )
        # Markers button group
        self.markers_group = QButtonGroup(self)
        # Single marker
        self.single_marker = QRadioButton(self.main_page)
        self.single_marker.setText('individual markers')
        self.single_marker.setObjectName('single')
        self.single_marker.setStyleSheet(self.style['radio button'])
        self.single_marker.setChecked(True)
        self.markers_group.addButton(self.single_marker)
        # Any marker
        self.any_marker = QRadioButton(self.main_page)
        self.any_marker.setText('any marker')
        self.any_marker.setObjectName('any')
        self.any_marker.setStyleSheet(self.style['radio button'])
        self.markers_group.addButton(self.any_marker)
        # Both methods
        self.both_methods = QRadioButton(self.main_page)
        self.both_methods.setText('both')
        self.both_methods.setObjectName('single any')
        self.both_methods.setStyleSheet(self.style['radio button'])
        self.markers_group.addButton(self.both_methods)
        # Tukey text
        self.tukey_text = QLabel(self.main_page)
        self.tukey_text.setStyleSheet(self.style['label'])
        # Tukey button group
        self.tukey_text.setText('Tukey factor:')
        self.tukey_group = QButtonGroup(self)
        # Low Tukey value
        self.tukey_low = QRadioButton(self.main_page)
        self.tukey_low.setText('1.5')
        self.tukey_low.setStyleSheet(self.style['radio button'])
        self.tukey_low.setChecked(True)
        self.tukey_group.addButton(self.tukey_low)
        # High Tukey value
        self.tukey_high = QRadioButton(self.main_page)
        self.tukey_high.setText('3.0')
        self.tukey_high.setStyleSheet(self.style['radio button'])
        self.tukey_group.addButton(self.tukey_high)
        # Add widgets above to analysis frame layout
        self.analysis_frame.layout().addWidget(self.cutoff_text)
        self.cutoff_buttons = QHBoxLayout()
        for button in self.cutoff_group.buttons():
            self.cutoff_buttons.addWidget(button)
        self.analysis_frame.layout().addLayout(self.cutoff_buttons)
        self.analysis_frame.layout().addWidget(self.markers_text)
        self.markers_buttons = QHBoxLayout()
        for button in self.markers_group.buttons():
            self.markers_buttons.addWidget(button)
        self.analysis_frame.layout().addLayout(self.markers_buttons)
        self.analysis_frame.layout().addWidget(self.tukey_text)
        self.tukey_buttons = QHBoxLayout()
        for button in self.tukey_group.buttons():
            self.tukey_buttons.addWidget(button)
        self.tukey_buttons.addWidget(QLabel())  # aligns row with 2 buttons
        self.analysis_frame.layout().addLayout(self.tukey_buttons)

        # ## Output section
        # Output header
        self.output_header = QLabel(self.main_page)
        self.output_header.setText('Output settings')
        self.output_header.setStyleSheet(self.style['header'])
        self.output_header.adjustSize()
        self.main_layout.addWidget(self.output_header)
        # Output frame
        self.output_frame = QFrame(self.main_page)
        self.output_frame.setFrameShape(QFrame.StyledPanel)
        self.output_frame.setLayout(QFormLayout())
        self.main_layout.addWidget(self.output_frame)
        # Output button
        self.output_button = QPushButton(self.main_page)
        self.output_button.setStyleSheet(self.style['button'])
        self.set_icon(self.output_button, 'folder')
        self.output_button.setObjectName('output')
        self.output_button.setText(' Select output folder')
        self.output_button.clicked.connect(self.get_path)
        # Output path box
        self.output_path = QLineEdit(self.main_page)
        self.output_path.setStyleSheet(self.style['line edit'])
        # Generate CSV checkbox
        self.output_csv = QCheckBox(self.main_page)
        self.output_csv.setText('Export multiple text files (.csv)')
        self.output_csv.setStyleSheet(self.style['checkbox'])
        self.output_csv.setChecked(True)
        # Generate XLSX checkbox
        self.output_excel = QCheckBox(self.main_page)
        self.output_excel.setText('Export multiple Excel spreadsheets (.xlsx)')
        self.output_excel.setStyleSheet(self.style['checkbox'])
        self.output_excel.clicked.connect(self.enable_single_excel)
        # Generate single, large XLSX checkbox
        self.single_excel = QCheckBox(self.main_page)
        self.single_excel.setText(
            'Also save one multi-sheet Excel spreadsheet')
        self.single_excel.setToolTip(
            'After generating all Excel spreadsheets, SCOUTS combines them into '
            'a single\nExcel spreadsheet where each sheet corresponds to an output'
            'file from SCOUTS')
        self.single_excel.setStyleSheet(self.style['checkbox'])
        self.single_excel.setEnabled(False)
        self.single_excel.clicked.connect(self.memory_warning)
        # Add widgets above to output frame layout
        self.output_frame.layout().addRow(self.output_button, self.output_path)
        self.output_frame.layout().addRow(self.output_csv)
        self.output_frame.layout().addRow(self.output_excel)
        self.output_frame.layout().addRow(self.single_excel)

        # ## Run & help-quit section
        # Run button (stand-alone)
        self.run_button = QPushButton(self.main_page)
        self.set_icon(self.run_button, 'system-run')
        self.run_button.setText(' Run!')
        self.run_button.setStyleSheet(self.style['run button'])
        self.main_layout.addWidget(self.run_button)
        self.run_button.clicked.connect(self.run)
        # Help-quit frame (invisible)
        self.helpquit_frame = QFrame(self.main_page)
        self.helpquit_frame.setLayout(QHBoxLayout())
        self.helpquit_frame.layout().setMargin(0)
        self.main_layout.addWidget(self.helpquit_frame)
        # Help button
        self.help_button = QPushButton(self.main_page)
        self.set_icon(self.help_button, 'help-about')
        self.help_button.setText(' Help')
        self.help_button.setStyleSheet(self.style['md button'])
        self.help_button.clicked.connect(self.get_help)
        # Quit button
        self.quit_button = QPushButton(self.main_page)
        self.set_icon(self.quit_button, 'process-stop')
        self.quit_button.setText(' Quit')
        self.quit_button.setStyleSheet(self.style['md button'])
        self.quit_button.clicked.connect(self.close)
        # Add widgets above to help-quit layout
        self.helpquit_frame.layout().addWidget(self.help_button)
        self.helpquit_frame.layout().addWidget(self.quit_button)

        # ###
        # ### SAMPLES PAGE
        # ###

        # Samples page layout
        self.samples_layout = QVBoxLayout(self.samples_page)

        # ## Title section
        # Title
        self.samples_title = QLabel(self.samples_page)
        self.samples_title.setText('Name your samples')
        self.samples_title.setStyleSheet(self.style['title'])
        self.samples_title.adjustSize()
        self.samples_layout.addWidget(self.samples_title)
        # Subtitle
        self.samples_subtitle = QLabel(self.samples_page)
        string = (
            'Please name the samples to be analysed by SCOUTS.\n\nSCOUTS searches the first '
            'column of your data\nand locates the exact string as part of the sample name.'
        )
        self.samples_subtitle.setText(string)
        self.samples_subtitle.setStyleSheet(self.style['label'])
        self.samples_subtitle.adjustSize()
        self.samples_layout.addWidget(self.samples_subtitle)

        # ## Sample addition section
        # Sample addition frame
        self.samples_frame = QFrame(self.samples_page)
        self.samples_frame.setFrameShape(QFrame.StyledPanel)
        self.samples_frame.setLayout(QGridLayout())
        self.samples_layout.addWidget(self.samples_frame)
        # Sample name box
        self.sample_name = QLineEdit(self.samples_page)
        self.sample_name.setStyleSheet(self.style['line edit'])
        self.sample_name.setPlaceholderText('Sample name ...')
        # Reference check
        self.is_reference = QCheckBox(self.samples_page)
        self.is_reference.setText('Reference?')
        self.is_reference.setStyleSheet(self.style['checkbox'])
        # Add sample to table
        self.add_sample_button = QPushButton(self.samples_page)
        QShortcut(QKeySequence("Return"), self.add_sample_button,
                  self.write_to_sample_table)
        self.set_icon(self.add_sample_button, 'list-add')
        self.add_sample_button.setText(' Add sample (Enter)')
        self.add_sample_button.setStyleSheet(self.style['button'])
        self.add_sample_button.clicked.connect(self.write_to_sample_table)
        # Remove sample from table
        self.remove_sample_button = QPushButton(self.samples_page)
        QShortcut(QKeySequence("Delete"), self.remove_sample_button,
                  self.remove_from_sample_table)
        self.set_icon(self.remove_sample_button, 'list-remove')
        self.remove_sample_button.setText(' Remove sample (Del)')
        self.remove_sample_button.setStyleSheet(self.style['button'])
        self.remove_sample_button.clicked.connect(
            self.remove_from_sample_table)
        # Add widgets above to sample addition layout
        self.samples_frame.layout().addWidget(self.sample_name, 0, 0)
        self.samples_frame.layout().addWidget(self.is_reference, 1, 0)
        self.samples_frame.layout().addWidget(self.add_sample_button, 0, 1)
        self.samples_frame.layout().addWidget(self.remove_sample_button, 1, 1)

        # ## Sample table
        self.sample_table = QTableWidget(self.samples_page)
        self.sample_table.setColumnCount(2)
        self.sample_table.setHorizontalHeaderItem(0,
                                                  QTableWidgetItem('Sample'))
        self.sample_table.setHorizontalHeaderItem(
            1, QTableWidgetItem('Reference?'))
        self.sample_table.horizontalHeader().setSectionResizeMode(
            0, QHeaderView.Stretch)
        self.sample_table.horizontalHeader().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self.samples_layout.addWidget(self.sample_table)

        # ## Save & clear buttons
        # Save & clear frame (invisible)
        self.saveclear_frame = QFrame(self.samples_page)
        self.saveclear_frame.setLayout(QHBoxLayout())
        self.saveclear_frame.layout().setMargin(0)
        self.samples_layout.addWidget(self.saveclear_frame)
        # Clear samples button
        self.clear_samples = QPushButton(self.samples_page)
        self.set_icon(self.clear_samples, 'edit-delete')
        self.clear_samples.setText(' Clear table')
        self.clear_samples.setStyleSheet(self.style['md button'])
        self.clear_samples.clicked.connect(self.prompt_clear_data)
        # Save samples button
        self.save_samples = QPushButton(self.samples_page)
        self.set_icon(self.save_samples, 'document-save')
        self.save_samples.setText(' Save samples')
        self.save_samples.setStyleSheet(self.style['md button'])
        self.save_samples.clicked.connect(self.goto_main_page)
        # Add widgets above to save & clear layout
        self.saveclear_frame.layout().addWidget(self.clear_samples)
        self.saveclear_frame.layout().addWidget(self.save_samples)

        # ###
        # ### GATING PAGE
        # ###

        # Gating page layout
        self.gating_layout = QVBoxLayout(self.gating_page)

        # ## Title section
        # Title
        self.gates_title = QLabel(self.gating_page)
        self.gates_title.setText('Gating & outlier options')
        self.gates_title.setStyleSheet(self.style['title'])
        self.gates_title.adjustSize()
        self.gating_layout.addWidget(self.gates_title)

        # ## Gating options section
        # Gating header
        self.gate_header = QLabel(self.gating_page)
        self.gate_header.setText('Gating')
        self.gate_header.setStyleSheet(self.style['header'])
        self.gate_header.adjustSize()
        self.gating_layout.addWidget(self.gate_header)

        # Gating frame
        self.gate_frame = QFrame(self.gating_page)
        self.gate_frame.setFrameShape(QFrame.StyledPanel)
        self.gate_frame.setLayout(QFormLayout())
        self.gating_layout.addWidget(self.gate_frame)
        # Gating button group
        self.gating_group = QButtonGroup(self)
        # Do not gate samples
        self.no_gates = QRadioButton(self.gating_page)
        self.no_gates.setObjectName('no_gate')
        self.no_gates.setText("Don't gate samples")
        self.no_gates.setStyleSheet(self.style['radio button'])
        self.no_gates.setChecked(True)
        self.gating_group.addButton(self.no_gates)
        self.no_gates.clicked.connect(self.activate_gate)
        # CyToF gating
        self.cytof_gates = QRadioButton(self.gating_page)
        self.cytof_gates.setObjectName('cytof')
        self.cytof_gates.setText('Mass Cytometry gating')
        self.cytof_gates.setStyleSheet(self.style['radio button'])
        self.cytof_gates.setToolTip(
            'Exclude cells for which the average expression of all\n'
            'markers is below the selected value')
        self.gating_group.addButton(self.cytof_gates)
        self.cytof_gates.clicked.connect(self.activate_gate)
        # CyToF gating spinbox
        self.cytof_gates_value = QDoubleSpinBox(self.gating_page)
        self.cytof_gates_value.setMinimum(0)
        self.cytof_gates_value.setMaximum(1)
        self.cytof_gates_value.setValue(0.1)
        self.cytof_gates_value.setSingleStep(0.05)
        self.cytof_gates_value.setEnabled(False)
        # scRNA-Seq gating
        self.rnaseq_gates = QRadioButton(self.gating_page)
        self.rnaseq_gates.setText('scRNA-Seq gating')
        self.rnaseq_gates.setStyleSheet(self.style['radio button'])
        self.rnaseq_gates.setToolTip(
            'When calculating cutoff, ignore reads below the selected value')
        self.rnaseq_gates.setObjectName('rnaseq')
        self.gating_group.addButton(self.rnaseq_gates)
        self.rnaseq_gates.clicked.connect(self.activate_gate)
        # scRNA-Seq gating spinbox
        self.rnaseq_gates_value = QDoubleSpinBox(self.gating_page)
        self.rnaseq_gates_value.setMinimum(0)
        self.rnaseq_gates_value.setMaximum(10)
        self.rnaseq_gates_value.setValue(0)
        self.rnaseq_gates_value.setSingleStep(1)
        self.rnaseq_gates_value.setEnabled(False)
        # export gated population checkbox
        self.export_gated = QCheckBox(self.gating_page)
        self.export_gated.setText('Export gated cells as an output file')
        self.export_gated.setStyleSheet(self.style['checkbox'])
        self.export_gated.setEnabled(False)
        # Add widgets above to Gate frame layout
        self.gate_frame.layout().addRow(self.no_gates, QLabel())
        self.gate_frame.layout().addRow(self.cytof_gates,
                                        self.cytof_gates_value)
        self.gate_frame.layout().addRow(self.rnaseq_gates,
                                        self.rnaseq_gates_value)
        self.gate_frame.layout().addRow(self.export_gated, QLabel())

        # ## Outlier options section
        # Outlier header
        self.outlier_header = QLabel(self.gating_page)
        self.outlier_header.setText('Outliers')
        self.outlier_header.setStyleSheet(self.style['header'])
        self.outlier_header.adjustSize()
        self.gating_layout.addWidget(self.outlier_header)
        # Outlier frame
        self.outlier_frame = QFrame(self.gating_page)
        self.outlier_frame.setFrameShape(QFrame.StyledPanel)
        self.outlier_frame.setLayout(QVBoxLayout())
        self.gating_layout.addWidget(self.outlier_frame)
        # Top outliers information
        self.top_outliers = QLabel(self.gating_page)
        self.top_outliers.setStyleSheet(self.style['label'])
        self.top_outliers.setText(
            'By default, SCOUTS selects the top outliers from the population')
        self.top_outliers.setStyleSheet(self.style['label'])
        # Bottom outliers data
        self.bottom_outliers = QCheckBox(self.gating_page)
        self.bottom_outliers.setText('Include results for low outliers')
        self.bottom_outliers.setStyleSheet(self.style['checkbox'])
        # Non-outliers data
        self.not_outliers = QCheckBox(self.gating_page)
        self.not_outliers.setText('Include results for non-outliers')
        self.not_outliers.setStyleSheet(self.style['checkbox'])
        # Add widgets above to Gate frame layout
        self.outlier_frame.layout().addWidget(self.top_outliers)
        self.outlier_frame.layout().addWidget(self.bottom_outliers)
        self.outlier_frame.layout().addWidget(self.not_outliers)

        # ## Save/back button
        self.save_gates = QPushButton(self.gating_page)
        self.set_icon(self.save_gates, 'go-next')
        self.save_gates.setText(' Back to main menu')
        self.save_gates.setStyleSheet(self.style['md button'])
        self.gating_layout.addWidget(self.save_gates)
        self.save_gates.clicked.connect(self.goto_main_page)

        # ## Add empty label to take vertical space
        self.empty_label = QLabel(self.gating_page)
        self.empty_label.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Expanding)
        self.gating_layout.addWidget(self.empty_label)
    def __init__(self):
        super(WidgetConfig, self).__init__()

        HEIGHT = 40

        grid = QGridLayout()

        # 使用默认摄像头复选框
        self.check_camera = QCheckBox('Use default camera')
        self.check_camera.setChecked(False)
        self.check_camera.stateChanged.connect(self.slot_check_camera)

        grid.addWidget(self.check_camera, 0, 0, 1, 3)  # 一行三列

        # 选择视频文件
        label_video = QLabel('Detect File')
        self.line_video = QLineEdit()
        if 'video' in GLOBAL.config:
            self.line_video.setText(GLOBAL.config['video'])
        self.line_video.setFixedHeight(HEIGHT)
        self.line_video.setEnabled(False)
        self.line_video.editingFinished.connect(
            lambda: GLOBAL.record_config({'video': self.line_video.text()}))

        self.btn_video = QPushButton('Choose')
        self.btn_video.setFixedHeight(HEIGHT)
        self.btn_video.setEnabled(False)
        self.btn_video.clicked.connect(self.choose_video_file)

        self.slot_check_camera()

        grid.addWidget(label_video, 1, 0)
        grid.addWidget(self.line_video, 1, 1)
        grid.addWidget(self.btn_video, 1, 2)

        # 选择权重文件
        label_weights = QLabel('Weights File')
        self.line_weights = QLineEdit()
        if 'weights' in GLOBAL.config:
            self.line_weights.setText(GLOBAL.config['weights'])
        self.line_weights.setFixedHeight(HEIGHT)
        self.line_weights.editingFinished.connect(lambda: GLOBAL.record_config(
            {'weights': self.line_weights.text()}))

        self.btn_weights = QPushButton('Choose')
        self.btn_weights.setFixedHeight(HEIGHT)
        self.btn_weights.clicked.connect(self.choose_weights_file)

        grid.addWidget(label_weights, 2, 0)
        grid.addWidget(self.line_weights, 2, 1)
        grid.addWidget(self.btn_weights, 2, 2)

        # 是否使用GPU
        label_device = QLabel('CUDA device')
        self.line_device = QLineEdit('gpu')
        if 'device' in GLOBAL.config:
            self.line_device.setText(GLOBAL.config['device'])
        else:
            self.line_device.setText('cpu')
        self.line_device.setPlaceholderText('cpu or 0 or 0,1,2,3')
        self.line_device.setFixedHeight(HEIGHT)
        self.line_device.editingFinished.connect(
            lambda: GLOBAL.record_config({'device': self.line_device.text()}))

        grid.addWidget(label_device, 3, 0)
        grid.addWidget(self.line_device, 3, 1, 1, 2)

        # 设置图像大小
        label_size = QLabel('Img Size')
        self.combo_size = QComboBox()
        self.combo_size.setFixedHeight(HEIGHT)
        self.combo_size.setStyleSheet(
            'QAbstractItemView::item {height: 40px;}')
        self.combo_size.setView(QListView())
        self.combo_size.addItem('320', 320)
        self.combo_size.addItem('416', 416)
        self.combo_size.addItem('480', 480)
        self.combo_size.addItem('544', 544)
        self.combo_size.addItem('640', 640)
        self.combo_size.setCurrentIndex(2)
        self.combo_size.currentIndexChanged.connect(
            lambda: GLOBAL.record_config(
                {'img_size': self.combo_size.currentData()}))

        grid.addWidget(label_size, 4, 0)
        grid.addWidget(self.combo_size, 4, 1, 1, 2)

        #choose net camera
        label_stream = QLabel('NetVedioStream')
        self.combo_stream = QComboBox()
        self.combo_stream.setFixedHeight(HEIGHT)
        self.combo_stream.setStyleSheet(
            'QAbstractItemView::item {height: 40px;}')
        self.combo_stream.setView(QListView())
        self.combo_stream.addItem('rtsp://*****:*****@192.168.0.65/',
                                  'rtsp://*****:*****@192.168.0.65/')
        self.combo_stream.addItem('rtsp://*****:*****@192.168.0.66/',
                                  'rtsp://*****:*****@192.168.0.66/')
        self.combo_stream.addItem('rtsp://*****:*****@192.168.0.67/',
                                  'rtsp://*****:*****@192.168.0.67/')
        self.combo_stream.addItem('rtsp://*****:*****@192.168.0.68/',
                                  'rtsp://*****:*****@192.168.0.68/')
        self.combo_stream.addItem('rtsp://*****:*****@192.168.0.65/',
                                  'rtsp://*****:*****@192.168.0.65/')
        self.combo_stream.setCurrentIndex(0)
        self.combo_stream.currentIndexChanged.connect(
            lambda: GLOBAL.record_config(
                {'netstreamvedio': self.combo_stream.currentData()}))

        grid.addWidget(label_stream, 5, 0)
        grid.addWidget(self.combo_stream, 5, 1, 1, 2)

        # 设置置信度阈值
        label_conf = QLabel('Confidence')
        self.spin_conf = QDoubleSpinBox()
        self.spin_conf.setFixedHeight(HEIGHT)
        self.spin_conf.setDecimals(1)
        self.spin_conf.setRange(0.1, 0.9)
        self.spin_conf.setSingleStep(0.1)
        if 'conf_thresh' in GLOBAL.config:
            self.spin_conf.setValue(GLOBAL.config['conf_thresh'])
        else:
            self.spin_conf.setValue(0.4)  # 默认值
            GLOBAL.record_config({'conf_thresh': 0.4})
        self.spin_conf.valueChanged.connect(lambda: GLOBAL.record_config(
            {'conf_thresh': round(self.spin_conf.value(), 1)}))

        grid.addWidget(label_conf, 6, 0)
        grid.addWidget(self.spin_conf, 6, 1, 1, 2)

        # 设置IOU阈值
        label_iou = QLabel('IOU')
        self.spin_iou = QDoubleSpinBox()
        self.spin_iou.setFixedHeight(HEIGHT)
        self.spin_iou.setDecimals(1)
        self.spin_iou.setRange(0.1, 0.9)
        self.spin_iou.setSingleStep(0.1)
        if 'iou_thresh' in GLOBAL.config:
            self.spin_iou.setValue(GLOBAL.config['iou_thresh'])
        else:
            self.spin_iou.setValue(0.5)  # 默认值
            GLOBAL.record_config({'iou_thresh': 0.5})
        self.spin_iou.valueChanged.connect(lambda: GLOBAL.record_config(
            {'iou_thresh': round(self.spin_iou.value(), 1)}))

        grid.addWidget(label_iou, 7, 0)
        grid.addWidget(self.spin_iou, 7, 1, 1, 2)

        # class-agnostic NMS
        self.check_agnostic = QCheckBox('Agnostic')
        if 'agnostic' in GLOBAL.config:
            self.check_agnostic.setChecked(GLOBAL.config['agnostic'])
        else:
            self.check_agnostic.setChecked(True)
        self.check_agnostic.stateChanged.connect(lambda: GLOBAL.record_config(
            {'agnostic': self.check_agnostic.isChecked()}))

        grid.addWidget(self.check_agnostic, 8, 0, 1, 3)  # 一行三列

        # augmented inference
        self.check_augment = QCheckBox('Augment')
        if 'augment' in GLOBAL.config:
            self.check_augment.setChecked(GLOBAL.config['augment'])
        else:
            self.check_augment.setChecked(True)
        self.check_augment.stateChanged.connect(lambda: GLOBAL.record_config(
            {'augment': self.check_augment.isChecked()}))

        grid.addWidget(self.check_augment, 9, 0, 1, 3)  # 一行三列

        self.setLayout(grid)  # 设置布局
Exemple #5
0
    def __init__(self, parent=None):
        super(NGL_HKLViewer, self).__init__(parent)

        self.verbose = 0
        self.UseOSbrowser = False
        self.jscriptfname = ""
        self.devmode = False
        for e in sys.argv:
            if "verbose" in e:
                self.verbose = e.split("verbose=")[1]
            if "UseOSbrowser" in e:
                self.UseOSbrowser = e.split("UseOSbrowser=")[1]
            if "jscriptfname" in e:
                self.jscriptfname = e.split("jscriptfname=")[1]
            if "devmode" in e:
                self.devmode = True

        self.zmq_context = None
        self.bufsize = 20000

        self.originalPalette = QApplication.palette()

        self.openFileNameButton = QPushButton("Load reflection file")
        self.openFileNameButton.setDefault(True)
        self.openFileNameButton.clicked.connect(self.OpenReflectionsFile)

        self.debugbutton = QPushButton("Debug")
        self.debugbutton.clicked.connect(self.DebugInteractively)

        self.settingsbtn = QPushButton("Settings")
        self.settingsbtn.clicked.connect(self.SettingsDialog)

        self.mousemoveslider = QSlider(Qt.Horizontal)
        self.mousemoveslider.setMinimum(0)
        self.mousemoveslider.setMaximum(300)
        self.mousemoveslider.setValue(0)
        self.mousemoveslider.sliderReleased.connect(
            self.onFinalMouseSensitivity)
        self.mousemoveslider.valueChanged.connect(self.onMouseSensitivity)
        self.mousesensitxtbox = QLineEdit('')
        self.mousesensitxtbox.setReadOnly(True)
        self.fontspinBox = QDoubleSpinBox()
        self.fontspinBox.setSingleStep(1)
        self.fontspinBox.setRange(4, 50)
        self.font = QFont()
        self.font.setFamily(self.font.defaultFamily())
        self.fontspinBox.setValue(self.font.pointSize())
        #self.fontspinBox.setValue(self.font.pixelSize())
        self.fontspinBox.valueChanged.connect(self.onFontsizeChanged)
        self.Fontsize_labeltxt = QLabel()
        self.Fontsize_labeltxt.setText("Font size:")

        self.cameraPerspectCheckBox = QCheckBox()
        self.cameraPerspectCheckBox.setText("Perspective camera")
        self.cameraPerspectCheckBox.clicked.connect(self.onCameraPerspect)
        self.cameraPerspectCheckBox.setCheckState(Qt.Unchecked)

        self.settingsform = SettingsForm(self)

        self.MillerComboBox = QComboBox()
        self.MillerComboBox.activated.connect(self.onMillerComboSelchange)
        #self.MillerComboBox.setSizeAdjustPolicy(QComboBox.AdjustToContents)

        self.MillerLabel = QLabel()
        self.MillerLabel.setText("Selected HKL Scene")

        self.HKLnameedit = QLineEdit('')
        self.HKLnameedit.setReadOnly(True)
        self.textInfo = QTextEdit()
        self.textInfo.setLineWrapMode(QTextEdit.NoWrap)
        self.textInfo.setReadOnly(True)

        labels = [
            "Label", "Type", "no. of HKLs", "Span of HKLs", "Min Max data",
            "Min Max sigmas", "d_min, d_max", "Symmetry unique", "Anomalous"
        ]
        self.millertable = QTableWidget(0, len(labels))
        self.millertable.setHorizontalHeaderLabels(labels)
        self.millertable.horizontalHeader().setDefaultAlignment(Qt.AlignLeft)
        # don't allow editing this table
        self.millertable.setEditTriggers(QTableWidget.NoEditTriggers)

        self.createExpansionBox()
        self.createFileInfoBox()
        self.CreateSliceTabs()
        self.createRadiiScaleGroupBox()
        self.createBinsBox()
        self.CreateFunctionTabs()

        mainLayout = QGridLayout()
        mainLayout.addWidget(self.FileInfoBox, 0, 0)
        mainLayout.addWidget(self.MillerLabel, 1, 0)
        mainLayout.addWidget(self.MillerComboBox, 2, 0)
        mainLayout.addWidget(self.functionTabWidget, 3, 0)
        mainLayout.addWidget(self.settingsbtn, 4, 0, 1, 1)

        #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) )
        if self.UseOSbrowser == False:
            self.BrowserBox = QWebEngineView()
            mainLayout.addWidget(self.BrowserBox, 0, 1, 5, 3)
            self.BrowserBox.setUrl("https://cctbx.github.io/")
            #self.BrowserBox.setUrl("https://webglreport.com/")
            #self.BrowserBox.loadFinished.connect(self.onLoadFinished)
            mainLayout.setColumnStretch(2, 1)

        mainLayout.setRowStretch(0, 1)
        mainLayout.setRowStretch(1, 0)
        mainLayout.setRowStretch(2, 1)
        mainLayout.setRowStretch(3, 1)
        mainLayout.setColumnStretch(4, 0)
        self.setLayout(mainLayout)

        self.setWindowTitle("HKL-Viewer")
        self.cctbxproc = None
        self.LaunchCCTBXPython()
        self.out = None
        self.err = None
        self.comboviewwidth = 0
        self.hklscenes_arrays = []
        self.array_infotpls = []
        self.matching_arrays = []
        self.bin_infotpls = None
        self.bin_opacities = None
        self.html_url = ""
        self.spacegroups = []
        self.info = []
        self.infostr = ""
        self.fileisvalid = False
        self.NewFileLoaded = False
        self.NewHKLscenes = False
        self.updatingNbins = False
        self.binstableitemchanges = False

        self.show()
Exemple #6
0
class FirstAlgorithm(QDialog):

    executed = Signal(dict, list)

    defaultParameters = {
        'offset filter': True,
        'supply filter': True,
        'LPF highcut': 3,
        'BPF lowcut': 8,
        'BPF highcut': 30,
        'art thres': 100,
        'window': 25,
        'prev sec': 5,
        'hmt larger': 3,
        'hmt larger mean': 2,
    }

    def __init__(self,
                 dataManager,
                 chartManager,
                 parent=None,
                 inputList=None,
                 initParam=None):
        QDialog.__init__(self, parent)

        self.dataManager = dataManager
        self.fs = self.dataManager.getFs()
        self.chartManager = chartManager
        self.setWindowTitle('Algorithms')
        self.inputList = inputList
        if initParam:
            self.parameters = initParam
            print('initParam')
        else:
            self.parameters = self.defaultParameters
            print('defaultParameters')

        #Setup Layouts
        self.mainLayout = QVBoxLayout(self)
        self.setupInLayout()

        self.setupSettings()

        self.setupBtnBoxLayout()

    def setupInLayout(self):
        inGroup = QGroupBox('Input to process')
        inLayout = QFormLayout(inGroup)

        self.inTree = DataSelector(self.dataManager, inputList=self.inputList)

        inLayout.addWidget(QLabel('Select Input'))
        inLayout.addWidget(self.inTree)

        self.mainLayout.addWidget(inGroup)

    def setupSettings(self):

        spinBoxLayout = QFormLayout()

        self.removeOffset = QCheckBox('Remove DC offset')
        self.removeOffset.setChecked(self.parameters['offset filter'])
        spinBoxLayout.addRow(self.removeOffset)

        self.removeSupply = QCheckBox('Remove 50Hz')
        self.removeSupply.setChecked(self.parameters['supply filter'])
        spinBoxLayout.addRow(self.removeSupply)

        ##        self.lpfHighcut = QSpinBox()
        ##        self.lpfHighcut.setMaximum(10000)
        ##        self.lpfHighcut.setValue(self.parameters['LPF highcut'])
        ##        spinBoxLayout.addRow('LPF highcut frequency:', self.lpfHighcut)

        self.bpfLowcut = QSpinBox()
        self.bpfLowcut.setMaximum(10000)
        self.bpfLowcut.setValue(self.parameters['BPF lowcut'])
        spinBoxLayout.addRow('BPF lowcut frequency:', self.bpfLowcut)

        self.bpfHighcut = QSpinBox()
        self.bpfHighcut.setMaximum(10000)
        self.bpfHighcut.setValue(self.parameters['BPF highcut'])
        spinBoxLayout.addRow('BPF highcut frequency:', self.bpfHighcut)

        ##        self.ArtefactsThreshold = QSpinBox()
        ##        self.ArtefactsThreshold.setMaximum(10000)
        ##        self.ArtefactsThreshold.setValue(self.parameters['art thres'])
        ##        spinBoxLayout.addRow('Artefacts Threshold:', self.ArtefactsThreshold)

        self.algWindowSize = QSpinBox()
        self.algWindowSize.setMaximum(10000)
        self.algWindowSize.setValue(self.parameters['window'])
        spinBoxLayout.addRow('Window (samples):', self.algWindowSize)

        self.hmtLargerMean = QDoubleSpinBox()
        self.hmtLargerMean.setMinimum(0.1)
        self.hmtLargerMean.setMaximum(10000)
        self.hmtLargerMean.setValue(self.parameters['hmt larger mean'])
        spinBoxLayout.addRow('How many times larger than mean:',
                             self.hmtLargerMean)

        self.prevSeconds = QDoubleSpinBox()
        self.prevSeconds.setMinimum(0.1)
        self.prevSeconds.setMaximum(10000)
        self.prevSeconds.setValue(self.parameters['prev sec'])
        spinBoxLayout.addRow('Number of previous seconds:', self.prevSeconds)

        self.hmtLarger = QDoubleSpinBox()
        self.hmtLarger.setMinimum(0.1)
        self.hmtLarger.setMaximum(10000)
        self.hmtLarger.setValue(self.parameters['hmt larger'])
        spinBoxLayout.addRow('How many times larger than previous:',
                             self.hmtLarger)

        gBox = QGroupBox('Settings')
        gBox.setLayout(spinBoxLayout)
        self.mainLayout.addWidget(gBox)

    def setupBtnBoxLayout(self):
        bottomLayout = QHBoxLayout()
        self.progBar = QProgressBar()
        self.progBar.setVisible(False)
        bottomLayout.addWidget(self.progBar)
        buttonBox = QDialogButtonBox(QDialogButtonBox.Ok
                                     | QDialogButtonBox.Close)
        buttonBox.accepted.connect(self.okBtnBox)
        buttonBox.rejected.connect(self.close)
        bottomLayout.addWidget(buttonBox)
        self.mainLayout.addLayout(bottomLayout)

    def okBtnBox(self):
        inStruct = self.inTree.getSelectedStruct()
        inDataStruct = self.dataManager.getData(inStruct, inv=True)

        self.progBar.setVisible(True)
        self.progBar.setValue(0)
        nProgres = 5
        progStep = 100.0 / nProgres
        progress = 0

        wName = list(inDataStruct.keys())[0]
        gName = list(inDataStruct[wName].keys())[0]

        ## Input
        inData = np.copy(inDataStruct[wName][gName])

        ## Noises
        if self.removeOffset.isChecked():
            inData = [signal.detrend(data, type='constant') for data in inData]

        if self.removeSupply.isChecked():
            b, a = filterCalc(order=5,
                              bandarr=[48, 52],
                              fs=self.fs,
                              btype='bandstop',
                              ftype='butter')
            inData = [signal.lfilter(b, a, data) for data in inData]

        winLen = self.algWindowSize.value()

        ##        ## Artefacts
        ##        lpfHighcut = self.lpfHighcut.value()
        ##        order=5
        ##
        ##        b, a = filterCalc(order, [lpfHighcut], self.fs, 'low', 'butter')
        ##        lpfData = []
        ##        for data in inData:
        ##            newData = signal.lfilter(b, a, data)
        ##            lpfData.append(newData)
        ##
        ##
        ##
        ##        segNmbr = int(np.shape(lpfData)[1]/winLen)
        ##        artefactsThreshold = self.ArtefactsThreshold.value()
        ##
        ##        lpfWinData = np.copy(lpfData)
        ##        lpfWinData = [np.array_split(ch, segNmbr) for ch in lpfWinData]
        ##
        ##        for ch in lpfWinData:
        ##            for seg in ch:
        ##                seg.fill(max(seg)- min(seg))
        ##
        progress += progStep
        self.progBar.setValue(progress)
        ##
        ####        thresLpfData = np.copy(lpfWinData)
        ##        thresLpfData = deepcopy(lpfWinData)
        ##
        ##        for x in thresLpfData:
        ##            for y in x:
        ##                if y[0] >= artefactsThreshold:
        ##                    y.fill(1)
        ##                else:
        ##                    y.fill(0)
        ##
        ##        lpfWinData = [np.concatenate(ch) for ch in lpfWinData]
        ##        thresLpfData = [np.concatenate(ch) for ch in thresLpfData]
        ##
        progress += progStep
        self.progBar.setValue(progress)

        ## Spikes
        bpfLowcut = self.bpfLowcut.value()
        bpfHighcut = self.bpfHighcut.value()
        order = 4
        b, a = filterCalc(order, [bpfLowcut, bpfHighcut], self.fs, 'band',
                          'butter')
        bpfData = []
        for data in inData:
            newData = signal.lfilter(b, a, data)
            bpfData.append(newData)

        segNmbr = int(np.shape(bpfData)[1] / winLen)

        prevSeconds = self.prevSeconds.value()
        prevWindows = int(prevSeconds * self.fs / winLen)

        progress += progStep
        self.progBar.setValue(progress)

        bpfWinData = np.copy(bpfData)
        bpfWinData = [np.array_split(ch, segNmbr) for ch in bpfWinData]
        chi = 0
        for ch in bpfWinData:
            for seg in ch:
                seg.fill(max(seg) - min(seg))

        progress += progStep
        self.progBar.setValue(progress)

        hmtLarger = self.hmtLarger.value()
        hmtLargerMean = self.hmtLargerMean.value()
        ##        thresBpfData = np.copy(bpfWinData)
        thresBpfData = deepcopy(bpfWinData)

        for ch in range(len(bpfWinData)):
            channelMean = self.hmtLargerMean.value() * np.mean(inData[ch])
            for i in range(prevWindows, len(bpfWinData[ch])):
                if bpfWinData[ch][i][0] > channelMean:
                    prev = [
                        bpfWinData[ch][j][0]
                        for j in range(i - prevWindows, i)
                    ]
                    if bpfWinData[ch][i][0] > hmtLarger * np.mean(prev):
                        thresBpfData[ch][i].fill(1)
                    else:
                        thresBpfData[ch][i].fill(0)
                else:
                    thresBpfData[ch][i].fill(0)

        progress += progStep
        self.progBar.setValue(progress)

        for ch in thresBpfData:
            for i in range(prevWindows):
                ch[i].fill(0)

        bpfWinData = [np.concatenate(ch) for ch in bpfWinData]
        thresBpfData = [np.concatenate(ch) for ch in thresBpfData]

        spikeMap = [np.sum(x) / winLen for x in thresBpfData]
        nazwaPliku = str(winLen) + '_' + str(prevSeconds) + '_' + str(
            hmtLarger) + '.csv'
        with open(nazwaPliku, 'w', encoding='utf-8') as csvfile:
            csvwriter = csv.writer(csvfile)
            csvwriter.writerow(spikeMap)


##        for ch in spikeMap
##            csvwriter.writerow(spikeMap)

## Add data or replace existing
        swsName = 'Algorithm output'
        chNames = inStruct[wName][gName]
        if swsName not in self.dataManager.getDataGroups():
            self.dataManager.createDataGroup(swsName, 'Algorithm')
            self.dataManager.addChannels(swsName, chNames)

            self.dataManager.addSignal(swsName, 'Input Signal', inData,
                                       chNames)
            ##            self.dataManager.addSignal(swsName, 'LPF', lpfData, chNames)
            ##            self.dataManager.addSignal(swsName, 'LPF+Window+Peak-to-peak', lpfWinData, chNames)
            ##            self.dataManager.addSignal(swsName, 'LPF+Threshold - Artefacts', thresLpfData, chNames)
            self.dataManager.addSignal(swsName, 'BPF', bpfData, chNames)
            self.dataManager.addSignal(swsName, 'BPF+Window+Peak-to-peak',
                                       bpfWinData, chNames)
            self.dataManager.addSignal(swsName, 'BPF+Threshold - Spikes',
                                       thresBpfData, chNames)
        else:
            self.dataManager.silentChangeSignal(swsName, 'Input Signal',
                                                inData, chNames)
            ##            self.dataManager.silentChangeSignal(swsName, 'LPF', lpfData, chNames)
            ##            self.dataManager.silentChangeSignal(swsName, 'LPF+Window+P2P', lpfWinData, chNames)
            ##            self.dataManager.silentChangeSignal(swsName, 'LPF+Threshold - Artefacts', thresLpfData, chNames)
            self.dataManager.silentChangeSignal(swsName, 'BPF', bpfData,
                                                chNames)
            self.dataManager.silentChangeSignal(swsName,
                                                'BPF+Window+Peak-to-peak',
                                                bpfWinData, chNames)
            self.dataManager.silentChangeSignal(swsName,
                                                'BPF+Threshold - Spikes',
                                                thresBpfData, chNames)

        self.chartManager.setMask('Algorithm output', 'BPF+Threshold - Spikes')
        self.chartManager.setMap(spikeMap)
        self.parameters = {
            'offset filter': self.removeOffset.isChecked(),
            'supply filter': self.removeSupply.isChecked(),
            ##                           'LPF highcut'   : lpfHighcut,
            'BPF lowcut': bpfLowcut,
            'BPF highcut': bpfHighcut,
            ##                           'art thres'     : artefactsThreshold,
            'window': winLen,
            'prev sec': prevSeconds,
            'hmt larger': hmtLarger,
            'hmt larger mean': hmtLargerMean,
        }
        self.executed.emit(self.parameters, self.inputList)
Exemple #7
0
    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 __init__(self, conn):
        '''
        Parameters:
            conn : connection
                Connection to the database.
        '''
        super().__init__()
        self.setWindowTitle('Aggiungi Acquisto')
        self.setWindowFlag(QtCore.Qt.WindowContextHelpButtonHint, False)

        self.conn = conn
        self.cursor = conn.cursor()

        self.books = dict()
        self.books_qt = dict()

        self.gen_layout = QVBoxLayout()

        self.form_layout = QFormLayout()
        self.form_layout.setRowWrapPolicy(QFormLayout.WrapLongRows)

        # Widgets
        self.client_field = QLineEdit()
        self.form_layout.addRow('Numero Cliente (facoltativo): ',
                                self.client_field)

        self.dip_field = QLineEdit()
        self.form_layout.addRow('Dipendente (CF): ', self.dip_field)

        self.date_picker = QDateEdit(QDate.currentDate())
        self.date_picker.setDisplayFormat("MM/dd/yyyy")
        self.date_picker.setCalendarPopup(True)
        self.form_layout.addRow('Data (mm/gg/aaaa): ', self.date_picker)

        self.importo_field = QDoubleSpinBox()
        self.importo_field.setMaximum(999999999.99)
        self.form_layout.addRow('Importo: ', self.importo_field)

        self.ins_layout = QHBoxLayout()
        self.libro_field = QLineEdit()
        self.quantita_field = QSpinBox()
        self.quantita_field.setMinimum(1)
        self.libro_button = QPushButton('Aggiungi')
        self.libro_button.clicked.connect(self.aggiungi_libro)
        self.ins_layout.addWidget(QLabel('Libro (ISBN): '))
        self.ins_layout.addWidget(self.libro_field)
        self.ins_layout.addWidget(QLabel('Quantità: '))
        self.ins_layout.addWidget(self.quantita_field)
        self.ins_layout.addWidget(self.libro_button)

        self.labels = ['ISBN', 'Quantità', '']
        self.table = QTableWidget(0, 3)
        self.table.setHorizontalHeaderLabels(self.labels)
        self.table.horizontalHeader().setSectionResizeMode(
            0, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            1, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)

        self.confirm_button = QPushButton('Conferma')
        self.confirm_button.clicked.connect(self.post_acquisto)

        self.gen_layout.addLayout(self.form_layout)
        self.gen_layout.addLayout(self.ins_layout)
        self.gen_layout.addWidget(self.table)
        self.gen_layout.addWidget(self.confirm_button)
        self.setLayout(self.gen_layout)
Exemple #9
0
    def __init__(self):
        super().__init__()

        layout = QVBoxLayout()

        form = QFormLayout()

        self.track_id = QSpinBox()
        self.track_id.setDisabled(True)
        self.name = QLineEdit()
        self.album = QComboBox()
        self.media_type = QComboBox()
        self.genre = QComboBox()
        self.composer = QLineEdit()

        self.milliseconds = QSpinBox()
        self.milliseconds.setRange(0, 2147483647)
        self.milliseconds.setSingleStep(1)

        self.bytes = QSpinBox()
        self.bytes.setRange(0, 2147483647)
        self.bytes.setSingleStep(1)

        self.unit_price = QDoubleSpinBox()
        self.unit_price.setRange(0, 999)
        self.unit_price.setSingleStep(0.01)
        self.unit_price.setPrefix("$")

        form.addRow(QLabel("Track ID"), self.track_id)
        form.addRow(QLabel("Track name"), self.name)
        form.addRow(QLabel("Composer"), self.composer)
        form.addRow(QLabel("Milliseconds"), self.milliseconds)
        form.addRow(QLabel("Bytes"), self.bytes)
        form.addRow(QLabel("Unit Price"), self.unit_price)

        self.model = QSqlTableModel(db=db)

        self.mapper = QDataWidgetMapper()
        self.mapper.setModel(self.model)

        self.mapper.addMapping(self.track_id, 0)
        self.mapper.addMapping(self.name, 1)
        self.mapper.addMapping(self.composer, 5)
        self.mapper.addMapping(self.milliseconds, 6)
        self.mapper.addMapping(self.bytes, 7)
        self.mapper.addMapping(self.unit_price, 8)

        self.model.setTable("Track")
        self.model.select()

        self.mapper.toFirst()

        self.setMinimumSize(QSize(400, 400))

        controls = QHBoxLayout()

        # tag::controls[]
        prev_rec = QPushButton("Previous")
        prev_rec.clicked.connect(self.mapper.toPrevious)

        next_rec = QPushButton("Next")
        next_rec.clicked.connect(self.mapper.toNext)

        save_rec = QPushButton("Save Changes")
        save_rec.clicked.connect(self.mapper.submit)
        # end::controls[]

        controls.addWidget(prev_rec)
        controls.addWidget(next_rec)
        controls.addWidget(save_rec)

        layout.addLayout(form)
        layout.addLayout(controls)

        widget = QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)
    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()
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")
Exemple #12
0
 def __init__(self, step_size, parent=None):
     QDoubleSpinBox.__init__(self, parent)
     self.step_size = step_size
     self.setKeyboardTracking(False)
     self.valueChanged.connect(self.spinbox_is_value_valid)
     self.setSingleStep(step_size)
Exemple #13
0
 def __init_advanced_features_widget__(self, parent=None):
     self.__advanced_widget = QGroupBox("Advanced Features Options", parent)
     fixed_layer_check = QCheckBox("Fixed Layer", self.__advanced_widget)
     fixed_layer_check.setChecked(self.dlp_controller.fixed_layer)
     fixed_layer_check.toggled.connect(self.dlp_controller.set_fixed_layer)
     incremental_amplitude_check = QCheckBox("Incremental Amplitude",
                                             self.__advanced_widget)
     incremental_amplitude_check.setChecked(
         self.dlp_controller.incremental_amplitude)
     incremental_amplitude_check.toggled.connect(
         self.dlp_controller.set_incremental_amplitude)
     starting_amplitude_label = QLabel("Starting Amplitude",
                                       self.__advanced_widget)
     starting_amplitude_edit = QSpinBox(self.__advanced_widget)
     starting_amplitude_edit.setMaximum(1000)
     starting_amplitude_edit.setMinimum(0)
     starting_amplitude_edit.setSingleStep(1)
     starting_amplitude_edit.setValue(
         self.dlp_controller.starting_incremental_amplitude)
     starting_amplitude_edit.valueChanged.connect(
         self.dlp_controller.set_starting_incremental_amplitude)
     amplitude_step_label = QLabel("Step Size", self.__advanced_widget)
     amplitude_step_edit = QSpinBox(self.__advanced_widget)
     amplitude_step_edit.setMaximum(1000)
     amplitude_step_edit.setMinimum(0)
     amplitude_step_edit.setSingleStep(1)
     amplitude_step_edit.setValue(
         self.dlp_controller.incremental_step_amplitude)
     amplitude_step_edit.valueChanged.connect(
         self.dlp_controller.set_incremental_step_amplitude)
     incremental_exposure_check = QCheckBox("Incremental Exposure",
                                            self.__advanced_widget)
     incremental_exposure_check.setChecked(
         self.dlp_controller.incremental_exposure)
     incremental_exposure_check.toggled.connect(
         self.dlp_controller.set_incremental_exposure)
     starting_exposure_label = QLabel("Starting Exposure",
                                      self.__advanced_widget)
     starting_exposure_edit = QDoubleSpinBox(self.__advanced_widget)
     starting_exposure_edit.setSuffix(str('ms'))
     starting_exposure_edit.setMaximum(100000)
     starting_exposure_edit.setMinimum(0)
     starting_exposure_edit.setDecimals(1)
     starting_exposure_edit.setSingleStep(0.1)
     starting_exposure_edit.valueChanged.connect(
         self.dlp_controller.set_starting_incremental_exposure)
     starting_exposure_edit.setValue(
         self.dlp_controller.starting_incremental_exposure)
     exposure_step_label = QLabel("Step Size", self.__advanced_widget)
     exposure_step_edit = QDoubleSpinBox(self.__advanced_widget)
     exposure_step_edit.setSuffix(str('ms'))
     exposure_step_edit.setMaximum(100000)
     exposure_step_edit.setMinimum(0)
     exposure_step_edit.setDecimals(1)
     exposure_step_edit.setSingleStep(0.1)
     exposure_step_edit.valueChanged.connect(
         self.dlp_controller.set_incremental_step_exposure)
     exposure_step_edit.setValue(
         self.dlp_controller.incremental_step_exposure)
     incremental_thickness_check = QCheckBox("Incremental Thickness",
                                             self.__advanced_widget)
     incremental_thickness_check.setChecked(
         self.dlp_controller.incremental_thickness)
     incremental_thickness_check.toggled.connect(
         self.dlp_controller.set_incremental_thickness)
     thickness_label = QLabel("Starting Thickness", self.__features_widget)
     self.starting_thickness_edit = MyDiscreteStepsSpinBox(
         self.dlp_controller.get_step_length_microns(),
         self.__features_widget)
     self.starting_thickness_edit.setSuffix(str('\u03BCm'))
     self.starting_thickness_edit.setMaximum(1000000)
     self.starting_thickness_edit.setMinimum(0)
     self.starting_thickness_edit.setDecimals(3)
     self.starting_thickness_edit.my_value_changed_signal.connect(
         self.dlp_controller.set_starting_incremental_thickness)
     self.starting_thickness_edit.setValue(
         self.dlp_controller.starting_incremental_thickness * 1000)
     thickness_step_label = QLabel("Step Size", self.__features_widget)
     self.thickness_step_edit = MyDiscreteStepsSpinBox(
         self.dlp_controller.get_step_length_microns(),
         self.__features_widget)
     self.thickness_step_edit.setSuffix(str('\u03BCm'))
     self.thickness_step_edit.setMaximum(1000000)
     self.thickness_step_edit.setMinimum(0)
     self.thickness_step_edit.setDecimals(3)
     self.thickness_step_edit.my_value_changed_signal.connect(
         self.dlp_controller.set_incremental_step_thickness)
     self.thickness_step_edit.setValue(
         self.dlp_controller.incremental_step_thickness * 1000)
     apply_grayscale_correction_check = QCheckBox("Grayscale Correction",
                                                  self.__advanced_widget)
     apply_grayscale_correction_check.setChecked(
         self.dlp_controller.grayscale_correction)
     apply_grayscale_correction_check.toggled.connect(
         self.dlp_controller.set_grayscale_correction)
     grayscale_parameters_widget = QWidget(self.__features_widget)
     a_parameter_label = QLabel("\u03B1", grayscale_parameters_widget)
     alpha_parameter_edit = QDoubleSpinBox(grayscale_parameters_widget)
     alpha_parameter_edit.setMaximum(1000)
     alpha_parameter_edit.setMinimum(0)
     alpha_parameter_edit.setDecimals(3)
     alpha_parameter_edit.setSingleStep(0.001)
     alpha_parameter_edit.valueChanged.connect(
         self.dlp_controller.set_grayscale_alpha)
     alpha_parameter_edit.setValue(self.dlp_controller.grayscale_alpha)
     beta_parameter_label = QLabel("\u03B2", grayscale_parameters_widget)
     beta_parameter_edit = QDoubleSpinBox(grayscale_parameters_widget)
     beta_parameter_edit.setMaximum(1000)
     beta_parameter_edit.setMinimum(0)
     beta_parameter_edit.setDecimals(3)
     beta_parameter_edit.setSingleStep(0.001)
     beta_parameter_edit.valueChanged.connect(
         self.dlp_controller.set_grayscale_beta)
     beta_parameter_edit.setValue(self.dlp_controller.grayscale_beta)
     gamma_parameter_label = QLabel("\u03B3", grayscale_parameters_widget)
     gamma_parameter_edit = QDoubleSpinBox(grayscale_parameters_widget)
     gamma_parameter_edit.setMaximum(1000)
     gamma_parameter_edit.setMinimum(0)
     gamma_parameter_edit.setDecimals(3)
     gamma_parameter_edit.setSingleStep(0.001)
     gamma_parameter_edit.valueChanged.connect(
         self.dlp_controller.set_grayscale_gamma)
     gamma_parameter_edit.setValue(self.dlp_controller.grayscale_gamma)
     grayscale_parameters_layout = QHBoxLayout(grayscale_parameters_widget)
     grayscale_parameters_layout.addWidget(a_parameter_label)
     grayscale_parameters_layout.addWidget(alpha_parameter_edit)
     grayscale_parameters_layout.addWidget(beta_parameter_label)
     grayscale_parameters_layout.addWidget(beta_parameter_edit)
     grayscale_parameters_layout.addWidget(gamma_parameter_label)
     grayscale_parameters_layout.addWidget(gamma_parameter_edit)
     grayscale_parameters_widget.setLayout(grayscale_parameters_layout)
     advanced_features_layout = QGridLayout(self.__advanced_widget)
     advanced_features_layout.addWidget(incremental_amplitude_check, 1, 0,
                                        1, 2)
     advanced_features_layout.addWidget(fixed_layer_check, 1, 3)
     advanced_features_layout.addWidget(starting_amplitude_label, 2, 0)
     advanced_features_layout.addWidget(starting_amplitude_edit, 2, 1)
     advanced_features_layout.addWidget(amplitude_step_label, 2, 2)
     advanced_features_layout.addWidget(amplitude_step_edit, 2, 3)
     advanced_features_layout.addWidget(incremental_exposure_check, 3, 0, 1,
                                        2)
     advanced_features_layout.addWidget(starting_exposure_label, 4, 0)
     advanced_features_layout.addWidget(starting_exposure_edit, 4, 1)
     advanced_features_layout.addWidget(exposure_step_label, 4, 2)
     advanced_features_layout.addWidget(exposure_step_edit, 4, 3)
     advanced_features_layout.addWidget(incremental_thickness_check, 5, 0,
                                        1, 2)
     advanced_features_layout.addWidget(thickness_label, 6, 0)
     advanced_features_layout.addWidget(self.starting_thickness_edit, 6, 1)
     advanced_features_layout.addWidget(thickness_step_label, 6, 2)
     advanced_features_layout.addWidget(self.thickness_step_edit, 6, 3)
     advanced_features_layout.addWidget(apply_grayscale_correction_check, 7,
                                        0, 1, 2)
     advanced_features_layout.addWidget(grayscale_parameters_widget, 8, 0,
                                        1, 4)
     self.__advanced_widget.setLayout(advanced_features_layout)
Exemple #14
0
 def __init_features_widget__(self, parent=None):
     self.__features_widget = QGroupBox("Features Layers Parameters",
                                        parent)
     # self.__features_widget.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
     thickness_label = QLabel("Layer Thickness", self.__features_widget)
     self.features_thickness_edit = MyDiscreteStepsSpinBox(
         self.dlp_controller.get_step_length_microns(),
         self.__features_widget)
     self.features_thickness_edit.setSuffix(str('\u03BCm'))
     self.features_thickness_edit.setMaximum(1000000)
     self.features_thickness_edit.setMinimum(0)
     self.features_thickness_edit.setDecimals(3)
     self.features_thickness_edit.my_value_changed_signal.connect(
         self.dlp_controller.set_features_thickness)
     self.features_thickness_edit.setValue(
         self.dlp_controller.features_thickness * 1000)
     exposure_label = QLabel("Exposure Time", self.__features_widget)
     exposure_edit = QDoubleSpinBox(self.__features_widget)
     exposure_edit.setSuffix(str('ms'))
     exposure_edit.setMaximum(10000000)
     exposure_edit.setMinimum(0)
     exposure_edit.setDecimals(1)
     exposure_edit.setSingleStep(0.1)
     exposure_edit.setValue(self.dlp_controller.features_exposure)
     exposure_edit.valueChanged.connect(
         self.dlp_controller.set_features_exposure_time)
     amplitude_label = QLabel("Light Amplitude", self.__features_widget)
     amplitude_edit = QSpinBox(self.__features_widget)
     amplitude_edit.setMaximum(1600)
     amplitude_edit.setMinimum(0)
     amplitude_edit.setSingleStep(1)
     amplitude_edit.setValue(self.dlp_controller.features_amplitude)
     amplitude_edit.valueChanged.connect(
         self.dlp_controller.set_features_amplitude)
     burn_layers_label = QLabel("Burn Layers", self.__features_widget)
     burn_layers_edit = QSpinBox(self.__features_widget)
     burn_layers_edit.setMaximum(1000)
     burn_layers_edit.setMinimum(0)
     burn_layers_edit.setSingleStep(1)
     burn_layers_edit.setValue(self.dlp_controller.features_burn_layers)
     burn_layers_edit.valueChanged.connect(
         self.dlp_controller.set_features_burning_layers)
     burn_exposure_label = QLabel("Burn Exposure", self.__features_widget)
     burn_exposure_edit = QDoubleSpinBox(self.__features_widget)
     burn_exposure_edit.setSuffix(str('ms'))
     burn_exposure_edit.setMaximum(100000)
     burn_exposure_edit.setMinimum(0)
     burn_exposure_edit.setDecimals(1)
     burn_exposure_edit.setSingleStep(0.1)
     burn_exposure_edit.setValue(self.dlp_controller.features_burn_exposure)
     burn_exposure_edit.valueChanged.connect(
         self.dlp_controller.set_features_burning_exposure_time)
     burn_amplitude_label = QLabel("Burn Amplitude", self.__features_widget)
     burn_amplitude_edit = QSpinBox(self.__features_widget)
     burn_amplitude_edit.setMaximum(1600)
     burn_amplitude_edit.setMinimum(0)
     burn_amplitude_edit.setSingleStep(1)
     burn_amplitude_edit.setValue(
         self.dlp_controller.features_burn_amplitude)
     burn_amplitude_edit.valueChanged.connect(
         self.dlp_controller.set_features_burning_amplitude)
     select_layers_button = QPushButton("Select Features Images")
     select_layers_button.clicked.connect(self.load_features_images)
     features_layout = QGridLayout(self.__features_widget)
     features_layout.addWidget(thickness_label, 1, 0)
     features_layout.addWidget(self.features_thickness_edit, 1, 1)
     features_layout.addWidget(exposure_label, 2, 0)
     features_layout.addWidget(exposure_edit, 2, 1)
     features_layout.addWidget(amplitude_label, 3, 0)
     features_layout.addWidget(amplitude_edit, 3, 1)
     features_layout.addWidget(burn_layers_label, 4, 0)
     features_layout.addWidget(burn_layers_edit, 4, 1)
     features_layout.addWidget(burn_exposure_label, 5, 0)
     features_layout.addWidget(burn_exposure_edit, 5, 1)
     features_layout.addWidget(burn_amplitude_label, 6, 0)
     features_layout.addWidget(burn_amplitude_edit, 6, 1)
     features_layout.addWidget(select_layers_button, 7, 0, 1, 2)
     self.__features_widget.setLayout(features_layout)
Exemple #15
0
 def __init_projector_widget__(self, parent=None):
     self.__projector_widget = QGroupBox("Projector Options", parent)
     # self.__projector_widget.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum)
     mirror_x = QCheckBox("Mirror X")
     mirror_x.setChecked(self.dlp_controller.is_horizontal_mirrored())
     mirror_x.toggled.connect(self.dlp_controller.set_horizontal_mirroring)
     mirror_y = QCheckBox("Mirror Y")
     mirror_y.setChecked(self.dlp_controller.is_vertical_mirrored())
     mirror_y.toggled.connect(self.dlp_controller.set_vertical_mirroring)
     start_projector_button = QPushButton("Start Projector",
                                          self.__projector_widget)
     start_projector_button.clicked.connect(
         self.dlp_controller.start_projector)
     project_pattern_button = QPushButton("Project Pattern",
                                          self.__projector_widget)
     project_pattern_button.clicked.connect(
         self.dlp_controller.project_calibration_pattern)
     print_position_button = QPushButton("Print Position",
                                         self.__projector_widget)
     print_position_button.clicked.connect(
         self.dlp_controller.print_motor_position)
     home_projector_button = QPushButton("Home Projector",
                                         self.__projector_widget)
     home_projector_button.clicked.connect(
         self.dlp_controller.home_projector)
     move_projector_button = QPushButton("Move Projector",
                                         self.__projector_widget)
     move_projector_button.clicked.connect(
         self.dlp_controller.move_projector)
     move_projector_edit = QDoubleSpinBox(self.__projector_widget)
     move_projector_edit.setSuffix("mm")
     move_projector_edit.setMaximum(10000)
     move_projector_edit.setMinimum(-10000)
     move_projector_edit.setDecimals(3)
     move_projector_edit.setSingleStep(0.001)
     move_projector_edit.valueChanged.connect(
         self.dlp_controller.update_projector_distance)
     set_amplitude_button = QPushButton("Set Projector Amplitude",
                                        self.__projector_widget)
     set_amplitude_button.clicked.connect(
         self.dlp_controller.set_projector_amplitude)
     set_amplitude_edit = QSpinBox(self.__projector_widget)
     set_amplitude_edit.setMaximum(1000)
     set_amplitude_edit.setMinimum(0)
     set_amplitude_edit.setValue(self.dlp_controller.projector_amplitude)
     set_amplitude_edit.valueChanged.connect(
         self.dlp_controller.update_projector_amplitude)
     lock_unlock_projector_button = QPushButton("Lock/Unlock Projector",
                                                self.__projector_widget)
     lock_unlock_projector_button.clicked.connect(
         self.dlp_controller.lock_unlock_projector)
     projector_layout = QGridLayout(self.__projector_widget)
     # projector_layout.addWidget(projector_label, 0, 0)
     projector_layout.addWidget(mirror_x, 0, 1)
     projector_layout.addWidget(mirror_y, 0, 2)
     projector_layout.addWidget(start_projector_button, 1, 0, 1, 1)
     projector_layout.addWidget(project_pattern_button, 1, 1, 1, 1)
     projector_layout.addWidget(print_position_button, 1, 2, 1, 1)
     projector_layout.addWidget(home_projector_button, 2, 0, 1, 1)
     projector_layout.addWidget(move_projector_button, 2, 1, 1, 1)
     projector_layout.addWidget(move_projector_edit, 2, 2)
     projector_layout.addWidget(set_amplitude_button, 3, 0, 1, 1)
     projector_layout.addWidget(set_amplitude_edit, 3, 1)
     projector_layout.addWidget(lock_unlock_projector_button, 3, 2, 1, 1)
     self.__projector_widget.setLayout(projector_layout)
Exemple #16
0
class Design(QDialog):
    def __init__(self):
        super(spur_design, self).__init__()
        self.createForm()
        self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok
                                          | QDialogButtonBox.Cancel)
        self.buttonBox.accepted.connect(self.submit)
        self.buttonBox.rejected.connect(self.reject)
        mainLayout = QVBoxLayout()
        mainLayout.addWidget(self.formGroupBox)
        mainLayout.addWidget(self.buttonBox)
        self.setLayout(mainLayout)
        self.setWindowTitle("OctoCAD\N{COPYRIGHT SIGN}")
        self.setGeometry(0, 0, 600, 400)
        self.setIcon()
        self.centering()
        self.show()

    def setIcon(self):
        icon = QIcon(
            "/home/ubuntu/OctoCAD/icons/logo_transparent_enlarged.png")
        self.setWindowIcon(icon)

    def centering(self):
        window = self.frameGeometry()
        center = QDesktopWidget().availableGeometry().center()
        window.moveCenter(center)
        self.move(window.topLeft())

    def createForm(self):
        self.formGroupBox = QGroupBox("Design Configuration")
        self.layout = QFormLayout()
        self.Sutp = QDoubleSpinBox()
        self.Sutp.setRange(1, 10000)
        self.layout.addRow(
            QLabel("Enter ultimate tensile strength of pinion N.mm^-2"),
            self.Sutp)
        self.Sutg = QDoubleSpinBox()
        self.Sutg.setRange(1, 10000)
        self.layout.addRow(
            QLabel("Enter ultimate tensile strength of gear N.mm^-2"),
            self.Sutg)
        self.Ep = QDoubleSpinBox()
        self.Ep.setRange(1, 10000000)
        self.layout.addRow(
            QLabel("Enter modulus of elasticity of pinion N.mm^-2"), self.Ep)
        self.Eg = QDoubleSpinBox()
        self.Eg.setRange(1, 10000000)
        self.layout.addRow(
            QLabel("Enter modulus of elasticity of gear N.mm^-2"), self.Eg)
        self.grade = QComboBox()
        self.grade.addItem("1")
        self.grade.addItem("2")
        self.grade.addItem("3")
        self.grade.addItem("4")
        self.grade.addItem("5")
        self.grade.addItem("6")
        self.grade.addItem("7")
        self.grade.addItem("8")
        self.grade.addItem("9")
        self.grade.addItem("10")
        self.grade.addItem("11")
        self.grade.addItem("12")
        self.layout.addRow(QLabel("Select grade of gear pair"), self.grade)
        self.y = QComboBox()
        self.y.addItem("14.5 degree full depth involute tooth")
        self.y.addItem("20 degree full depth involute tooth")
        self.y.addItem("20 degree stub involute tooth")
        self.layout.addRow(QLabel("Select type of gear pair"), self.y)
        self.zp = QSpinBox()
        self.zp.setRange(14, 300)
        self.layout.addRow(QLabel("Enter number of pinion teeth"), self.zp)
        self.zg = QSpinBox()
        self.zg.setRange(14, 300)
        self.layout.addRow(QLabel("Enter number of gear teeth"), self.zg)
        self.P = QDoubleSpinBox()
        self.P.setRange(1, 1000000)
        self.layout.addRow(QLabel("Enter power transmitted by gear pair W"),
                           self.P)
        self.Np = QDoubleSpinBox()
        self.Np.setRange(1, 10000)
        self.layout.addRow(QLabel("Enter speed of pinion rpm"), self.Np)
        self.Q = QComboBox()
        self.Q.addItem("Internal gearing")
        self.Q.addItem("External gearing")
        self.layout.addRow(QLabel("Enter type of gearing"), self.Q)
        self.FOSr = QDoubleSpinBox()
        self.FOSr.setRange(1, 10)
        self.layout.addRow(QLabel("Enter factor of safety"), self.FOSr)
        self.cs = QDoubleSpinBox()
        self.layout.addRow(QLabel("Enter service factor"), self.cs)
        self.cs.setRange(1, 10)
        self.formGroupBox.setLayout(self.layout)

    def submit(self):
        os.makedirs("/home/ubuntu/.OctoCAD/spur-gear", exist_ok=True)
        with open("/home/ubuntu/.OctoCAD/spur-gear/user_input_design.txt",
                  "w") as user_input_design_f:
            user_input_design_f.write("# name: Eg\n# type: scalar\n")
            user_input_design_f.write(self.Eg.text() + "\n\n\n")
            user_input_design_f.write("# name: Ep\n# type: scalar\n")
            user_input_design_f.write(self.Ep.text() + "\n\n\n")
            user_input_design_f.write("# name: FOSr\n# type: scalar\n")
            user_input_design_f.write(self.FOSr.text() + "\n\n\n")
            user_input_design_f.write("# name: Np\n# type: scalar\n")
            user_input_design_f.write(self.Np.text() + "\n\n\n")
            user_input_design_f.write("# name: P\n# type: scalar\n")
            user_input_design_f.write(self.P.text() + "\n\n\n")
            user_input_design_f.write("# name: Q\n# type: scalar\n")
            if self.Q.currentText() == "Internal gearing":
                user_input_design_f.write("1" + "\n\n\n")
            if self.Q.currentText() == "External gearing":
                user_input_design_f.write("2" + "\n\n\n")
            user_input_design_f.write("# name: Sutg\n# type: scalar\n")
            user_input_design_f.write(self.Sutg.text() + "\n\n\n")
            user_input_design_f.write("# name: Sutp\n# type: scalar\n")
            user_input_design_f.write(self.Sutp.text() + "\n\n\n")
            user_input_design_f.write("# name: cs\n# type: scalar\n")
            user_input_design_f.write(self.cs.text() + "\n\n\n")
            user_input_design_f.write("# name: grade\n# type: scalar\n")
            user_input_design_f.write(self.grade.currentText() + "\n\n\n")
            user_input_design_f.write("# name: y\n# type: scalar\n")
            if self.y.currentText() == "14.5 degree full depth involute tooth":
                user_input_design_f.write("1" + "\n\n\n")
            if self.y.currentText() == "20 degree full depth involute tooth":
                user_input_design_f.write("2" + "\n\n\n")
            if self.y.currentText() == "20 degree stub involute tooth":
                user_input_design_f.write("3" + "\n\n\n")
            user_input_design_f.write("# name: zg\n# type: scalar\n")
            user_input_design_f.write(self.zg.text() + "\n\n\n")
            user_input_design_f.write("# name: zp\n# type: scalar\n")
            user_input_design_f.write(self.zp.text() + "\n\n\n")
        os.system("octave /home/ubuntu/OctoCAD/bis/gear/spur-gear/io.m")
        self.createResult()

    def createResult(self):
        with open("/home/ubuntu/.OctoCAD/spur-gear/result.txt",
                  "r") as result_f:
            str_Fd = result_f.readline().split("=")[1].rstrip("\n")
            str_Fap = result_f.readline().split("=")[1].rstrip("\n")
            str_Fag = result_f.readline().split("=")[1].rstrip("\n")
            str_Fw = result_f.readline().split("=")[1].rstrip("\n")
            str_BHN = result_f.readline().split("=")[1].rstrip("\n")
            str_m = result_f.readline().split("=")[1].rstrip("\n")
            str_FOS = result_f.readline().split("=")[1].rstrip("\n")
            str_zp = result_f.readline().split("=")[1].rstrip("\n")
            str_zg = result_f.readline().split("=")[1].rstrip("\n")
            str_result = "Module of gear pair is " + str_m + " mm\n\nEffective load on the gear pair is " + str_Fd + " N\n\nBending load capacity of pinion is " + str_Fap + " N\n\nBending load capacity of gear " + str_Fag + " N\n\nWear load capacity of gear pair is " + str_Fw + " N\n\nSurface hardness of the gear pair is " + str_BHN + " BHN\n\nAvailabe factor of safety is " + str_FOS + "\n\n"
            result_box = QMessageBox()
            result_box.setWindowTitle("Design of gear pair")
            result_box.setText(str_result)
            result_box.exec_()
            obj_QApplication.exit()
class AcquistoForm(QDialog):
    '''
    Widget per l'inserimento di un acquisto immediato.
    '''
    def __init__(self, conn):
        '''
        Parameters:
            conn : connection
                Connection to the database.
        '''
        super().__init__()
        self.setWindowTitle('Aggiungi Acquisto')
        self.setWindowFlag(QtCore.Qt.WindowContextHelpButtonHint, False)

        self.conn = conn
        self.cursor = conn.cursor()

        self.books = dict()
        self.books_qt = dict()

        self.gen_layout = QVBoxLayout()

        self.form_layout = QFormLayout()
        self.form_layout.setRowWrapPolicy(QFormLayout.WrapLongRows)

        # Widgets
        self.client_field = QLineEdit()
        self.form_layout.addRow('Numero Cliente (facoltativo): ',
                                self.client_field)

        self.dip_field = QLineEdit()
        self.form_layout.addRow('Dipendente (CF): ', self.dip_field)

        self.date_picker = QDateEdit(QDate.currentDate())
        self.date_picker.setDisplayFormat("MM/dd/yyyy")
        self.date_picker.setCalendarPopup(True)
        self.form_layout.addRow('Data (mm/gg/aaaa): ', self.date_picker)

        self.importo_field = QDoubleSpinBox()
        self.importo_field.setMaximum(999999999.99)
        self.form_layout.addRow('Importo: ', self.importo_field)

        self.ins_layout = QHBoxLayout()
        self.libro_field = QLineEdit()
        self.quantita_field = QSpinBox()
        self.quantita_field.setMinimum(1)
        self.libro_button = QPushButton('Aggiungi')
        self.libro_button.clicked.connect(self.aggiungi_libro)
        self.ins_layout.addWidget(QLabel('Libro (ISBN): '))
        self.ins_layout.addWidget(self.libro_field)
        self.ins_layout.addWidget(QLabel('Quantità: '))
        self.ins_layout.addWidget(self.quantita_field)
        self.ins_layout.addWidget(self.libro_button)

        self.labels = ['ISBN', 'Quantità', '']
        self.table = QTableWidget(0, 3)
        self.table.setHorizontalHeaderLabels(self.labels)
        self.table.horizontalHeader().setSectionResizeMode(
            0, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            1, QHeaderView.Stretch)
        self.table.horizontalHeader().setSectionResizeMode(
            2, QHeaderView.ResizeToContents)

        self.confirm_button = QPushButton('Conferma')
        self.confirm_button.clicked.connect(self.post_acquisto)

        self.gen_layout.addLayout(self.form_layout)
        self.gen_layout.addLayout(self.ins_layout)
        self.gen_layout.addWidget(self.table)
        self.gen_layout.addWidget(self.confirm_button)
        self.setLayout(self.gen_layout)

    def aggiungi_libro(self):
        self.books[self.libro_field.text()] = self.quantita_field.value()
        self.update_table()

    def remove_libro(self, book):
        self.books.pop(book, None)
        self.update_table()

    def update_table(self):
        self.table.clearContents()
        while self.table.rowCount() > 0:
            self.table.removeRow(0)
        for book in self.books.keys():
            row = self.table.rowCount()
            button = QPushButton('Rimuovi')
            button.clicked.connect(lambda: self.remove_libro(book))
            self.table.insertRow(row)
            self.table.setItem(row, 0, QTableWidgetItem(book))
            self.table.setItem(row, 1, QTableWidgetItem(str(self.books[book])))
            self.table.setCellWidget(row, 2, button)

    def verif_qty(self):
        '''
        Shows error messages based on the validity of inserted books, and
        returns False, or returns True if all the books are ok to sell right now.
        '''
        if len(self.books.items()) == 0:
            self._show_error('Non ci sono libri nell\'acquisto')
            return 1
        for book, qty in self.books.items():
            self.cursor.execute(FIND_QUANTITA, (book, ))
            result = self.cursor.fetchall()
            if not result:
                self._show_error('\'{}\' non è un libro valido.'.format(book))
                return 2
            stored = result[0][0]
            if stored < qty:
                return self.__show_are_you_sure(
                    'L\'acquisto richiede {} libri {}, ma ne sono presenti solo {}.\nNon sarà possibile sottrarre i libri acquistati.\nVuoi proseguire ugualmente?'
                    .format(qty, book, stored))
        return 0

    def verif_client_dip(self):
        '''
        Returns false and displays and error message if cliente and dipendente are
        not valid tuples in the database, returns true if they are ok
        '''
        cliente = self.client_field.text()
        if cliente:
            if not cliente.isdigit():
                self._show_error('Il codice del Cliente deve essere numerico.')
                return 1
            self.cursor.execute(FIND_CLIENTE, (cliente, ))
            result = self.cursor.fetchall()
            if not result or not result[0][0]:
                self._show_error('Cliente {} non esiste.'.format(cliente))
                return 2

        dipendente = self.dip_field.text()
        if not dipendente:
            self._show_error('Il Dipendente non può essere vuoto.')
            return 3
        self.cursor.execute(FIND_DIPENDENTE, (dipendente, ))
        result = self.cursor.fetchall()
        if not result or not result[0][0]:
            self._show_error('Dipendente {} non esiste.'.format(dipendente))
            return 4
        return 0

    def post_acquisto(self):
        if self.verif_client_dip():
            return
        should_show = self.verif_qty()
        if should_show > 0:
            return
        cliente = self.client_field.text().strip() if self.client_field.text(
        ).strip() else None
        importo = self.importo_field.value()
        self.cursor.execute(
            INSERT_ACQUISTO,
            (self.date_picker.date().toString('MM/dd/yyyy'),
             self.importo_field.value(), self.dip_field.text()))
        new_id = self.cursor.fetchall()[0][0]
        self.cursor.execute(INSERT_IMMEDIATO, (new_id, cliente))
        for book in self.books.keys():
            self.cursor.execute(INSERT_COMPRENDE,
                                (new_id, book, self.books[book]))
        self.conn.commit()
        if should_show == 0: self._show_confirm()
        self.accept()

    def __show_are_you_sure(self, msg=''):
        dialog = _AreYouSureDialog(msg)
        dialog.setWindowTitle('ATTENZIONE')
        result = dialog.exec_()
        return -1 if result == QDialog.Accepted else 3

    def _show_confirm(self):
        dialog = _ScalaAcquistiDialog(self.books, self.conn)
        dialog.setWindowTitle('Rimozione libri')
        dialog.exec_()

    def _show_error(self, msg=''):
        dialog = QMessageBox()
        dialog.setWindowTitle('ERRORE')
        dialog.setText(msg)
        dialog.exec_()
Exemple #18
0
 def createForm(self):
     self.formGroupBox = QGroupBox("Design Configuration")
     self.layout = QFormLayout()
     self.Sutp = QDoubleSpinBox()
     self.Sutp.setRange(1, 10000)
     self.layout.addRow(
         QLabel("Enter ultimate tensile strength of pinion N.mm^-2"),
         self.Sutp)
     self.Sutg = QDoubleSpinBox()
     self.Sutg.setRange(1, 10000)
     self.layout.addRow(
         QLabel("Enter ultimate tensile strength of gear N.mm^-2"),
         self.Sutg)
     self.Ep = QDoubleSpinBox()
     self.Ep.setRange(1, 10000000)
     self.layout.addRow(
         QLabel("Enter modulus of elasticity of pinion N.mm^-2"), self.Ep)
     self.Eg = QDoubleSpinBox()
     self.Eg.setRange(1, 10000000)
     self.layout.addRow(
         QLabel("Enter modulus of elasticity of gear N.mm^-2"), self.Eg)
     self.grade = QComboBox()
     self.grade.addItem("1")
     self.grade.addItem("2")
     self.grade.addItem("3")
     self.grade.addItem("4")
     self.grade.addItem("5")
     self.grade.addItem("6")
     self.grade.addItem("7")
     self.grade.addItem("8")
     self.grade.addItem("9")
     self.grade.addItem("10")
     self.grade.addItem("11")
     self.grade.addItem("12")
     self.layout.addRow(QLabel("Select grade of gear pair"), self.grade)
     self.y = QComboBox()
     self.y.addItem("14.5 degree full depth involute tooth")
     self.y.addItem("20 degree full depth involute tooth")
     self.y.addItem("20 degree stub involute tooth")
     self.layout.addRow(QLabel("Select type of gear pair"), self.y)
     self.zp = QSpinBox()
     self.zp.setRange(14, 300)
     self.layout.addRow(QLabel("Enter number of pinion teeth"), self.zp)
     self.zg = QSpinBox()
     self.zg.setRange(14, 300)
     self.layout.addRow(QLabel("Enter number of gear teeth"), self.zg)
     self.P = QDoubleSpinBox()
     self.P.setRange(1, 1000000)
     self.layout.addRow(QLabel("Enter power transmitted by gear pair W"),
                        self.P)
     self.Np = QDoubleSpinBox()
     self.Np.setRange(1, 10000)
     self.layout.addRow(QLabel("Enter speed of pinion rpm"), self.Np)
     self.Q = QComboBox()
     self.Q.addItem("Internal gearing")
     self.Q.addItem("External gearing")
     self.layout.addRow(QLabel("Enter type of gearing"), self.Q)
     self.FOSr = QDoubleSpinBox()
     self.FOSr.setRange(1, 10)
     self.layout.addRow(QLabel("Enter factor of safety"), self.FOSr)
     self.cs = QDoubleSpinBox()
     self.layout.addRow(QLabel("Enter service factor"), self.cs)
     self.cs.setRange(1, 10)
     self.formGroupBox.setLayout(self.layout)
Exemple #19
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()
Exemple #20
0
class Canvas (QWidget):
    def __init__(self):
        QWidget.__init__(self)

        self.file = "mug.webp"

        self.__img = cv2.imread(self.file)
        self.__mask = np.zeros(1)
        self.original = cv2.imread(self.file)
        self.__thirdChannelMask = np.dstack((self.__mask, self.__mask, self.__mask))

        self.__nseg = 1
        self.__sig = 1
        self.__comp = 1

        self.nSlider = QSlider(orientation=Qt.Horizontal)
        self.sigSlider = QSlider(orientation=Qt.Horizontal)
        self.thicSlider = QSlider(orientation=Qt.Horizontal)

        self.resize_spinbox = QSpinBox(self)
        self.resize_spinbox.setRange(1, 100)
        self.resize_spinbox.setValue(100)
        self.resize_spinbox.setSuffix(" %")

        self.double_spin_width = QDoubleSpinBox(self)
        self.double_spin_width.setSuffix(" px")
        self.double_spin_width.setValue(0)
        self.double_spin_width.setRange(1, 2000)

        self.double_spin_height = QDoubleSpinBox(self)
        self.double_spin_height.setSuffix(" px")
        self.double_spin_height.setValue(0)
        self.double_spin_height.setRange(1, 2000)

        self.zeroModeCheck = QCheckBox("Usar SLIC0")

        self.__highlightcolor = QColor(255, 255, 255)

        self.__transparency = 0.5

        self.__AllColors = [self.__highlightcolor.toTuple()[:3]]

        nLabel = QLabel("Numero de segmentos:")
        sigLabel = QLabel("Sigma:")
        thicLabel = QLabel("Compactação:")
        resizeLabel = QLabel("Fator de resize da image:")
        makssizeLabel = QLabel("Dimensão da mascara de saída:")

        self.__label = QLabel()

        nLabel.setToolTip("O número aproximado de labels da imagem segmentada")
        sigLabel.setToolTip("A largura da Gaussiana")
        thicLabel.setToolTip("Equilibra a proximidade das cores e a proximidade do espaço, maiores valores tornam os Superpixels mais quadrados")

        self.nSlider.setMinimum(1)
        self.nSlider.setMaximum(100)

        self.sigSlider.setMinimum(1)
        self.sigSlider.setMaximum(100)

        self.thicSlider.setMinimum(1)
        self.thicSlider.setMaximum(100)

        glayout1 = QGridLayout()
        glayout1.addWidget(nLabel, 0, 0)
        glayout1.addWidget(self.nSlider, 0, 1)
        glayout1.addWidget(sigLabel, 1, 0)
        glayout1.addWidget(self.sigSlider, 1, 1)
        glayout1.addWidget(thicLabel, 2, 0)
        glayout1.addWidget(self.thicSlider, 2, 1)

        glayout2 = QGridLayout()
        glayout2.addWidget(resizeLabel, 0, 0)
        glayout2.addWidget(self.resize_spinbox, 0, 1)
        glayout2.addWidget(self.zeroModeCheck, 0, 2)
        glayout2.addWidget(makssizeLabel, 1, 0)
        glayout2.addWidget(self.double_spin_width, 1, 1)
        glayout2.addWidget(self.double_spin_height, 1, 2)

        glayout2.setColumnStretch(3, 1)

        self.__label.setAlignment(Qt.AlignLeft | Qt.AlignTop)

        mainlayout = QVBoxLayout()
        mainlayout.addLayout(glayout1)
        mainlayout.addLayout(glayout2)
        mainlayout.addStretch(1)
        mainlayout.addWidget(self.__label)
        mainlayout.addStretch(1)
        mainlayout.setAlignment(Qt.AlignCenter)
        self.setLayout(mainlayout)

        self.nSlider.sliderReleased.connect(self.onNsegChange)
        self.sigSlider.sliderReleased.connect(self.onSigChange)
        self.thicSlider.sliderReleased.connect(self.onCompChange)

        self.__label.mousePressEvent = self.Highlight

        self.resize_spinbox.valueChanged.connect(self.Resize)

        self.open_image(self.__img)

    def getBackground(self):
        mask = self.__thirdChannelMask.copy()
        mask_r = mask[:, :, 2]
        mask_g = mask[:, :, 1]
        mask_b = mask[:, :, 0]

        offImage = list()
        for color in self.__AllColors:
            b_off = mask_b != color[2]
            g_off = mask_g != color[1]
            r_off = mask_r != color[0]
            aux = np.logical_and(b_off, g_off)
            offImage.append(np.logical_and(aux, r_off))

        final = offImage[0]
        for cut in offImage:
            final = np.logical_or(final, cut)

        return final

    def changeImage(self):
        self.__mask = slic(self.__img, n_segments=self.__nseg, compactness=self.__comp, sigma=self.__sig, convert2lab=True, slic_zero=self.zeroModeCheck.isChecked())

        mask = self.__mask.copy()
        mask = np.dstack((mask, mask, mask))
        mask = img_as_ubyte(mask)

        self.__thirdChannelMask = mask
        img = cv2.addWeighted(self.__img, 1, mask, 0.5, 0)
        marc_img = mark_boundaries(img, self.__mask)
        self.open_image(marc_img)

    def load_image(self):
        self.__img = cv2.imread(self.file)
        self.original = self.__img
        self.double_spin_width.setValue(self.__img.shape[1])
        self.double_spin_height.setValue(self.__img.shape[0])

        val = self.resize_spinbox.value()
        newDim = int(self.__img.shape[1]*val/100), int(self.__img.shape[0]*val/100)

        self.__img = cv2.resize(self.__img, newDim)

        self.open_image(self.__img)

    def open_image(self, img):
        if img.shape[2] == 4:
            qformat = QImage.Format_RGBA8888
        else:
            qformat = QImage.Format_RGB888

        copy = img_as_ubyte(img)
        qimg = QImage(copy.data, copy.shape[1], copy.shape[0], copy.strides[0], qformat).rgbSwapped()
        pixmap = QPixmap.fromImage(qimg)

        self.__label.setPixmap(pixmap)
        self.__label.adjustSize()

    @Slot()
    def onNsegChange(self):
        self.__nseg = self.nSlider.value()
        self.changeImage()

    @Slot()
    def onSigChange(self):
        self.__sig = self.sigSlider.value()
        self.changeImage()

    @Slot()
    def onCompChange(self):
        self.__comp = self.thicSlider.value()
        self.changeImage()

    @Slot()
    def onFileOpen(self):
        self.thicSlider.setValue(1)
        self.nSlider.setValue(1)
        self.sigSlider.setValue(1)
        diag = QFileDialog()
        file = diag.getOpenFileName()[0]
        if file != "":
            self.file = file
            self.load_image()

    @Slot()
    def onSaveFile(self):
        diag = QFileDialog()
        file = diag.getSaveFileName()[0]
        if self.file != "":
            self.__label.pixmap().save(file)

    @Slot()
    def onSaveMask(self):
        diag = QFileDialog()
        file = diag.getSaveFileName()[0]
        final_img = cv2.resize(self.__mask, (self.double_spin_width.value(), self.double_spin_height.value()))

        if file != "":
            cv2.imwrite(file, final_img)

    @Slot()
    def Highlight(self, e):
        if e.x() < 0 or e.x() > self.__img.shape[1] or e.y() < 0 or e.y() > self.__img.shape[0]:
            return

        self.__mask = flood_fill(self.__mask, (e.y(), e.x()), 255)

        self.__thirdChannelMask[:, :, 2] = flood_fill(self.__thirdChannelMask[:, :, 2], (e.y(), e.x()), self.__highlightcolor.red())
        self.__thirdChannelMask[:, :, 1] = flood_fill(self.__thirdChannelMask[:, :, 1], (e.y(), e.x()), self.__highlightcolor.green())
        self.__thirdChannelMask[:, :, 0] = flood_fill(self.__thirdChannelMask[:, :, 0], (e.y(), e.x()), self.__highlightcolor.blue())

        img = cv2.addWeighted(self.__img, 1, self.__thirdChannelMask, self.__transparency, 0)
        marc_img = mark_boundaries(img, self.__mask)
        self.open_image(marc_img)


    @Slot()
    def exportBinary(self):
        diag = QFileDialog()
        file = diag.getSaveFileName()[0]
        mask = self.__thirdChannelMask.copy()
        final = self.getBackground()
        b = mask[:, :, 0]
        g = mask[:, :, 1]
        r = mask[:, :, 2]
        b[final] = 0
        g[final] = 0
        r[final] = 0

        final_img = cv2.resize(mask, (int(self.double_spin_width.value()), int(self.double_spin_height.value())))
        if file != "":
            cv2.imwrite(file, final_img)

    @Slot()
    def onRemoveBackgroud(self):
        box = QMessageBox()
        box.setText("Selecione a cor do background")
        box.setIcon(QMessageBox.Information)
        box.exec()
        diag = QColorDialog()
        backColor = diag.getColor()

        final = self.getBackground()
        b = self.__img[:, :, 0]
        g = self.__img[:, :, 1]
        r = self.__img[:, :, 2]
        b[final] = backColor.blue()
        g[final] = backColor.green()
        r[final] = backColor.red()

        self.open_image(self.__img)

    @Slot()
    def Resize(self):
        val = self.resize_spinbox.value()
        newDim = int(self.original.shape[1] * val / 100), int(self.original.shape[0] * val / 100)
        self.__img = cv2.resize(self.original, newDim)
        self.open_image(self.__img)

    @Slot()
    def setHighlightColor(self, color):
        self.__highlightcolor = color

    @Slot()
    def getAllColors(self, colors):
        self.__AllColors = colors

    @Slot()
    def setTran(self, value):
        self.__transparency = 1- value/100

    @Slot()
    def onUndo(self):
        self.thicSlider.setValue(1)
        self.nSlider.setValue(1)
        self.sigSlider.setValue(1)
        self.onNsegChange()
        self.onSigChange()
        self.onCompChange()
        self.__img = self.original
        self.open_image(self.__img)
def createDoubleSpinBox():
    spinbox = QDoubleSpinBox()
    spinbox.setDecimals(3)
    spinbox.setValue(0.000)
    spinbox.setAlignment(Qt.AlignCenter)
    return spinbox
Exemple #22
0
    def __init__(self):
        QWidget.__init__(self)

        self.file = "mug.webp"

        self.__img = cv2.imread(self.file)
        self.__mask = np.zeros(1)
        self.original = cv2.imread(self.file)
        self.__thirdChannelMask = np.dstack((self.__mask, self.__mask, self.__mask))

        self.__nseg = 1
        self.__sig = 1
        self.__comp = 1

        self.nSlider = QSlider(orientation=Qt.Horizontal)
        self.sigSlider = QSlider(orientation=Qt.Horizontal)
        self.thicSlider = QSlider(orientation=Qt.Horizontal)

        self.resize_spinbox = QSpinBox(self)
        self.resize_spinbox.setRange(1, 100)
        self.resize_spinbox.setValue(100)
        self.resize_spinbox.setSuffix(" %")

        self.double_spin_width = QDoubleSpinBox(self)
        self.double_spin_width.setSuffix(" px")
        self.double_spin_width.setValue(0)
        self.double_spin_width.setRange(1, 2000)

        self.double_spin_height = QDoubleSpinBox(self)
        self.double_spin_height.setSuffix(" px")
        self.double_spin_height.setValue(0)
        self.double_spin_height.setRange(1, 2000)

        self.zeroModeCheck = QCheckBox("Usar SLIC0")

        self.__highlightcolor = QColor(255, 255, 255)

        self.__transparency = 0.5

        self.__AllColors = [self.__highlightcolor.toTuple()[:3]]

        nLabel = QLabel("Numero de segmentos:")
        sigLabel = QLabel("Sigma:")
        thicLabel = QLabel("Compactação:")
        resizeLabel = QLabel("Fator de resize da image:")
        makssizeLabel = QLabel("Dimensão da mascara de saída:")

        self.__label = QLabel()

        nLabel.setToolTip("O número aproximado de labels da imagem segmentada")
        sigLabel.setToolTip("A largura da Gaussiana")
        thicLabel.setToolTip("Equilibra a proximidade das cores e a proximidade do espaço, maiores valores tornam os Superpixels mais quadrados")

        self.nSlider.setMinimum(1)
        self.nSlider.setMaximum(100)

        self.sigSlider.setMinimum(1)
        self.sigSlider.setMaximum(100)

        self.thicSlider.setMinimum(1)
        self.thicSlider.setMaximum(100)

        glayout1 = QGridLayout()
        glayout1.addWidget(nLabel, 0, 0)
        glayout1.addWidget(self.nSlider, 0, 1)
        glayout1.addWidget(sigLabel, 1, 0)
        glayout1.addWidget(self.sigSlider, 1, 1)
        glayout1.addWidget(thicLabel, 2, 0)
        glayout1.addWidget(self.thicSlider, 2, 1)

        glayout2 = QGridLayout()
        glayout2.addWidget(resizeLabel, 0, 0)
        glayout2.addWidget(self.resize_spinbox, 0, 1)
        glayout2.addWidget(self.zeroModeCheck, 0, 2)
        glayout2.addWidget(makssizeLabel, 1, 0)
        glayout2.addWidget(self.double_spin_width, 1, 1)
        glayout2.addWidget(self.double_spin_height, 1, 2)

        glayout2.setColumnStretch(3, 1)

        self.__label.setAlignment(Qt.AlignLeft | Qt.AlignTop)

        mainlayout = QVBoxLayout()
        mainlayout.addLayout(glayout1)
        mainlayout.addLayout(glayout2)
        mainlayout.addStretch(1)
        mainlayout.addWidget(self.__label)
        mainlayout.addStretch(1)
        mainlayout.setAlignment(Qt.AlignCenter)
        self.setLayout(mainlayout)

        self.nSlider.sliderReleased.connect(self.onNsegChange)
        self.sigSlider.sliderReleased.connect(self.onSigChange)
        self.thicSlider.sliderReleased.connect(self.onCompChange)

        self.__label.mousePressEvent = self.Highlight

        self.resize_spinbox.valueChanged.connect(self.Resize)

        self.open_image(self.__img)
Exemple #23
0
class NGL_HKLViewer(QWidget):
    def __init__(self, parent=None):
        super(NGL_HKLViewer, self).__init__(parent)

        self.verbose = 0
        self.UseOSbrowser = False
        self.jscriptfname = ""
        self.devmode = False
        for e in sys.argv:
            if "verbose" in e:
                self.verbose = e.split("verbose=")[1]
            if "UseOSbrowser" in e:
                self.UseOSbrowser = e.split("UseOSbrowser=")[1]
            if "jscriptfname" in e:
                self.jscriptfname = e.split("jscriptfname=")[1]
            if "devmode" in e:
                self.devmode = True

        self.zmq_context = None
        self.bufsize = 20000

        self.originalPalette = QApplication.palette()

        self.openFileNameButton = QPushButton("Load reflection file")
        self.openFileNameButton.setDefault(True)
        self.openFileNameButton.clicked.connect(self.OpenReflectionsFile)

        self.debugbutton = QPushButton("Debug")
        self.debugbutton.clicked.connect(self.DebugInteractively)

        self.settingsbtn = QPushButton("Settings")
        self.settingsbtn.clicked.connect(self.SettingsDialog)

        self.mousemoveslider = QSlider(Qt.Horizontal)
        self.mousemoveslider.setMinimum(0)
        self.mousemoveslider.setMaximum(300)
        self.mousemoveslider.setValue(0)
        self.mousemoveslider.sliderReleased.connect(
            self.onFinalMouseSensitivity)
        self.mousemoveslider.valueChanged.connect(self.onMouseSensitivity)
        self.mousesensitxtbox = QLineEdit('')
        self.mousesensitxtbox.setReadOnly(True)
        self.fontspinBox = QDoubleSpinBox()
        self.fontspinBox.setSingleStep(1)
        self.fontspinBox.setRange(4, 50)
        self.font = QFont()
        self.font.setFamily(self.font.defaultFamily())
        self.fontspinBox.setValue(self.font.pointSize())
        #self.fontspinBox.setValue(self.font.pixelSize())
        self.fontspinBox.valueChanged.connect(self.onFontsizeChanged)
        self.Fontsize_labeltxt = QLabel()
        self.Fontsize_labeltxt.setText("Font size:")

        self.cameraPerspectCheckBox = QCheckBox()
        self.cameraPerspectCheckBox.setText("Perspective camera")
        self.cameraPerspectCheckBox.clicked.connect(self.onCameraPerspect)
        self.cameraPerspectCheckBox.setCheckState(Qt.Unchecked)

        self.settingsform = SettingsForm(self)

        self.MillerComboBox = QComboBox()
        self.MillerComboBox.activated.connect(self.onMillerComboSelchange)
        #self.MillerComboBox.setSizeAdjustPolicy(QComboBox.AdjustToContents)

        self.MillerLabel = QLabel()
        self.MillerLabel.setText("Selected HKL Scene")

        self.HKLnameedit = QLineEdit('')
        self.HKLnameedit.setReadOnly(True)
        self.textInfo = QTextEdit()
        self.textInfo.setLineWrapMode(QTextEdit.NoWrap)
        self.textInfo.setReadOnly(True)

        labels = [
            "Label", "Type", "no. of HKLs", "Span of HKLs", "Min Max data",
            "Min Max sigmas", "d_min, d_max", "Symmetry unique", "Anomalous"
        ]
        self.millertable = QTableWidget(0, len(labels))
        self.millertable.setHorizontalHeaderLabels(labels)
        self.millertable.horizontalHeader().setDefaultAlignment(Qt.AlignLeft)
        # don't allow editing this table
        self.millertable.setEditTriggers(QTableWidget.NoEditTriggers)

        self.createExpansionBox()
        self.createFileInfoBox()
        self.CreateSliceTabs()
        self.createRadiiScaleGroupBox()
        self.createBinsBox()
        self.CreateFunctionTabs()

        mainLayout = QGridLayout()
        mainLayout.addWidget(self.FileInfoBox, 0, 0)
        mainLayout.addWidget(self.MillerLabel, 1, 0)
        mainLayout.addWidget(self.MillerComboBox, 2, 0)
        mainLayout.addWidget(self.functionTabWidget, 3, 0)
        mainLayout.addWidget(self.settingsbtn, 4, 0, 1, 1)

        #import code, traceback; code.interact(local=locals(), banner="".join( traceback.format_stack(limit=10) ) )
        if self.UseOSbrowser == False:
            self.BrowserBox = QWebEngineView()
            mainLayout.addWidget(self.BrowserBox, 0, 1, 5, 3)
            self.BrowserBox.setUrl("https://cctbx.github.io/")
            #self.BrowserBox.setUrl("https://webglreport.com/")
            #self.BrowserBox.loadFinished.connect(self.onLoadFinished)
            mainLayout.setColumnStretch(2, 1)

        mainLayout.setRowStretch(0, 1)
        mainLayout.setRowStretch(1, 0)
        mainLayout.setRowStretch(2, 1)
        mainLayout.setRowStretch(3, 1)
        mainLayout.setColumnStretch(4, 0)
        self.setLayout(mainLayout)

        self.setWindowTitle("HKL-Viewer")
        self.cctbxproc = None
        self.LaunchCCTBXPython()
        self.out = None
        self.err = None
        self.comboviewwidth = 0
        self.hklscenes_arrays = []
        self.array_infotpls = []
        self.matching_arrays = []
        self.bin_infotpls = None
        self.bin_opacities = None
        self.html_url = ""
        self.spacegroups = []
        self.info = []
        self.infostr = ""
        self.fileisvalid = False
        self.NewFileLoaded = False
        self.NewHKLscenes = False
        self.updatingNbins = False
        self.binstableitemchanges = False

        self.show()

    def SettingsDialog(self):
        self.settingsform.show()

    def update(self):
        if self.cctbxproc:
            if self.cctbxproc.stdout:
                print(self.cctbxproc.stdout.read().decode("utf-8"))
            if self.cctbxproc.stderr:
                print(self.cctbxproc.stderr.read().decode("utf-8"))
        if self.out:
            print(self.out.decode("utf-8"))
        if self.err:
            print(self.err.decode("utf-8"))
        if self.zmq_context:
            try:
                msg = self.socket.recv(
                    flags=zmq.NOBLOCK
                )  #To empty the socket from previous messages
                msgstr = msg.decode()
                self.infodict = eval(msgstr)
                #print("received from cctbx: " + str(self.infodict))
                if self.infodict:

                    if self.infodict.get("hklscenes_arrays"):
                        self.hklscenes_arrays = self.infodict.get(
                            "hklscenes_arrays", [])

                    if self.infodict.get("array_infotpls"):
                        self.array_infotpls = self.infodict.get(
                            "array_infotpls", [])

                    if self.infodict.get("bin_data_label"):
                        self.BinDataComboBox.setCurrentText(
                            self.infodict["bin_data_label"])

                    if self.infodict.get("bin_infotpls"):
                        self.bin_infotpls = self.infodict["bin_infotpls"]

                        self.nbins = len(self.bin_infotpls)
                        self.updatingNbins = True
                        self.Nbins_spinBox.setValue(self.nbins)
                        self.updatingNbins = False
                        self.binstable.clearContents()
                        self.binstable.setRowCount(self.nbins)
                        for row, bin_infotpl in enumerate(self.bin_infotpls):
                            for col, elm in enumerate(bin_infotpl):
                                # only allow changing the last column with opacity values
                                if col != 3:
                                    item = QTableWidgetItem(str(elm))
                                else:
                                    item = QTableWidgetItem()
                                    item.setFlags(Qt.ItemIsUserCheckable
                                                  | Qt.ItemIsEnabled)
                                    item.setCheckState(Qt.Checked)
                                item.setFlags(item.flags() ^ Qt.ItemIsEditable)
                                self.binstable.setItem(row, col, item)
                        if self.bin_opacities:
                            self.update_table_opacities()

                    if self.infodict.get("bin_opacities"):
                        self.bin_opacities = self.infodict["bin_opacities"]
                        if self.binstable.rowCount() > 0:
                            self.update_table_opacities()

                    if self.infodict.get("html_url"):
                        self.html_url = self.infodict["html_url"]
                        if self.UseOSbrowser == False:
                            self.BrowserBox.setUrl(self.html_url)
                            # workaround for background colour bug in chromium
                            # https://bugreports.qt.io/browse/QTBUG-41960
                            self.BrowserBox.page().setBackgroundColor(
                                QColor(100, 100, 100, 1.0))

                    if self.infodict.get("spacegroups"):
                        self.spacegroups = self.infodict.get("spacegroups", [])
                        self.SpaceGroupComboBox.clear()
                        self.SpaceGroupComboBox.addItems(self.spacegroups)

                    if self.infodict.get("merge_data"):
                        self.mergedata = self.infodict["merge_data"]

                    currentinfostr = ""
                    if self.infodict.get("info"):
                        currentinfostr = self.infodict.get("info", [])

                    if self.infodict.get("NewFileLoaded"):
                        self.NewFileLoaded = self.infodict.get(
                            "NewFileLoaded", False)

                    if self.infodict.get("NewHKLscenes"):
                        self.NewHKLscenes = self.infodict.get(
                            "NewHKLscenes", False)

                    self.fileisvalid = True
                    #print("ngl_hkl_infodict: " + str(ngl_hkl_infodict))

                    if currentinfostr:
                        #print(currentinfostr)
                        self.infostr += currentinfostr + "\n"
                        # display no more than self.bufsize bytes of text
                        self.infostr = self.infostr[-self.bufsize:]
                        self.textInfo.setPlainText(self.infostr)
                        self.textInfo.verticalScrollBar().setValue(
                            self.textInfo.verticalScrollBar().maximum())

                    if self.NewFileLoaded and self.NewHKLscenes:
                        #if self.mergedata == True : val = Qt.CheckState.Checked
                        #if self.mergedata == None : val = Qt.CheckState.PartiallyChecked
                        #if self.mergedata == False : val = Qt.CheckState.Unchecked
                        #self.mergecheckbox.setCheckState(val )
                        #print("got hklscenes: " + str(self.hklscenes_arrays))

                        self.MillerComboBox.clear()
                        self.MillerComboBox.addItems(
                            [e[3] for e in self.hklscenes_arrays])
                        self.MillerComboBox.setCurrentIndex(
                            -1)  # unselect the first item in the list
                        self.comboviewwidth = 0
                        for e in self.hklscenes_arrays:
                            self.comboviewwidth = max(
                                self.comboviewwidth,
                                self.MillerComboBox.fontMetrics().width(e[3]))
                        self.MillerComboBox.view().setMinimumWidth(
                            self.comboviewwidth)

                        self.millertable.clearContents()
                        self.millertable.setRowCount(len(
                            self.hklscenes_arrays))
                        for n, millarr in enumerate(self.array_infotpls):
                            for m, elm in enumerate(millarr):
                                self.millertable.setItem(
                                    n, m, QTableWidgetItem(str(elm)))
                        self.functionTabWidget.setDisabled(True)
                        self.NewFileLoaded = False

                    if self.NewHKLscenes:
                        self.BinDataComboBox.clear()
                        self.BinDataComboBox.addItems(
                            ["Resolution"] +
                            [e[3] for e in self.hklscenes_arrays])
                        self.BinDataComboBox.view().setMinimumWidth(
                            self.comboviewwidth)
                        #self.BinDataComboBox.setCurrentIndex(-1) # unselect the first item in the list
                        self.NewHKLscenes = False

            except Exception as e:
                errmsg = str(e)
                if "Resource temporarily unavailable" not in errmsg:
                    print(errmsg + traceback.format_exc(limit=10))
                pass

    def onFinalMouseSensitivity(self):
        val = self.mousemoveslider.value() / 100.0
        self.NGL_HKL_command(
            'NGL_HKLviewer.viewer.NGL.mouse_sensitivity = %f' % val)

    def onMouseSensitivity(self):
        val = self.mousemoveslider.value() / 100.0
        self.mousesensitxtbox.setText("%2.2f" % val)

    def onFontsizeChanged(self, val):
        font = app.font()
        font.setPointSize(val)
        app.setFont(font)
        self.settingsform.setFixedSize(self.settingsform.sizeHint())

    def onCameraPerspect(self, val):
        if self.cameraPerspectCheckBox.isChecked():
            self.NGL_HKL_command("NGL_HKLviewer.camera_type = perspective")
        else:
            self.NGL_HKL_command("NGL_HKLviewer.camera_type = orthographic")

    def MergeData(self):
        if self.mergecheckbox.checkState() == Qt.CheckState.Checked:
            self.NGL_HKL_command('NGL_HKLviewer.mergedata = True')
        if self.mergecheckbox.checkState() == Qt.CheckState.PartiallyChecked:
            self.NGL_HKL_command('NGL_HKLviewer.mergedata = None')
        if self.mergecheckbox.checkState() == Qt.CheckState.Unchecked:
            self.NGL_HKL_command('NGL_HKLviewer.mergedata = False')

    def ExpandToP1(self):
        if self.expandP1checkbox.isChecked():
            self.NGL_HKL_command('NGL_HKLviewer.viewer.expand_to_p1 = True')
        else:
            self.NGL_HKL_command('NGL_HKLviewer.viewer.expand_to_p1 = False')

    def ExpandAnomalous(self):
        if self.expandAnomalouscheckbox.isChecked():
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.expand_anomalous = True')
        else:
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.expand_anomalous = False')

    def showSysAbsent(self):
        if self.sysabsentcheckbox.isChecked():
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.show_systematic_absences = True')
        else:
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.show_systematic_absences = False')

    def showMissing(self):
        if self.missingcheckbox.isChecked():
            self.NGL_HKL_command('NGL_HKLviewer.viewer.show_missing = True')
        else:
            self.NGL_HKL_command('NGL_HKLviewer.viewer.show_missing = False')

    def showOnlyMissing(self):
        if self.onlymissingcheckbox.isChecked():
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.show_only_missing = True')
        else:
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.show_only_missing = False')

    def showSlice(self):
        if self.showslicecheckbox.isChecked():
            self.NGL_HKL_command('NGL_HKLviewer.viewer.slice_mode = True')
            if self.expandP1checkbox.isChecked():
                self.NGL_HKL_command("""NGL_HKLviewer.viewer {
                                                       expand_to_p1 = True
                                                       inbrowser = False
                                                    }
                             """)
            if self.expandAnomalouscheckbox.isChecked():
                self.NGL_HKL_command("""NGL_HKLviewer.viewer {
                                                       expand_anomalous = True
                                                       inbrowser = False
                                                     }
                             """)
        else:
            self.NGL_HKL_command("""NGL_HKLviewer.viewer {
                                                      slice_mode = False
                                                      inbrowser = True
                                                    }
                            """)

    def onSliceComboSelchange(self, i):
        rmin = self.array_infotpls[self.MillerComboBox.currentIndex()][3][0][i]
        rmax = self.array_infotpls[self.MillerComboBox.currentIndex()][3][1][i]
        self.sliceindexspinBox.setRange(rmin, rmax)
        self.NGL_HKL_command("NGL_HKLviewer.viewer.slice_axis = %s" %
                             self.sliceaxis[i])

    def onSliceIndexChanged(self, val):
        self.sliceindex = val
        self.NGL_HKL_command("NGL_HKLviewer.viewer.slice_index = %d" %
                             self.sliceindex)

    def onBindataComboSelchange(self, i):
        if self.BinDataComboBox.currentText():
            if self.BinDataComboBox.currentIndex() > 0:
                bin_scene_label = str(self.BinDataComboBox.currentIndex() - 1)
            else:
                bin_scene_label = "Resolution"
            self.NGL_HKL_command("NGL_HKLviewer.bin_scene_label = %s" %
                                 bin_scene_label)

    def update_table_opacities(self, allalpha=None):
        bin_opacitieslst = eval(self.bin_opacities)
        self.binstable_isready = False
        for binopacity in bin_opacitieslst:
            if not allalpha:
                alpha = float(binopacity.split(",")[0])
            else:
                alpha = allalpha
            bin = int(binopacity.split(",")[1])
            item = QTableWidgetItem()
            item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
            if alpha < 0.5:
                item.setCheckState(Qt.Unchecked)
            else:
                item.setCheckState(Qt.Checked)
            item.setFlags(item.flags() ^ Qt.ItemIsEditable)
            self.binstable.setItem(bin, 3, item)
        self.binstable_isready = True

    def SetOpaqueAll(self):
        if self.binstableitemchanges:
            return
        bin_opacitieslst = eval(self.bin_opacities)
        nbins = len(bin_opacitieslst)
        sum = 0
        for binopacity in bin_opacitieslst:
            sum += float(binopacity.split(",")[0])
        if sum >= nbins:
            self.OpaqueAllCheckbox.setCheckState(Qt.Checked)
        if sum == 0:
            self.OpaqueAllCheckbox.setCheckState(Qt.Unchecked)
        if sum > 0.0 and sum < nbins:
            self.OpaqueAllCheckbox.setCheckState(Qt.PartiallyChecked)

    def onBinsTableItemChanged(self, item):
        row = item.row()
        column = item.column()
        try:
            if item.checkState() == Qt.Unchecked:
                newval = 0
            else:
                newval = 1.0
            if column == 3 and self.binstable_isready:  # changing opacity
                assert (newval <= 1.0 and newval >= 0.0)
                bin_opacitieslst = eval(self.bin_opacities)
                bin_opacitieslst[row] = str(newval) + ', ' + str(row)
                self.bin_opacities = str(bin_opacitieslst)
                self.SetOpaqueAll()
                self.NGL_HKL_command(
                    'NGL_HKLviewer.viewer.NGL.bin_opacities = "%s"' %
                    self.bin_opacities)
        except Exception as e:
            print(str(e))
            #self.binstable.currentItem().setText( self.currentSelectedBinsTableVal)

    def onBinsTableItemSelectionChanged(self):
        row = self.binstable.currentItem().row()
        column = self.binstable.currentItem().column()
        self.currentSelectedBinsTableVal = self.binstable.currentItem().text()
        #print( "in itemSelectionChanged " + self.currentSelectedBinsTableVal)

    def onOpaqueAll(self):
        self.binstableitemchanges = True
        bin_opacitieslst = eval(self.bin_opacities)
        nbins = len(bin_opacitieslst)
        bin_opacitieslst = []
        self.binstable_isready = False
        if self.OpaqueAllCheckbox.isChecked():
            for i in range(nbins):
                bin_opacitieslst.append("1.0, %d" % i)
        else:
            for i in range(nbins):
                bin_opacitieslst.append("0.0, %d" % i)
        self.bin_opacities = str(bin_opacitieslst)
        self.NGL_HKL_command('NGL_HKLviewer.viewer.NGL.bin_opacities = "%s"' %
                             self.bin_opacities)
        self.binstableitemchanges = False
        self.binstable_isready = True

    """
  def onLoadFinished(self, val):
    pass
    #print("web page finished loading now")


  def onBinsTableitemActivated(self, item):
    row = item.row()
    column = item.column()
    currentval = item.text()
    #print( "in itemActivated " + currentval)


  def onBinsTableCellentered(self, row, col):
    pass
    #print( "in Cellentered " + self.binstable.currentItem().text() )


  def onBinsTableCellPressed(self, row, col):
    pass
    #print( "in CellPressed " + self.binstable.currentItem().text() )
  """

    def onNbinsChanged(self, val):
        self.nbins = val
        if not self.updatingNbins:  # avoid possible endless loop to cctbx
            self.NGL_HKL_command("NGL_HKLviewer.nbins = %d" % self.nbins)

    def onRadiiScaleChanged(self, val):
        self.radii_scale = val
        self.NGL_HKL_command("""
      NGL_HKLviewer.viewer {
        nth_power_scale_radii = %f
        scale = %f
      }
      """ % (self.nth_power_scale, self.radii_scale))

    def onPowerScaleChanged(self, val):
        self.nth_power_scale = val
        self.NGL_HKL_command("""
      NGL_HKLviewer.viewer {
        nth_power_scale_radii = %f
        scale = %f
      }
      """ % (self.nth_power_scale, self.radii_scale))

    def onManualPowerScale(self):
        if self.ManualPowerScalecheckbox.isChecked():
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.nth_power_scale_radii = %f' %
                self.nth_power_scale)
            self.power_scale_spinBox.setEnabled(True)
        else:
            self.NGL_HKL_command(
                'NGL_HKLviewer.viewer.nth_power_scale_radii = -1.0')
            self.power_scale_spinBox.setEnabled(False)
            self.nth_power_scale = -1.0

    def OpenReflectionsFile(self):
        options = QFileDialog.Options()
        fileName, filtr = QFileDialog.getOpenFileName(
            self, "Load reflections file", "",
            "All Files (*);;MTZ Files (*.mtz);;CIF (*.cif)", "", options)
        if fileName:
            self.HKLnameedit.setText(fileName)
            #self.infostr = ""
            self.textInfo.setPlainText("")
            self.fileisvalid = False
            self.NGL_HKL_command('NGL_HKLviewer.filename = "%s"' % fileName)
            self.MillerComboBox.clear()
            self.BinDataComboBox.clear()

    def createExpansionBox(self):
        self.SpaceGroupComboBox = QComboBox()
        self.SpaceGroupComboBox.activated.connect(self.SpacegroupSelchange)

        self.SpacegroupLabel = QLabel()
        self.SpacegroupLabel.setText("Space Subgroups")

        self.mergecheckbox = QCheckBox()
        self.mergecheckbox.setText("Merge data")
        #self.mergecheckbox.setTristate (True)
        self.mergecheckbox.clicked.connect(self.MergeData)

        self.expandP1checkbox = QCheckBox()
        self.expandP1checkbox.setText("Expand to P1")
        self.expandP1checkbox.clicked.connect(self.ExpandToP1)

        self.expandAnomalouscheckbox = QCheckBox()
        self.expandAnomalouscheckbox.setText("Show Friedel pairs")
        self.expandAnomalouscheckbox.clicked.connect(self.ExpandAnomalous)

        self.sysabsentcheckbox = QCheckBox()
        self.sysabsentcheckbox.setText("Show Systematic Absences")
        self.sysabsentcheckbox.clicked.connect(self.showSysAbsent)

        self.missingcheckbox = QCheckBox()
        self.missingcheckbox.setText("Show Missing")
        self.missingcheckbox.clicked.connect(self.showMissing)

        self.onlymissingcheckbox = QCheckBox()
        self.onlymissingcheckbox.setText("Only Show Missing")
        self.onlymissingcheckbox.clicked.connect(self.showOnlyMissing)

        self.ExpansionBox = QGroupBox("Expansions")
        layout = QGridLayout()
        layout.addWidget(self.SpacegroupLabel, 0, 0)
        layout.addWidget(self.SpaceGroupComboBox, 0, 1)
        #layout.addWidget(self.mergecheckbox,             1, 0)
        layout.addWidget(self.expandP1checkbox, 1, 0)
        layout.addWidget(self.expandAnomalouscheckbox, 1, 1)
        layout.addWidget(self.sysabsentcheckbox, 2, 0)
        layout.addWidget(self.missingcheckbox, 3, 0)
        layout.addWidget(self.onlymissingcheckbox, 3, 1)
        layout.setRowStretch(0, 0)
        layout.setRowStretch(1, 0)
        layout.setRowStretch(2, 0)
        layout.setRowStretch(3, 1)
        self.ExpansionBox.setLayout(layout)

    def CreateSliceTabs(self):
        self.showslicecheckbox = QCheckBox()
        self.showslicecheckbox.setText("Show Slice")
        self.showslicecheckbox.clicked.connect(self.showSlice)

        self.sliceindexspinBox = QDoubleSpinBox()
        self.sliceindex = 0
        self.sliceindexspinBox.setValue(self.sliceindex)
        self.sliceindexspinBox.setDecimals(0)
        self.sliceindexspinBox.setSingleStep(1)
        self.sliceindexspinBox.setRange(0, 20)
        self.sliceindexspinBox.valueChanged.connect(self.onSliceIndexChanged)

        self.SliceLabelComboBox = QComboBox()
        self.SliceLabelComboBox.activated.connect(self.onSliceComboSelchange)
        self.sliceaxis = ["h", "k", "l"]
        self.SliceLabelComboBox.addItems(self.sliceaxis)

        self.sliceTabWidget = QTabWidget()
        tab1 = QWidget()
        layout1 = QGridLayout()
        layout1.addWidget(self.showslicecheckbox, 0, 0, 1, 1)
        layout1.addWidget(self.SliceLabelComboBox, 0, 1, 1, 1)
        layout1.addWidget(self.sliceindexspinBox, 0, 2, 1, 1)
        tab1.setLayout(layout1)

        tab2 = QWidget()
        layout2 = QGridLayout()

        self.hvec_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.hvecval = 2.0
        self.hvec_spinBox.setValue(self.hvecval)
        self.hvec_spinBox.setDecimals(2)
        self.hvec_spinBox.setSingleStep(0.5)
        self.hvec_spinBox.setRange(-100.0, 10.0)
        self.hvec_spinBox.valueChanged.connect(self.onHvecChanged)
        self.hvec_Label = QLabel()
        self.hvec_Label.setText("H")
        layout2.addWidget(self.hvec_Label, 0, 0, 1, 1)
        layout2.addWidget(self.hvec_spinBox, 0, 1, 1, 1)

        self.kvec_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.kvecval = 0.0
        self.kvec_spinBox.setValue(self.kvecval)
        self.kvec_spinBox.setDecimals(2)
        self.kvec_spinBox.setSingleStep(0.5)
        self.kvec_spinBox.setRange(-100.0, 100.0)
        self.kvec_spinBox.valueChanged.connect(self.onKvecChanged)
        self.kvec_Label = QLabel()
        self.kvec_Label.setText("K")
        layout2.addWidget(self.kvec_Label, 1, 0, 1, 1)
        layout2.addWidget(self.kvec_spinBox, 1, 1, 1, 1)

        self.lvec_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.lvecval = 0.0
        self.lvec_spinBox.setValue(self.lvecval)
        self.lvec_spinBox.setDecimals(2)
        self.lvec_spinBox.setSingleStep(0.5)
        self.lvec_spinBox.setRange(-100.0, 100.0)
        self.lvec_spinBox.valueChanged.connect(self.onLvecChanged)
        self.lvec_Label = QLabel()
        self.lvec_Label.setText("L")
        layout2.addWidget(self.lvec_Label, 2, 0, 1, 1)
        layout2.addWidget(self.lvec_spinBox, 2, 1, 1, 1)

        self.hkldist_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.hkldistval = 0.0
        self.hkldist_spinBox.setValue(self.hkldistval)
        self.hkldist_spinBox.setDecimals(2)
        self.hkldist_spinBox.setSingleStep(0.5)
        self.hkldist_spinBox.setRange(-100.0, 100.0)
        self.hkldist_spinBox.valueChanged.connect(self.onHKLdistChanged)
        self.hkldist_Label = QLabel()
        self.hkldist_Label.setText("Distance from Origin")
        layout2.addWidget(self.hkldist_Label, 3, 0, 1, 1)
        layout2.addWidget(self.hkldist_spinBox, 3, 1, 1, 1)

        self.clipwidth_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.clipwidthval = 0.5
        self.clipwidth_spinBox.setValue(self.clipwidthval)
        self.clipwidth_spinBox.setDecimals(2)
        self.clipwidth_spinBox.setSingleStep(0.05)
        self.clipwidth_spinBox.setRange(0.0, 100.0)
        self.clipwidth_spinBox.valueChanged.connect(self.onClipwidthChanged)
        self.clipwidth_Label = QLabel()
        self.clipwidth_Label.setText("Clip Plane Width")
        layout2.addWidget(self.clipwidth_Label, 4, 0, 1, 1)
        layout2.addWidget(self.clipwidth_spinBox, 4, 1, 1, 1)

        self.ClipBox = QGroupBox("Normal Vector to Clip Plane")
        self.ClipBox.setLayout(layout2)

        layout3 = QGridLayout()
        self.ClipPlaneChkBox = QCheckBox(self.sliceTabWidget)
        self.ClipPlaneChkBox.setText(
            "Use clip plane normal to HKL vector pointing out")
        self.ClipPlaneChkBox.clicked.connect(self.onClipPlaneChkBox)

        layout3.addWidget(self.ClipPlaneChkBox, 0, 0)
        layout3.addWidget(self.ClipBox, 1, 0)
        tab2.setLayout(layout3)
        self.sliceTabWidget.addTab(tab1, "Explicit Slicing")
        self.sliceTabWidget.addTab(tab2, "Clip Plane Slicing")
        self.ClipBox.setDisabled(True)

    def onClipPlaneChkBox(self):
        if self.ClipPlaneChkBox.isChecked():
            self.ClipBox.setDisabled(False)
            philstr = """NGL_HKLviewer.normal_clip_plane {
  h = %s
  k = %s
  l = %s
  hkldist = %s
  clipwidth = %s
}
  NGL_HKLviewer.viewer.NGL.fixorientation = %s

      """ %(self.hvecval, self.kvecval, self.lvecval, self.hkldistval, self.clipwidthval, \
                                    str(self.fixedorientcheckbox.isChecked()) )
            self.NGL_HKL_command(philstr)
        else:
            self.ClipBox.setDisabled(True)
            self.NGL_HKL_command(
                "NGL_HKLviewer.normal_clip_plane.clipwidth = None")

    def onClipwidthChanged(self, val):
        self.clipwidthval = val
        self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.clipwidth = %f" %
                             self.clipwidthval)

    def onHKLdistChanged(self, val):
        self.hkldistval = val
        self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.hkldist = %f" %
                             self.hkldistval)

    def onHvecChanged(self, val):
        self.hvecval = val
        self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.h = %f" %
                             self.hvecval)

    def onKvecChanged(self, val):
        self.kvecval = val
        self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.k = %f" %
                             self.kvecval)

    def onLvecChanged(self, val):
        self.lvecval = val
        self.NGL_HKL_command("NGL_HKLviewer.normal_clip_plane.l = %f" %
                             self.lvecval)

    def onFixedorient(self):
        self.NGL_HKL_command('NGL_HKLviewer.viewer.NGL.fixorientation = %s' \
                                        %str(self.fixedorientcheckbox.isChecked()))

    def onMillerComboSelchange(self, i):
        self.NGL_HKL_command("NGL_HKLviewer.scene_id = %d" % i)
        #self.MillerComboBox.setCurrentIndex(i)
        if self.MillerComboBox.currentText():
            self.functionTabWidget.setEnabled(True)
            self.expandAnomalouscheckbox.setEnabled(True)
            # don' allow anomalous expansion for data that's already anomalous
            for arrayinfo in self.array_infotpls:
                isanomalous = arrayinfo[-1]
                label = arrayinfo[0]
                if isanomalous and label == self.MillerComboBox.currentText(
                )[:len(label)]:
                    self.expandAnomalouscheckbox.setDisabled(True)
        else:
            self.functionTabWidget.setDisabled(True)

        self.SpaceGroupComboBox.clear()
        self.SpaceGroupComboBox.addItems(self.spacegroups)
        # need to supply issymunique flag in infotuple
        #if self.hklscenes_arrays[ i ][6] == 0:
        #  self.mergecheckbox.setEnabled(True)
        #else:
        #  self.mergecheckbox.setEnabled(False)

    def createFileInfoBox(self):
        self.FileInfoBox = QGroupBox("Reflection File Information")
        layout = QGridLayout()
        layout.addWidget(self.openFileNameButton, 0, 0, 1, 2)
        if self.devmode:
            layout.addWidget(self.debugbutton, 0, 2, 1, 1)
        layout.addWidget(self.HKLnameedit, 1, 0, 1, 3)
        layout.addWidget(self.millertable, 2, 0, 1, 3)
        layout.addWidget(self.textInfo, 3, 0, 1, 3)
        #layout.setColumnStretch(1, 2)
        self.FileInfoBox.setLayout(layout)

    def createRadiiScaleGroupBox(self):
        self.RadiiScaleGroupBox = QGroupBox("Radii Size of HKL Spheres")

        self.ManualPowerScalecheckbox = QCheckBox()
        self.ManualPowerScalecheckbox.setText(
            "Manual Power Scaling of Sphere Radii")
        self.ManualPowerScalecheckbox.clicked.connect(self.onManualPowerScale)

        self.power_scale_spinBox = QDoubleSpinBox(self.RadiiScaleGroupBox)
        self.nth_power_scale = 0.5
        self.power_scale_spinBox.setValue(self.nth_power_scale)
        self.power_scale_spinBox.setDecimals(2)
        self.power_scale_spinBox.setSingleStep(0.05)
        self.power_scale_spinBox.setRange(0.0, 1.0)
        self.power_scale_spinBox.valueChanged.connect(self.onPowerScaleChanged)
        self.power_scale_spinBox.setEnabled(False)
        self.powerscaleLabel = QLabel()
        self.powerscaleLabel.setText("Power scale Factor")

        self.radii_scale_spinBox = QDoubleSpinBox(self.RadiiScaleGroupBox)
        self.radii_scale = 1.0
        self.radii_scale_spinBox.setValue(self.radii_scale)
        self.radii_scale_spinBox.setDecimals(1)
        self.radii_scale_spinBox.setSingleStep(0.1)
        self.radii_scale_spinBox.setRange(0.2, 2.0)
        self.radii_scale_spinBox.valueChanged.connect(self.onRadiiScaleChanged)
        self.radiiscaleLabel = QLabel()
        self.radiiscaleLabel.setText("Linear Scale Factor")

        layout = QGridLayout()
        layout.addWidget(self.ManualPowerScalecheckbox, 1, 0, 1, 2)
        layout.addWidget(self.powerscaleLabel, 2, 0, 1, 2)
        layout.addWidget(self.power_scale_spinBox, 2, 1, 1, 2)
        layout.addWidget(self.radiiscaleLabel, 3, 0, 1, 2)
        layout.addWidget(self.radii_scale_spinBox, 3, 1, 1, 2)
        layout.setColumnStretch(0, 1)
        layout.setColumnStretch(1, 0)
        self.RadiiScaleGroupBox.setLayout(layout)

    def createBinsBox(self):
        self.binstable = QTableWidget(0, 4)
        self.binstable_isready = False
        labels = [
            "no. of HKLs", "lower bin value", "upper bin value", "opacity"
        ]
        self.binstable.setHorizontalHeaderLabels(labels)
        self.binstable.horizontalHeader().setDefaultAlignment(Qt.AlignLeft)
        self.bindata_labeltxt = QLabel()
        self.bindata_labeltxt.setText("Data binned:")
        self.Nbins_spinBox = QSpinBox()
        self.Nbins_spinBox.setSingleStep(1)
        self.Nbins_spinBox.setRange(1, 40)
        self.Nbins_spinBox.valueChanged.connect(self.onNbinsChanged)
        self.Nbins_labeltxt = QLabel()
        self.Nbins_labeltxt.setText("Number of bins:")

        self.OpaqueAllCheckbox = QCheckBox()
        #self.OpaqueAllCheckbox.setTristate()
        self.OpaqueAllCheckbox.setText("Show all data in bins")
        self.OpaqueAllCheckbox.clicked.connect(self.onOpaqueAll)

        self.binstable.itemChanged.connect(self.onBinsTableItemChanged)
        self.binstable.itemSelectionChanged.connect(
            self.onBinsTableItemSelectionChanged)
        self.BinDataComboBox = QComboBox()
        self.BinDataComboBox.activated.connect(self.onBindataComboSelchange)
        self.BinsGroupBox = QGroupBox("Bins")
        layout = QGridLayout()
        layout.addWidget(self.bindata_labeltxt, 0, 0)
        layout.addWidget(self.BinDataComboBox, 0, 1)
        layout.addWidget(self.Nbins_labeltxt, 0, 2)
        layout.addWidget(self.Nbins_spinBox, 0, 3)
        layout.addWidget(self.OpaqueAllCheckbox, 1, 2)
        layout.addWidget(self.binstable, 2, 0, 1, 4)
        layout.setColumnStretch(0, 0)
        layout.setColumnStretch(1, 2)
        layout.setColumnStretch(3, 1)
        self.BinsGroupBox.setLayout(layout)

    def DebugInteractively(self):
        import code, traceback
        code.interact(local=locals(),
                      banner="".join(traceback.format_stack(limit=10)))

    def CreateFunctionTabs(self):
        self.functionTabWidget = QTabWidget()
        tab1 = QWidget()
        layout1 = QGridLayout()
        layout1.addWidget(self.ExpansionBox, 0, 0)
        layout1.setRowStretch(0, 0)
        tab1.setLayout(layout1)

        tab2 = QWidget()
        layout2 = QGridLayout()

        self.fixedorientcheckbox = QCheckBox(self.sliceTabWidget)
        self.fixedorientcheckbox.setText(
            "Fix orientation but allow zoom and translation")
        self.fixedorientcheckbox.clicked.connect(self.onFixedorient)
        layout2.addWidget(self.fixedorientcheckbox, 0, 0)

        layout2.addWidget(self.sliceTabWidget, 1, 0)
        tab2.setLayout(layout2)

        tab3 = QWidget()
        layout3 = QGridLayout()
        layout3.addWidget(self.RadiiScaleGroupBox, 0, 0)
        tab3.setLayout(layout3)

        tab4 = QWidget()
        layout4 = QGridLayout()
        layout4.addWidget(self.BinsGroupBox, 0, 0)
        tab4.setLayout(layout4)

        self.functionTabWidget.addTab(tab1, "Expand")
        self.functionTabWidget.addTab(tab2, "Slice")
        self.functionTabWidget.addTab(tab3, "Size")
        self.functionTabWidget.addTab(tab4, "Bins")
        self.functionTabWidget.setDisabled(True)

    def SpacegroupSelchange(self, i):
        self.NGL_HKL_command("NGL_HKLviewer.spacegroup_choice = %d" % i)

    def find_free_port(self):
        import socket
        s = socket.socket()
        s.bind(('', 0))  # Bind to a free port provided by the host.
        port = s.getsockname()[1]
        s.close()
        return port

    def LaunchCCTBXPython(self):
        self.sockport = self.find_free_port()
        self.zmq_context = zmq.Context()
        self.socket = self.zmq_context.socket(zmq.PAIR)
        self.socket.bind("tcp://127.0.0.1:%s" % self.sockport)
        try:
            msg = self.socket.recv(
                flags=zmq.NOBLOCK)  #To empty the socket from previous messages
        except Exception as e:
            pass
        cmdargs = 'cctbx.python.bat -i -c "from crys3d.hklview import cmdlineframes;' \
         + ' myHKLview = cmdlineframes.HKLViewFrame(useGuiSocket=%s, high_quality=True,' %self.sockport \
         + ' jscriptfname = \'%s\', ' %self.jscriptfname \
         + ' verbose=%s, UseOSBrowser= %s )"\n' %(self.verbose, str(self.UseOSbrowser))
        self.cctbxproc = subprocess.Popen(cmdargs,
                                          shell=True,
                                          stdin=subprocess.PIPE,
                                          stdout=sys.stdout,
                                          stderr=sys.stderr)
        #time.sleep(1)

    def NGL_HKL_command(self, cmdstr):
        #print("sending:\n" + cmdstr)
        self.socket.send(bytes(cmdstr, "utf-8"))
Exemple #24
0
class ColorDialog(QDialog):
    def __init__(self, model, font_metric, parent=None):
        super().__init__(parent)

        self.setWindowTitle('Color Options')

        self.model = model
        self.font_metric = font_metric
        self.main_window = parent

        self.createDialogLayout()

    def createDialogLayout(self):

        self.createGeneralTab()

        self.cellTable = self.createDomainTable(self.main_window.cellsModel)
        self.matTable = self.createDomainTable(self.main_window.materialsModel)
        self.tabs = {
            'cell': self.createDomainTab(self.cellTable),
            'material': self.createDomainTab(self.matTable),
            'temperature': self.createPropertyTab('temperature'),
            'density': self.createPropertyTab('density')
        }

        self.tab_bar = QTabWidget()
        self.tab_bar.setMaximumHeight(800)
        self.tab_bar.setSizePolicy(QSizePolicy.Expanding,
                                   QSizePolicy.Expanding)
        self.tab_bar.addTab(self.generalTab, 'General')
        self.tab_bar.addTab(self.tabs['cell'], 'Cells')
        self.tab_bar.addTab(self.tabs['material'], 'Materials')
        self.tab_bar.addTab(self.tabs['temperature'], 'Temperature')
        self.tab_bar.addTab(self.tabs['density'], 'Density')

        self.createButtonBox()

        self.colorDialogLayout = QVBoxLayout()
        self.colorDialogLayout.addWidget(self.tab_bar)
        self.colorDialogLayout.addWidget(self.buttonBox)
        self.setLayout(self.colorDialogLayout)

    def createGeneralTab(self):

        main_window = self.main_window

        # Masking options
        self.maskingCheck = QCheckBox('')
        self.maskingCheck.stateChanged.connect(main_window.toggleMasking)

        button_width = self.font_metric.boundingRect("XXXXXXXXXX").width()
        self.maskColorButton = QPushButton()
        self.maskColorButton.setCursor(QtCore.Qt.PointingHandCursor)
        self.maskColorButton.setFixedWidth(button_width)
        self.maskColorButton.setFixedHeight(self.font_metric.height() * 1.5)
        self.maskColorButton.clicked.connect(main_window.editMaskingColor)

        # Highlighting options
        self.hlCheck = QCheckBox('')
        self.hlCheck.stateChanged.connect(main_window.toggleHighlighting)

        self.hlColorButton = QPushButton()
        self.hlColorButton.setCursor(QtCore.Qt.PointingHandCursor)
        self.hlColorButton.setFixedWidth(button_width)
        self.hlColorButton.setFixedHeight(self.font_metric.height() * 1.5)
        self.hlColorButton.clicked.connect(main_window.editHighlightColor)

        self.alphaBox = QDoubleSpinBox()
        self.alphaBox.setRange(0, 1)
        self.alphaBox.setSingleStep(.05)
        self.alphaBox.valueChanged.connect(main_window.editAlpha)

        self.seedBox = QSpinBox()
        self.seedBox.setRange(1, 999)
        self.seedBox.valueChanged.connect(main_window.editSeed)

        # General options
        self.bgButton = QPushButton()
        self.bgButton.setCursor(QtCore.Qt.PointingHandCursor)
        self.bgButton.setFixedWidth(button_width)
        self.bgButton.setFixedHeight(self.font_metric.height() * 1.5)
        self.bgButton.clicked.connect(main_window.editBackgroundColor)

        self.colorbyBox = QComboBox(self)
        self.colorbyBox.addItem("material")
        self.colorbyBox.addItem("cell")
        self.colorbyBox.addItem("temperature")
        self.colorbyBox.addItem("density")
        self.colorbyBox.currentTextChanged[str].connect(
            main_window.editColorBy)

        self.universeLevelBox = QComboBox(self)
        self.universeLevelBox.addItem('all')
        for i in range(self.model.max_universe_levels):
            self.universeLevelBox.addItem(str(i))
        self.universeLevelBox.currentTextChanged[str].connect(
            main_window.editUniverseLevel)

        # Overlap plotting
        self.overlapCheck = QCheckBox('', self)
        overlap_connector = partial(main_window.toggleOverlaps)
        self.overlapCheck.stateChanged.connect(overlap_connector)

        self.overlapColorButton = QPushButton()
        self.overlapColorButton.setCursor(QtCore.Qt.PointingHandCursor)
        self.overlapColorButton.setFixedWidth(button_width)
        self.overlapColorButton.setFixedHeight(self.font_metric.height() * 1.5)
        self.overlapColorButton.clicked.connect(main_window.editOverlapColor)

        self.colorResetButton = QPushButton("&Reset Colors")
        self.colorResetButton.setCursor(QtCore.Qt.PointingHandCursor)
        self.colorResetButton.clicked.connect(main_window.resetColors)

        formLayout = QFormLayout()
        formLayout.setAlignment(QtCore.Qt.AlignHCenter)
        formLayout.setFormAlignment(QtCore.Qt.AlignHCenter)
        formLayout.setLabelAlignment(QtCore.Qt.AlignLeft)

        formLayout.addRow('Masking:', self.maskingCheck)
        formLayout.addRow('Mask Color:', self.maskColorButton)
        formLayout.addRow(HorizontalLine())
        formLayout.addRow('Highlighting:', self.hlCheck)
        formLayout.addRow('Highlight Color:', self.hlColorButton)
        formLayout.addRow('Highlight Alpha:', self.alphaBox)
        formLayout.addRow('Highlight Seed:', self.seedBox)
        formLayout.addRow(HorizontalLine())
        formLayout.addRow('Background Color:          ', self.bgButton)
        formLayout.addRow(HorizontalLine())
        formLayout.addRow('Show Overlaps:', self.overlapCheck)
        formLayout.addRow('Overlap Color:', self.overlapColorButton)
        formLayout.addRow(HorizontalLine())
        formLayout.addRow('Color Plot By:', self.colorbyBox)
        formLayout.addRow('Universe Level:', self.universeLevelBox)
        formLayout.addRow(self.colorResetButton, None)

        generalLayout = QHBoxLayout()
        innerWidget = QWidget()
        generalLayout.setAlignment(QtCore.Qt.AlignVCenter)
        innerWidget.setLayout(formLayout)
        generalLayout.addStretch(1)
        generalLayout.addWidget(innerWidget)
        generalLayout.addStretch(1)

        self.generalTab = QWidget()
        self.generalTab.setLayout(generalLayout)

    def createDomainTable(self, domainmodel):

        domainTable = QTableView()
        domainTable.setModel(domainmodel)
        domainTable.setItemDelegate(DomainDelegate(domainTable))
        domainTable.verticalHeader().setVisible(False)
        domainTable.resizeColumnsToContents()
        domainTable.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        domainTable.horizontalHeader().setSectionResizeMode(
            1, QHeaderView.Stretch)

        return domainTable

    def createDomainTab(self, domaintable):

        domainTab = QWidget()
        domainTab.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        domainLayout = QVBoxLayout()
        domainLayout.addWidget(domaintable)
        domainTab.setLayout(domainLayout)

        return domainTab

    def createPropertyTab(self, property_kind):
        propertyTab = QWidget()
        propertyTab.property_kind = property_kind
        propertyTab.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        propertyLayout = QVBoxLayout()

        propertyTab.minMaxCheckBox = QCheckBox()
        propertyTab.minMaxCheckBox.setCheckable(True)
        connector1 = partial(self.main_window.toggleUserMinMax,
                             property=property_kind)
        propertyTab.minMaxCheckBox.stateChanged.connect(connector1)

        propertyTab.minBox = ScientificDoubleSpinBox(self)
        propertyTab.minBox.setMaximum(1E9)
        propertyTab.minBox.setMinimum(0)
        propertyTab.maxBox = ScientificDoubleSpinBox(self)
        propertyTab.maxBox.setMaximum(1E9)
        propertyTab.maxBox.setMinimum(0)

        connector2 = partial(self.main_window.editColorbarMin,
                             property_type=property_kind)
        propertyTab.minBox.valueChanged.connect(connector2)
        connector3 = partial(self.main_window.editColorbarMax,
                             property_type=property_kind)
        propertyTab.maxBox.valueChanged.connect(connector3)

        propertyTab.colormapBox = QComboBox(self)
        cmaps = sorted(m for m in mcolormaps.datad if not m.endswith("_r"))
        for cmap in cmaps:
            propertyTab.colormapBox.addItem(cmap)

        connector = partial(self.main_window.editColorMap,
                            property_type=property_kind)

        propertyTab.colormapBox.currentTextChanged[str].connect(connector)

        propertyTab.dataIndicatorCheckBox = QCheckBox()
        propertyTab.dataIndicatorCheckBox.setCheckable(True)
        connector4 = partial(self.main_window.toggleDataIndicatorCheckBox,
                             property=property_kind)
        propertyTab.dataIndicatorCheckBox.stateChanged.connect(connector4)

        propertyTab.colorBarScaleCheckBox = QCheckBox()
        propertyTab.colorBarScaleCheckBox.setCheckable(True)
        connector5 = partial(self.main_window.toggleColorbarScale,
                             property=property_kind)
        propertyTab.colorBarScaleCheckBox.stateChanged.connect(connector5)

        formLayout = QFormLayout()
        formLayout.setAlignment(QtCore.Qt.AlignHCenter)
        formLayout.setFormAlignment(QtCore.Qt.AlignHCenter)
        formLayout.setLabelAlignment(QtCore.Qt.AlignLeft)

        formLayout.addRow('Colormap:', propertyTab.colormapBox)

        formLayout.addRow('Custom Min/Max', propertyTab.minMaxCheckBox)
        formLayout.addRow('Data Indicator', propertyTab.dataIndicatorCheckBox)
        formLayout.addRow('Log Scale', propertyTab.colorBarScaleCheckBox)
        formLayout.addRow(HorizontalLine())
        formLayout.addRow('Max: ', propertyTab.maxBox)
        formLayout.addRow('Min: ', propertyTab.minBox)

        propertyTab.setLayout(formLayout)

        return propertyTab

    def updateDataIndicatorVisibility(self):
        av = self.model.activeView
        for key, val in av.data_indicator_enabled.items():
            self.tabs[key].dataIndicatorCheckBox.setChecked(val)

    def updateColorMaps(self):
        cmaps = self.model.activeView.colormaps
        for key, val in cmaps.items():
            idx = self.tabs[key].colormapBox.findText(
                val, QtCore.Qt.MatchFixedString)
            if idx >= 0:
                self.tabs[key].colormapBox.setCurrentIndex(idx)

    def updateColorMinMax(self):
        minmax = self.model.activeView.user_minmax
        for key, val in minmax.items():
            self.tabs[key].minBox.setValue(val[0])
            self.tabs[key].maxBox.setValue(val[1])
        custom_minmax = self.model.activeView.use_custom_minmax
        for key, val, in custom_minmax.items():
            self.tabs[key].minMaxCheckBox.setChecked(val)
            self.tabs[key].minBox.setEnabled(val)
            self.tabs[key].maxBox.setEnabled(val)

    def updateColorbarScale(self):
        av = self.model.activeView
        for key, val in av.color_scale_log.items():
            self.tabs[key].colorBarScaleCheckBox.setChecked(val)

    def createButtonBox(self):

        applyButton = QPushButton("Apply Changes")
        applyButton.clicked.connect(self.main_window.applyChanges)
        closeButton = QPushButton("Close")
        closeButton.clicked.connect(self.hide)

        buttonLayout = QHBoxLayout()
        buttonLayout.addStretch(1)
        buttonLayout.addWidget(applyButton)
        buttonLayout.addWidget(closeButton)

        self.buttonBox = QWidget()
        self.buttonBox.setLayout(buttonLayout)

    def updateDialogValues(self):

        self.updateMasking()
        self.updateMaskingColor()
        self.updateColorMaps()
        self.updateColorMinMax()
        self.updateColorbarScale()
        self.updateDataIndicatorVisibility()
        self.updateHighlighting()
        self.updateHighlightColor()
        self.updateAlpha()
        self.updateSeed()
        self.updateBackgroundColor()
        self.updateColorBy()
        self.updateUniverseLevel()
        self.updateDomainTabs()
        self.updateOverlap()
        self.updateOverlapColor()

    def updateMasking(self):
        masking = self.model.activeView.masking

        self.maskingCheck.setChecked(masking)
        self.maskColorButton.setDisabled(not masking)

        if masking:
            self.cellTable.showColumn(4)
            self.matTable.showColumn(4)
        else:
            self.cellTable.hideColumn(4)
            self.matTable.hideColumn(4)

    def updateMaskingColor(self):
        color = self.model.activeView.maskBackground
        style_values = "border-radius: 8px; background-color: rgb{}"
        self.maskColorButton.setStyleSheet(style_values.format(str(color)))

    def updateHighlighting(self):
        highlighting = self.model.activeView.highlighting

        self.hlCheck.setChecked(highlighting)
        self.hlColorButton.setDisabled(not highlighting)
        self.alphaBox.setDisabled(not highlighting)
        self.seedBox.setDisabled(not highlighting)

        if highlighting:
            self.cellTable.showColumn(5)
            self.cellTable.hideColumn(2)
            self.cellTable.hideColumn(3)
            self.matTable.showColumn(5)
            self.matTable.hideColumn(2)
            self.matTable.hideColumn(3)
        else:
            self.cellTable.hideColumn(5)
            self.cellTable.showColumn(2)
            self.cellTable.showColumn(3)
            self.matTable.hideColumn(5)
            self.matTable.showColumn(2)
            self.matTable.showColumn(3)

    def updateHighlightColor(self):
        color = self.model.activeView.highlightBackground
        style_values = "border-radius: 8px; background-color: rgb{}"
        self.hlColorButton.setStyleSheet(style_values.format(str(color)))

    def updateAlpha(self):
        self.alphaBox.setValue(self.model.activeView.highlightAlpha)

    def updateSeed(self):
        self.seedBox.setValue(self.model.activeView.highlightSeed)

    def updateBackgroundColor(self):
        color = self.model.activeView.domainBackground
        self.bgButton.setStyleSheet("border-radius: 8px;"
                                    "background-color: rgb%s" % (str(color)))

    def updateOverlapColor(self):
        color = self.model.activeView.overlap_color
        self.overlapColorButton.setStyleSheet("border-radius: 8px;"
                                              "background-color: rgb%s" %
                                              (str(color)))

    def updateOverlap(self):
        colorby = self.model.activeView.colorby
        overlap_val = self.model.activeView.color_overlaps
        if colorby in ('cell', 'material'):
            self.overlapCheck.setChecked(overlap_val)

    def updateColorBy(self):
        colorby = self.model.activeView.colorby
        self.colorbyBox.setCurrentText(colorby)
        self.overlapCheck.setEnabled(colorby in ("cell", "material"))
        self.universeLevelBox.setEnabled(colorby == 'cell')

    def updateUniverseLevel(self):
        level = self.model.activeView.level
        if level == -1:
            self.universeLevelBox.setCurrentText('all')
        else:
            self.universeLevelBox.setCurrentText(str(level))

    def updateDomainTabs(self):
        self.cellTable.setModel(self.main_window.cellsModel)
        self.matTable.setModel(self.main_window.materialsModel)
Exemple #25
0
    def CreateSliceTabs(self):
        self.showslicecheckbox = QCheckBox()
        self.showslicecheckbox.setText("Show Slice")
        self.showslicecheckbox.clicked.connect(self.showSlice)

        self.sliceindexspinBox = QDoubleSpinBox()
        self.sliceindex = 0
        self.sliceindexspinBox.setValue(self.sliceindex)
        self.sliceindexspinBox.setDecimals(0)
        self.sliceindexspinBox.setSingleStep(1)
        self.sliceindexspinBox.setRange(0, 20)
        self.sliceindexspinBox.valueChanged.connect(self.onSliceIndexChanged)

        self.SliceLabelComboBox = QComboBox()
        self.SliceLabelComboBox.activated.connect(self.onSliceComboSelchange)
        self.sliceaxis = ["h", "k", "l"]
        self.SliceLabelComboBox.addItems(self.sliceaxis)

        self.sliceTabWidget = QTabWidget()
        tab1 = QWidget()
        layout1 = QGridLayout()
        layout1.addWidget(self.showslicecheckbox, 0, 0, 1, 1)
        layout1.addWidget(self.SliceLabelComboBox, 0, 1, 1, 1)
        layout1.addWidget(self.sliceindexspinBox, 0, 2, 1, 1)
        tab1.setLayout(layout1)

        tab2 = QWidget()
        layout2 = QGridLayout()

        self.hvec_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.hvecval = 2.0
        self.hvec_spinBox.setValue(self.hvecval)
        self.hvec_spinBox.setDecimals(2)
        self.hvec_spinBox.setSingleStep(0.5)
        self.hvec_spinBox.setRange(-100.0, 10.0)
        self.hvec_spinBox.valueChanged.connect(self.onHvecChanged)
        self.hvec_Label = QLabel()
        self.hvec_Label.setText("H")
        layout2.addWidget(self.hvec_Label, 0, 0, 1, 1)
        layout2.addWidget(self.hvec_spinBox, 0, 1, 1, 1)

        self.kvec_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.kvecval = 0.0
        self.kvec_spinBox.setValue(self.kvecval)
        self.kvec_spinBox.setDecimals(2)
        self.kvec_spinBox.setSingleStep(0.5)
        self.kvec_spinBox.setRange(-100.0, 100.0)
        self.kvec_spinBox.valueChanged.connect(self.onKvecChanged)
        self.kvec_Label = QLabel()
        self.kvec_Label.setText("K")
        layout2.addWidget(self.kvec_Label, 1, 0, 1, 1)
        layout2.addWidget(self.kvec_spinBox, 1, 1, 1, 1)

        self.lvec_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.lvecval = 0.0
        self.lvec_spinBox.setValue(self.lvecval)
        self.lvec_spinBox.setDecimals(2)
        self.lvec_spinBox.setSingleStep(0.5)
        self.lvec_spinBox.setRange(-100.0, 100.0)
        self.lvec_spinBox.valueChanged.connect(self.onLvecChanged)
        self.lvec_Label = QLabel()
        self.lvec_Label.setText("L")
        layout2.addWidget(self.lvec_Label, 2, 0, 1, 1)
        layout2.addWidget(self.lvec_spinBox, 2, 1, 1, 1)

        self.hkldist_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.hkldistval = 0.0
        self.hkldist_spinBox.setValue(self.hkldistval)
        self.hkldist_spinBox.setDecimals(2)
        self.hkldist_spinBox.setSingleStep(0.5)
        self.hkldist_spinBox.setRange(-100.0, 100.0)
        self.hkldist_spinBox.valueChanged.connect(self.onHKLdistChanged)
        self.hkldist_Label = QLabel()
        self.hkldist_Label.setText("Distance from Origin")
        layout2.addWidget(self.hkldist_Label, 3, 0, 1, 1)
        layout2.addWidget(self.hkldist_spinBox, 3, 1, 1, 1)

        self.clipwidth_spinBox = QDoubleSpinBox(self.sliceTabWidget)
        self.clipwidthval = 0.5
        self.clipwidth_spinBox.setValue(self.clipwidthval)
        self.clipwidth_spinBox.setDecimals(2)
        self.clipwidth_spinBox.setSingleStep(0.05)
        self.clipwidth_spinBox.setRange(0.0, 100.0)
        self.clipwidth_spinBox.valueChanged.connect(self.onClipwidthChanged)
        self.clipwidth_Label = QLabel()
        self.clipwidth_Label.setText("Clip Plane Width")
        layout2.addWidget(self.clipwidth_Label, 4, 0, 1, 1)
        layout2.addWidget(self.clipwidth_spinBox, 4, 1, 1, 1)

        self.ClipBox = QGroupBox("Normal Vector to Clip Plane")
        self.ClipBox.setLayout(layout2)

        layout3 = QGridLayout()
        self.ClipPlaneChkBox = QCheckBox(self.sliceTabWidget)
        self.ClipPlaneChkBox.setText(
            "Use clip plane normal to HKL vector pointing out")
        self.ClipPlaneChkBox.clicked.connect(self.onClipPlaneChkBox)

        layout3.addWidget(self.ClipPlaneChkBox, 0, 0)
        layout3.addWidget(self.ClipBox, 1, 0)
        tab2.setLayout(layout3)
        self.sliceTabWidget.addTab(tab1, "Explicit Slicing")
        self.sliceTabWidget.addTab(tab2, "Clip Plane Slicing")
        self.ClipBox.setDisabled(True)
Exemple #26
0
    def createGeneralTab(self):

        main_window = self.main_window

        # Masking options
        self.maskingCheck = QCheckBox('')
        self.maskingCheck.stateChanged.connect(main_window.toggleMasking)

        button_width = self.font_metric.boundingRect("XXXXXXXXXX").width()
        self.maskColorButton = QPushButton()
        self.maskColorButton.setCursor(QtCore.Qt.PointingHandCursor)
        self.maskColorButton.setFixedWidth(button_width)
        self.maskColorButton.setFixedHeight(self.font_metric.height() * 1.5)
        self.maskColorButton.clicked.connect(main_window.editMaskingColor)

        # Highlighting options
        self.hlCheck = QCheckBox('')
        self.hlCheck.stateChanged.connect(main_window.toggleHighlighting)

        self.hlColorButton = QPushButton()
        self.hlColorButton.setCursor(QtCore.Qt.PointingHandCursor)
        self.hlColorButton.setFixedWidth(button_width)
        self.hlColorButton.setFixedHeight(self.font_metric.height() * 1.5)
        self.hlColorButton.clicked.connect(main_window.editHighlightColor)

        self.alphaBox = QDoubleSpinBox()
        self.alphaBox.setRange(0, 1)
        self.alphaBox.setSingleStep(.05)
        self.alphaBox.valueChanged.connect(main_window.editAlpha)

        self.seedBox = QSpinBox()
        self.seedBox.setRange(1, 999)
        self.seedBox.valueChanged.connect(main_window.editSeed)

        # General options
        self.bgButton = QPushButton()
        self.bgButton.setCursor(QtCore.Qt.PointingHandCursor)
        self.bgButton.setFixedWidth(button_width)
        self.bgButton.setFixedHeight(self.font_metric.height() * 1.5)
        self.bgButton.clicked.connect(main_window.editBackgroundColor)

        self.colorbyBox = QComboBox(self)
        self.colorbyBox.addItem("material")
        self.colorbyBox.addItem("cell")
        self.colorbyBox.addItem("temperature")
        self.colorbyBox.addItem("density")
        self.colorbyBox.currentTextChanged[str].connect(
            main_window.editColorBy)

        self.universeLevelBox = QComboBox(self)
        self.universeLevelBox.addItem('all')
        for i in range(self.model.max_universe_levels):
            self.universeLevelBox.addItem(str(i))
        self.universeLevelBox.currentTextChanged[str].connect(
            main_window.editUniverseLevel)

        # Overlap plotting
        self.overlapCheck = QCheckBox('', self)
        overlap_connector = partial(main_window.toggleOverlaps)
        self.overlapCheck.stateChanged.connect(overlap_connector)

        self.overlapColorButton = QPushButton()
        self.overlapColorButton.setCursor(QtCore.Qt.PointingHandCursor)
        self.overlapColorButton.setFixedWidth(button_width)
        self.overlapColorButton.setFixedHeight(self.font_metric.height() * 1.5)
        self.overlapColorButton.clicked.connect(main_window.editOverlapColor)

        self.colorResetButton = QPushButton("&Reset Colors")
        self.colorResetButton.setCursor(QtCore.Qt.PointingHandCursor)
        self.colorResetButton.clicked.connect(main_window.resetColors)

        formLayout = QFormLayout()
        formLayout.setAlignment(QtCore.Qt.AlignHCenter)
        formLayout.setFormAlignment(QtCore.Qt.AlignHCenter)
        formLayout.setLabelAlignment(QtCore.Qt.AlignLeft)

        formLayout.addRow('Masking:', self.maskingCheck)
        formLayout.addRow('Mask Color:', self.maskColorButton)
        formLayout.addRow(HorizontalLine())
        formLayout.addRow('Highlighting:', self.hlCheck)
        formLayout.addRow('Highlight Color:', self.hlColorButton)
        formLayout.addRow('Highlight Alpha:', self.alphaBox)
        formLayout.addRow('Highlight Seed:', self.seedBox)
        formLayout.addRow(HorizontalLine())
        formLayout.addRow('Background Color:          ', self.bgButton)
        formLayout.addRow(HorizontalLine())
        formLayout.addRow('Show Overlaps:', self.overlapCheck)
        formLayout.addRow('Overlap Color:', self.overlapColorButton)
        formLayout.addRow(HorizontalLine())
        formLayout.addRow('Color Plot By:', self.colorbyBox)
        formLayout.addRow('Universe Level:', self.universeLevelBox)
        formLayout.addRow(self.colorResetButton, None)

        generalLayout = QHBoxLayout()
        innerWidget = QWidget()
        generalLayout.setAlignment(QtCore.Qt.AlignVCenter)
        innerWidget.setLayout(formLayout)
        generalLayout.addStretch(1)
        generalLayout.addWidget(innerWidget)
        generalLayout.addStretch(1)

        self.generalTab = QWidget()
        self.generalTab.setLayout(generalLayout)
Exemple #27
0
class SCOUTS(QMainWindow):
    """Main Window Widget for SCOUTS."""
    style = {
        'title': 'QLabel {font-size: 18pt; font-weight: 600}',
        'header': 'QLabel {font-size: 12pt; font-weight: 520}',
        'label': 'QLabel {font-size: 10pt}',
        'button': 'QPushButton {font-size: 10pt}',
        'md button': 'QPushButton {font-size: 12pt}',
        'run button': 'QPushButton {font-size: 18pt; font-weight: 600}',
        'line edit': 'QLineEdit {font-size: 10pt}',
        'checkbox': 'QCheckBox {font-size: 10pt}',
        'radio button': 'QRadioButton {font-size: 10pt}'
    }

    def __init__(self) -> None:
        """SCOUTS Constructor. Defines all aspects of the GUI."""

        # ###
        # ### Main Window setup
        # ###

        # Inherits from QMainWindow
        super().__init__()
        self.rootdir = get_project_root()
        self.threadpool = QThreadPool()
        # Sets values for QMainWindow
        self.setWindowTitle("SCOUTS")
        self.setWindowIcon(
            QIcon(
                os.path.abspath(os.path.join(self.rootdir, 'src',
                                             'scouts.ico'))))
        # Creates StackedWidget as QMainWindow's central widget
        self.stacked_pages = QStackedWidget(self)
        self.setCentralWidget(self.stacked_pages)
        # Creates Widgets for individual "pages" and adds them to the StackedWidget
        self.main_page = QWidget()
        self.samples_page = QWidget()
        self.gating_page = QWidget()
        self.pages = (self.main_page, self.samples_page, self.gating_page)
        for page in self.pages:
            self.stacked_pages.addWidget(page)
        # ## Sets widget at program startup
        self.stacked_pages.setCurrentWidget(self.main_page)

        # ###
        # ### MAIN PAGE
        # ###

        # Main page layout
        self.main_layout = QVBoxLayout(self.main_page)

        # Title section
        # Title
        self.title = QLabel(self.main_page)
        self.title.setText('SCOUTS - Single Cell Outlier Selector')
        self.title.setStyleSheet(self.style['title'])
        self.title.adjustSize()
        self.main_layout.addWidget(self.title)

        # ## Input section
        # Input header
        self.input_header = QLabel(self.main_page)
        self.input_header.setText('Input settings')
        self.input_header.setStyleSheet(self.style['header'])
        self.main_layout.addChildWidget(self.input_header)
        self.input_header.adjustSize()
        self.main_layout.addWidget(self.input_header)
        # Input frame
        self.input_frame = QFrame(self.main_page)
        self.input_frame.setFrameShape(QFrame.StyledPanel)
        self.input_frame.setLayout(QFormLayout())
        self.main_layout.addWidget(self.input_frame)
        # Input button
        self.input_button = QPushButton(self.main_page)
        self.input_button.setStyleSheet(self.style['button'])
        self.set_icon(self.input_button, 'x-office-spreadsheet')
        self.input_button.setObjectName('input')
        self.input_button.setText(' Select input file (.xlsx or .csv)')
        self.input_button.clicked.connect(self.get_path)
        # Input path box
        self.input_path = QLineEdit(self.main_page)
        self.input_path.setObjectName('input_path')
        self.input_path.setStyleSheet(self.style['line edit'])
        # Go to sample naming page
        self.samples_button = QPushButton(self.main_page)
        self.samples_button.setStyleSheet(self.style['button'])
        self.set_icon(self.samples_button, 'preferences-other')
        self.samples_button.setText(' Name samples...')
        self.samples_button.clicked.connect(self.goto_samples_page)
        # Go to gating page
        self.gates_button = QPushButton(self.main_page)
        self.gates_button.setStyleSheet(self.style['button'])
        self.set_icon(self.gates_button, 'preferences-other')
        self.gates_button.setText(' Gating && outlier options...')
        self.gates_button.clicked.connect(self.goto_gates_page)
        # Add widgets above to input frame Layout
        self.input_frame.layout().addRow(self.input_button, self.input_path)
        self.input_frame.layout().addRow(self.samples_button)
        self.input_frame.layout().addRow(self.gates_button)

        # ## Analysis section
        # Analysis header
        self.analysis_header = QLabel(self.main_page)
        self.analysis_header.setText('Analysis settings')
        self.analysis_header.setStyleSheet(self.style['header'])
        self.analysis_header.adjustSize()
        self.main_layout.addWidget(self.analysis_header)
        # Analysis frame
        self.analysis_frame = QFrame(self.main_page)
        self.analysis_frame.setFrameShape(QFrame.StyledPanel)
        self.analysis_frame.setLayout(QVBoxLayout())
        self.main_layout.addWidget(self.analysis_frame)
        # Cutoff text
        self.cutoff_text = QLabel(self.main_page)
        self.cutoff_text.setText('Type of outlier to select:')
        self.cutoff_text.setToolTip(
            'Choose whether to select outliers using the cutoff value from a reference\n'
            'sample (OutR) or by using the cutoff value calculated for each sample\n'
            'individually (OutS)')
        self.cutoff_text.setStyleSheet(self.style['label'])
        # Cutoff button group
        self.cutoff_group = QButtonGroup(self)
        # Cutoff by sample
        self.cutoff_sample = QRadioButton(self.main_page)
        self.cutoff_sample.setText('OutS')
        self.cutoff_sample.setObjectName('sample')
        self.cutoff_sample.setStyleSheet(self.style['radio button'])
        self.cutoff_sample.setChecked(True)
        self.cutoff_group.addButton(self.cutoff_sample)
        # Cutoff by reference
        self.cutoff_reference = QRadioButton(self.main_page)
        self.cutoff_reference.setText('OutR')
        self.cutoff_reference.setObjectName('ref')
        self.cutoff_reference.setStyleSheet(self.style['radio button'])
        self.cutoff_group.addButton(self.cutoff_reference)
        # Both cutoffs
        self.cutoff_both = QRadioButton(self.main_page)
        self.cutoff_both.setText('both')
        self.cutoff_both.setObjectName('sample ref')
        self.cutoff_both.setStyleSheet(self.style['radio button'])
        self.cutoff_group.addButton(self.cutoff_both)
        # Markers text
        self.markers_text = QLabel(self.main_page)
        self.markers_text.setStyleSheet(self.style['label'])
        self.markers_text.setText('Show results for:')
        self.markers_text.setToolTip(
            'Individual markers: for each marker, select outliers\n'
            'Any marker: select cells that are outliers for AT LEAST one marker'
        )
        # Markers button group
        self.markers_group = QButtonGroup(self)
        # Single marker
        self.single_marker = QRadioButton(self.main_page)
        self.single_marker.setText('individual markers')
        self.single_marker.setObjectName('single')
        self.single_marker.setStyleSheet(self.style['radio button'])
        self.single_marker.setChecked(True)
        self.markers_group.addButton(self.single_marker)
        # Any marker
        self.any_marker = QRadioButton(self.main_page)
        self.any_marker.setText('any marker')
        self.any_marker.setObjectName('any')
        self.any_marker.setStyleSheet(self.style['radio button'])
        self.markers_group.addButton(self.any_marker)
        # Both methods
        self.both_methods = QRadioButton(self.main_page)
        self.both_methods.setText('both')
        self.both_methods.setObjectName('single any')
        self.both_methods.setStyleSheet(self.style['radio button'])
        self.markers_group.addButton(self.both_methods)
        # Tukey text
        self.tukey_text = QLabel(self.main_page)
        self.tukey_text.setStyleSheet(self.style['label'])
        # Tukey button group
        self.tukey_text.setText('Tukey factor:')
        self.tukey_group = QButtonGroup(self)
        # Low Tukey value
        self.tukey_low = QRadioButton(self.main_page)
        self.tukey_low.setText('1.5')
        self.tukey_low.setStyleSheet(self.style['radio button'])
        self.tukey_low.setChecked(True)
        self.tukey_group.addButton(self.tukey_low)
        # High Tukey value
        self.tukey_high = QRadioButton(self.main_page)
        self.tukey_high.setText('3.0')
        self.tukey_high.setStyleSheet(self.style['radio button'])
        self.tukey_group.addButton(self.tukey_high)
        # Add widgets above to analysis frame layout
        self.analysis_frame.layout().addWidget(self.cutoff_text)
        self.cutoff_buttons = QHBoxLayout()
        for button in self.cutoff_group.buttons():
            self.cutoff_buttons.addWidget(button)
        self.analysis_frame.layout().addLayout(self.cutoff_buttons)
        self.analysis_frame.layout().addWidget(self.markers_text)
        self.markers_buttons = QHBoxLayout()
        for button in self.markers_group.buttons():
            self.markers_buttons.addWidget(button)
        self.analysis_frame.layout().addLayout(self.markers_buttons)
        self.analysis_frame.layout().addWidget(self.tukey_text)
        self.tukey_buttons = QHBoxLayout()
        for button in self.tukey_group.buttons():
            self.tukey_buttons.addWidget(button)
        self.tukey_buttons.addWidget(QLabel())  # aligns row with 2 buttons
        self.analysis_frame.layout().addLayout(self.tukey_buttons)

        # ## Output section
        # Output header
        self.output_header = QLabel(self.main_page)
        self.output_header.setText('Output settings')
        self.output_header.setStyleSheet(self.style['header'])
        self.output_header.adjustSize()
        self.main_layout.addWidget(self.output_header)
        # Output frame
        self.output_frame = QFrame(self.main_page)
        self.output_frame.setFrameShape(QFrame.StyledPanel)
        self.output_frame.setLayout(QFormLayout())
        self.main_layout.addWidget(self.output_frame)
        # Output button
        self.output_button = QPushButton(self.main_page)
        self.output_button.setStyleSheet(self.style['button'])
        self.set_icon(self.output_button, 'folder')
        self.output_button.setObjectName('output')
        self.output_button.setText(' Select output folder')
        self.output_button.clicked.connect(self.get_path)
        # Output path box
        self.output_path = QLineEdit(self.main_page)
        self.output_path.setStyleSheet(self.style['line edit'])
        # Generate CSV checkbox
        self.output_csv = QCheckBox(self.main_page)
        self.output_csv.setText('Export multiple text files (.csv)')
        self.output_csv.setStyleSheet(self.style['checkbox'])
        self.output_csv.setChecked(True)
        # Generate XLSX checkbox
        self.output_excel = QCheckBox(self.main_page)
        self.output_excel.setText('Export multiple Excel spreadsheets (.xlsx)')
        self.output_excel.setStyleSheet(self.style['checkbox'])
        self.output_excel.clicked.connect(self.enable_single_excel)
        # Generate single, large XLSX checkbox
        self.single_excel = QCheckBox(self.main_page)
        self.single_excel.setText(
            'Also save one multi-sheet Excel spreadsheet')
        self.single_excel.setToolTip(
            'After generating all Excel spreadsheets, SCOUTS combines them into '
            'a single\nExcel spreadsheet where each sheet corresponds to an output'
            'file from SCOUTS')
        self.single_excel.setStyleSheet(self.style['checkbox'])
        self.single_excel.setEnabled(False)
        self.single_excel.clicked.connect(self.memory_warning)
        # Add widgets above to output frame layout
        self.output_frame.layout().addRow(self.output_button, self.output_path)
        self.output_frame.layout().addRow(self.output_csv)
        self.output_frame.layout().addRow(self.output_excel)
        self.output_frame.layout().addRow(self.single_excel)

        # ## Run & help-quit section
        # Run button (stand-alone)
        self.run_button = QPushButton(self.main_page)
        self.set_icon(self.run_button, 'system-run')
        self.run_button.setText(' Run!')
        self.run_button.setStyleSheet(self.style['run button'])
        self.main_layout.addWidget(self.run_button)
        self.run_button.clicked.connect(self.run)
        # Help-quit frame (invisible)
        self.helpquit_frame = QFrame(self.main_page)
        self.helpquit_frame.setLayout(QHBoxLayout())
        self.helpquit_frame.layout().setMargin(0)
        self.main_layout.addWidget(self.helpquit_frame)
        # Help button
        self.help_button = QPushButton(self.main_page)
        self.set_icon(self.help_button, 'help-about')
        self.help_button.setText(' Help')
        self.help_button.setStyleSheet(self.style['md button'])
        self.help_button.clicked.connect(self.get_help)
        # Quit button
        self.quit_button = QPushButton(self.main_page)
        self.set_icon(self.quit_button, 'process-stop')
        self.quit_button.setText(' Quit')
        self.quit_button.setStyleSheet(self.style['md button'])
        self.quit_button.clicked.connect(self.close)
        # Add widgets above to help-quit layout
        self.helpquit_frame.layout().addWidget(self.help_button)
        self.helpquit_frame.layout().addWidget(self.quit_button)

        # ###
        # ### SAMPLES PAGE
        # ###

        # Samples page layout
        self.samples_layout = QVBoxLayout(self.samples_page)

        # ## Title section
        # Title
        self.samples_title = QLabel(self.samples_page)
        self.samples_title.setText('Name your samples')
        self.samples_title.setStyleSheet(self.style['title'])
        self.samples_title.adjustSize()
        self.samples_layout.addWidget(self.samples_title)
        # Subtitle
        self.samples_subtitle = QLabel(self.samples_page)
        string = (
            'Please name the samples to be analysed by SCOUTS.\n\nSCOUTS searches the first '
            'column of your data\nand locates the exact string as part of the sample name.'
        )
        self.samples_subtitle.setText(string)
        self.samples_subtitle.setStyleSheet(self.style['label'])
        self.samples_subtitle.adjustSize()
        self.samples_layout.addWidget(self.samples_subtitle)

        # ## Sample addition section
        # Sample addition frame
        self.samples_frame = QFrame(self.samples_page)
        self.samples_frame.setFrameShape(QFrame.StyledPanel)
        self.samples_frame.setLayout(QGridLayout())
        self.samples_layout.addWidget(self.samples_frame)
        # Sample name box
        self.sample_name = QLineEdit(self.samples_page)
        self.sample_name.setStyleSheet(self.style['line edit'])
        self.sample_name.setPlaceholderText('Sample name ...')
        # Reference check
        self.is_reference = QCheckBox(self.samples_page)
        self.is_reference.setText('Reference?')
        self.is_reference.setStyleSheet(self.style['checkbox'])
        # Add sample to table
        self.add_sample_button = QPushButton(self.samples_page)
        QShortcut(QKeySequence("Return"), self.add_sample_button,
                  self.write_to_sample_table)
        self.set_icon(self.add_sample_button, 'list-add')
        self.add_sample_button.setText(' Add sample (Enter)')
        self.add_sample_button.setStyleSheet(self.style['button'])
        self.add_sample_button.clicked.connect(self.write_to_sample_table)
        # Remove sample from table
        self.remove_sample_button = QPushButton(self.samples_page)
        QShortcut(QKeySequence("Delete"), self.remove_sample_button,
                  self.remove_from_sample_table)
        self.set_icon(self.remove_sample_button, 'list-remove')
        self.remove_sample_button.setText(' Remove sample (Del)')
        self.remove_sample_button.setStyleSheet(self.style['button'])
        self.remove_sample_button.clicked.connect(
            self.remove_from_sample_table)
        # Add widgets above to sample addition layout
        self.samples_frame.layout().addWidget(self.sample_name, 0, 0)
        self.samples_frame.layout().addWidget(self.is_reference, 1, 0)
        self.samples_frame.layout().addWidget(self.add_sample_button, 0, 1)
        self.samples_frame.layout().addWidget(self.remove_sample_button, 1, 1)

        # ## Sample table
        self.sample_table = QTableWidget(self.samples_page)
        self.sample_table.setColumnCount(2)
        self.sample_table.setHorizontalHeaderItem(0,
                                                  QTableWidgetItem('Sample'))
        self.sample_table.setHorizontalHeaderItem(
            1, QTableWidgetItem('Reference?'))
        self.sample_table.horizontalHeader().setSectionResizeMode(
            0, QHeaderView.Stretch)
        self.sample_table.horizontalHeader().setSectionResizeMode(
            1, QHeaderView.ResizeToContents)
        self.samples_layout.addWidget(self.sample_table)

        # ## Save & clear buttons
        # Save & clear frame (invisible)
        self.saveclear_frame = QFrame(self.samples_page)
        self.saveclear_frame.setLayout(QHBoxLayout())
        self.saveclear_frame.layout().setMargin(0)
        self.samples_layout.addWidget(self.saveclear_frame)
        # Clear samples button
        self.clear_samples = QPushButton(self.samples_page)
        self.set_icon(self.clear_samples, 'edit-delete')
        self.clear_samples.setText(' Clear table')
        self.clear_samples.setStyleSheet(self.style['md button'])
        self.clear_samples.clicked.connect(self.prompt_clear_data)
        # Save samples button
        self.save_samples = QPushButton(self.samples_page)
        self.set_icon(self.save_samples, 'document-save')
        self.save_samples.setText(' Save samples')
        self.save_samples.setStyleSheet(self.style['md button'])
        self.save_samples.clicked.connect(self.goto_main_page)
        # Add widgets above to save & clear layout
        self.saveclear_frame.layout().addWidget(self.clear_samples)
        self.saveclear_frame.layout().addWidget(self.save_samples)

        # ###
        # ### GATING PAGE
        # ###

        # Gating page layout
        self.gating_layout = QVBoxLayout(self.gating_page)

        # ## Title section
        # Title
        self.gates_title = QLabel(self.gating_page)
        self.gates_title.setText('Gating & outlier options')
        self.gates_title.setStyleSheet(self.style['title'])
        self.gates_title.adjustSize()
        self.gating_layout.addWidget(self.gates_title)

        # ## Gating options section
        # Gating header
        self.gate_header = QLabel(self.gating_page)
        self.gate_header.setText('Gating')
        self.gate_header.setStyleSheet(self.style['header'])
        self.gate_header.adjustSize()
        self.gating_layout.addWidget(self.gate_header)

        # Gating frame
        self.gate_frame = QFrame(self.gating_page)
        self.gate_frame.setFrameShape(QFrame.StyledPanel)
        self.gate_frame.setLayout(QFormLayout())
        self.gating_layout.addWidget(self.gate_frame)
        # Gating button group
        self.gating_group = QButtonGroup(self)
        # Do not gate samples
        self.no_gates = QRadioButton(self.gating_page)
        self.no_gates.setObjectName('no_gate')
        self.no_gates.setText("Don't gate samples")
        self.no_gates.setStyleSheet(self.style['radio button'])
        self.no_gates.setChecked(True)
        self.gating_group.addButton(self.no_gates)
        self.no_gates.clicked.connect(self.activate_gate)
        # CyToF gating
        self.cytof_gates = QRadioButton(self.gating_page)
        self.cytof_gates.setObjectName('cytof')
        self.cytof_gates.setText('Mass Cytometry gating')
        self.cytof_gates.setStyleSheet(self.style['radio button'])
        self.cytof_gates.setToolTip(
            'Exclude cells for which the average expression of all\n'
            'markers is below the selected value')
        self.gating_group.addButton(self.cytof_gates)
        self.cytof_gates.clicked.connect(self.activate_gate)
        # CyToF gating spinbox
        self.cytof_gates_value = QDoubleSpinBox(self.gating_page)
        self.cytof_gates_value.setMinimum(0)
        self.cytof_gates_value.setMaximum(1)
        self.cytof_gates_value.setValue(0.1)
        self.cytof_gates_value.setSingleStep(0.05)
        self.cytof_gates_value.setEnabled(False)
        # scRNA-Seq gating
        self.rnaseq_gates = QRadioButton(self.gating_page)
        self.rnaseq_gates.setText('scRNA-Seq gating')
        self.rnaseq_gates.setStyleSheet(self.style['radio button'])
        self.rnaseq_gates.setToolTip(
            'When calculating cutoff, ignore reads below the selected value')
        self.rnaseq_gates.setObjectName('rnaseq')
        self.gating_group.addButton(self.rnaseq_gates)
        self.rnaseq_gates.clicked.connect(self.activate_gate)
        # scRNA-Seq gating spinbox
        self.rnaseq_gates_value = QDoubleSpinBox(self.gating_page)
        self.rnaseq_gates_value.setMinimum(0)
        self.rnaseq_gates_value.setMaximum(10)
        self.rnaseq_gates_value.setValue(0)
        self.rnaseq_gates_value.setSingleStep(1)
        self.rnaseq_gates_value.setEnabled(False)
        # export gated population checkbox
        self.export_gated = QCheckBox(self.gating_page)
        self.export_gated.setText('Export gated cells as an output file')
        self.export_gated.setStyleSheet(self.style['checkbox'])
        self.export_gated.setEnabled(False)
        # Add widgets above to Gate frame layout
        self.gate_frame.layout().addRow(self.no_gates, QLabel())
        self.gate_frame.layout().addRow(self.cytof_gates,
                                        self.cytof_gates_value)
        self.gate_frame.layout().addRow(self.rnaseq_gates,
                                        self.rnaseq_gates_value)
        self.gate_frame.layout().addRow(self.export_gated, QLabel())

        # ## Outlier options section
        # Outlier header
        self.outlier_header = QLabel(self.gating_page)
        self.outlier_header.setText('Outliers')
        self.outlier_header.setStyleSheet(self.style['header'])
        self.outlier_header.adjustSize()
        self.gating_layout.addWidget(self.outlier_header)
        # Outlier frame
        self.outlier_frame = QFrame(self.gating_page)
        self.outlier_frame.setFrameShape(QFrame.StyledPanel)
        self.outlier_frame.setLayout(QVBoxLayout())
        self.gating_layout.addWidget(self.outlier_frame)
        # Top outliers information
        self.top_outliers = QLabel(self.gating_page)
        self.top_outliers.setStyleSheet(self.style['label'])
        self.top_outliers.setText(
            'By default, SCOUTS selects the top outliers from the population')
        self.top_outliers.setStyleSheet(self.style['label'])
        # Bottom outliers data
        self.bottom_outliers = QCheckBox(self.gating_page)
        self.bottom_outliers.setText('Include results for low outliers')
        self.bottom_outliers.setStyleSheet(self.style['checkbox'])
        # Non-outliers data
        self.not_outliers = QCheckBox(self.gating_page)
        self.not_outliers.setText('Include results for non-outliers')
        self.not_outliers.setStyleSheet(self.style['checkbox'])
        # Add widgets above to Gate frame layout
        self.outlier_frame.layout().addWidget(self.top_outliers)
        self.outlier_frame.layout().addWidget(self.bottom_outliers)
        self.outlier_frame.layout().addWidget(self.not_outliers)

        # ## Save/back button
        self.save_gates = QPushButton(self.gating_page)
        self.set_icon(self.save_gates, 'go-next')
        self.save_gates.setText(' Back to main menu')
        self.save_gates.setStyleSheet(self.style['md button'])
        self.gating_layout.addWidget(self.save_gates)
        self.save_gates.clicked.connect(self.goto_main_page)

        # ## Add empty label to take vertical space
        self.empty_label = QLabel(self.gating_page)
        self.empty_label.setSizePolicy(QSizePolicy.Expanding,
                                       QSizePolicy.Expanding)
        self.gating_layout.addWidget(self.empty_label)

    # ###
    # ### ICON SETTING
    # ###

    def set_icon(self, widget: QWidget, icon: str) -> None:
        """Associates an icon to a widget."""
        i = QIcon()
        i.addPixmap(
            QPixmap(
                os.path.abspath(
                    os.path.join(self.rootdir, 'src', 'default_icons',
                                 f'{icon}.svg'))))
        widget.setIcon(QIcon.fromTheme(icon, i))

    # ###
    # ### STACKED WIDGET PAGE SWITCHING
    # ###

    def goto_main_page(self) -> None:
        """Switches stacked widget pages to the main page."""
        self.stacked_pages.setCurrentWidget(self.main_page)

    def goto_samples_page(self) -> None:
        """Switches stacked widget pages to the samples table page."""
        self.stacked_pages.setCurrentWidget(self.samples_page)

    def goto_gates_page(self) -> None:
        """Switches stacked widget pages to the gating & other options page."""
        self.stacked_pages.setCurrentWidget(self.gating_page)

    # ###
    # ### MAIN PAGE GUI LOGIC
    # ###

    def get_path(self) -> None:
        """Opens a dialog box and sets the chosen file/folder path, depending on the caller widget."""
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        sender_name = self.sender().objectName()
        if sender_name == 'input':
            query, _ = QFileDialog.getOpenFileName(self,
                                                   "Select file",
                                                   "",
                                                   "All Files (*)",
                                                   options=options)
        elif sender_name == 'output':
            query = QFileDialog.getExistingDirectory(self,
                                                     "Select Directory",
                                                     options=options)
        else:
            return
        if query:
            getattr(self, f'{sender_name}_path').setText(query)

    def enable_single_excel(self) -> None:
        """Enables checkbox for generating a single Excel output."""
        if self.output_excel.isChecked():
            self.single_excel.setEnabled(True)
        else:
            self.single_excel.setEnabled(False)
            self.single_excel.setChecked(False)

    # ###
    # ### SAMPLE NAME/SAMPLE TABLE GUI LOGIC
    # ###

    def write_to_sample_table(self) -> None:
        """Writes data to sample table."""
        table = self.sample_table
        ref = 'no'
        sample = self.sample_name.text()
        if sample:
            for cell in range(table.rowCount()):
                item = table.item(cell, 0)
                if item.text() == sample:
                    self.same_sample()
                    return
            if self.is_reference.isChecked():
                for cell in range(table.rowCount()):
                    item = table.item(cell, 1)
                    if item.text() == 'yes':
                        self.more_than_one_reference()
                        return
                ref = 'yes'
            sample = QTableWidgetItem(sample)
            is_reference = QTableWidgetItem(ref)
            is_reference.setFlags(Qt.ItemIsEnabled)
            row_position = table.rowCount()
            table.insertRow(row_position)
            table.setItem(row_position, 0, sample)
            table.setItem(row_position, 1, is_reference)
            self.is_reference.setChecked(False)
            self.sample_name.setText('')

    def remove_from_sample_table(self) -> None:
        """Removes data from sample table."""
        table = self.sample_table
        rows = set(index.row() for index in table.selectedIndexes())
        for index in sorted(rows, reverse=True):
            self.sample_table.removeRow(index)

    def prompt_clear_data(self) -> None:
        """Prompts option to clear all data in the sample table."""
        if self.confirm_clear_data():
            table = self.sample_table
            while table.rowCount():
                self.sample_table.removeRow(0)

    # ###
    # ### GATING GUI LOGIC
    # ###

    def activate_gate(self) -> None:
        """Activates/deactivates buttons related to gating."""
        if self.sender().objectName() == 'no_gate':
            self.cytof_gates_value.setEnabled(False)
            self.rnaseq_gates_value.setEnabled(False)
            self.export_gated.setEnabled(False)
            self.export_gated.setChecked(False)
        elif self.sender().objectName() == 'cytof':
            self.cytof_gates_value.setEnabled(True)
            self.rnaseq_gates_value.setEnabled(False)
            self.export_gated.setEnabled(True)
        elif self.sender().objectName() == 'rnaseq':
            self.cytof_gates_value.setEnabled(False)
            self.rnaseq_gates_value.setEnabled(True)
            self.export_gated.setEnabled(True)

    # ###
    # ### CONNECT SCOUTS TO ANALYTICAL MODULES
    # ###

    def run(self) -> None:
        """Runs SCOUTS as a Worker, based on user input in the GUI."""
        try:
            data = self.parse_input()
        except Exception as error:
            trace = traceback.format_exc()
            self.propagate_error((error, trace))
        else:
            data['widget'] = self
            worker = Worker(func=start_scouts, **data)
            worker.signals.started.connect(self.analysis_has_started)
            worker.signals.finished.connect(self.analysis_has_finished)
            worker.signals.success.connect(self.success_message)
            worker.signals.error.connect(self.propagate_error)
            self.threadpool.start(worker)

    def parse_input(self) -> Dict:
        """Returns user input on the GUI as a dictionary."""
        # Input and output
        input_dict = {
            'input_file': str(self.input_path.text()),
            'output_folder': str(self.output_path.text())
        }
        if not input_dict['input_file'] or not input_dict['output_folder']:
            raise NoIOPathError
        # Set cutoff by reference or by sample rule
        input_dict['cutoff_rule'] = self.cutoff_group.checkedButton(
        ).objectName()  # 'sample', 'ref', 'sample ref'
        # Outliers for each individual marker or any marker in row
        input_dict['marker_rule'] = self.markers_group.checkedButton(
        ).objectName()  # 'single', 'any', 'single any'
        # Tukey factor used for calculating cutoff
        input_dict['tukey_factor'] = float(
            self.tukey_group.checkedButton().text())  # '1.5', '3.0'
        # Output settings
        input_dict['export_csv'] = True if self.output_csv.isChecked(
        ) else False
        input_dict['export_excel'] = True if self.output_excel.isChecked(
        ) else False
        input_dict['single_excel'] = True if self.single_excel.isChecked(
        ) else False
        # Retrieve samples from sample table
        input_dict['sample_list'] = []
        for tuples in self.yield_samples_from_table():
            input_dict['sample_list'].append(tuples)
        if not input_dict['sample_list']:
            raise NoSampleError
        # Set gate cutoff (if any)
        input_dict['gating'] = self.gating_group.checkedButton().objectName(
        )  # 'no_gate', 'cytof', 'rnaseq'
        input_dict['gate_cutoff_value'] = None
        if input_dict['gating'] != 'no_gate':
            input_dict['gate_cutoff_value'] = getattr(
                self, f'{input_dict["gating"]}_gates_value').value()
        input_dict['export_gated'] = True if self.export_gated.isChecked(
        ) else False
        # Generate results for non-outliers
        input_dict['non_outliers'] = False
        if self.not_outliers.isChecked():
            input_dict['non_outliers'] = True
        # Generate results for bottom outliers
        input_dict['bottom_outliers'] = False
        if self.bottom_outliers.isChecked():
            input_dict['bottom_outliers'] = True
        # return dictionary with all gathered inputs
        return input_dict

    def yield_samples_from_table(
            self) -> Generator[Tuple[str, str], None, None]:
        """Yields sample names from the sample table."""
        table = self.sample_table
        for cell in range(table.rowCount()):
            sample_name = table.item(cell, 0).text()
            sample_type = table.item(cell, 1).text()
            yield sample_name, sample_type

    # ###
    # ### MESSAGE BOXES
    # ###

    def analysis_has_started(self) -> None:
        """Disables run button while SCOUTS analysis is underway."""
        self.run_button.setText(' Working...')
        self.run_button.setEnabled(False)

    def analysis_has_finished(self) -> None:
        """Enables run button after SCOUTS analysis has finished."""
        self.run_button.setEnabled(True)
        self.run_button.setText(' Run!')

    def success_message(self) -> None:
        """Info message box used when SCOUTS finished without errors."""
        title = "Analysis finished!"
        mes = "Your analysis has finished. No errors were reported."
        if self.stacked_pages.isEnabled() is True:
            QMessageBox.information(self, title, mes)

    def memory_warning(self) -> None:
        """Warning message box used when user wants to generate a single excel file."""
        if self.sender().isChecked():
            title = 'Memory warning!'
            mes = (
                "Depending on your dataset, this option can consume a LOT of memory and take"
                " a long time to process. Please make sure that your computer can handle it!"
            )
            QMessageBox.information(self, title, mes)

    def same_sample(self) -> None:
        """Error message box used when the user tries to input the same sample twice in the sample table."""
        title = 'Error: sample name already in table'
        mes = (
            "Sorry, you can't do this because this sample name is already in the table. "
            "Please select a different name.")
        QMessageBox.critical(self, title, mes)

    def more_than_one_reference(self) -> None:
        """Error message box used when the user tries to input two reference samples in the sample table."""
        title = "Error: more than one reference selected"
        mes = (
            "Sorry, you can't do this because there is already a reference column in the table. "
            "Please remove it before adding a reference.")
        QMessageBox.critical(self, title, mes)

    def confirm_clear_data(self) -> bool:
        """Question message box used to confirm user action of clearing sample table."""
        title = 'Confirm Action'
        mes = "Table will be cleared. Are you sure?"
        reply = QMessageBox.question(self, title, mes,
                                     QMessageBox.Yes | QMessageBox.No,
                                     QMessageBox.No)
        if reply == QMessageBox.Yes:
            return True
        return False

    # ###
    # ### EXCEPTIONS & ERRORS
    # ###

    def propagate_error(self, error: Tuple[Exception, str]) -> None:
        """Calls the appropriate error message box based on type of Exception raised."""
        if isinstance(error[0], NoIOPathError):
            self.no_io_path_error_message()
        elif isinstance(error[0], NoReferenceError):
            self.no_reference_error_message()
        elif isinstance(error[0], NoSampleError):
            self.no_sample_error_message()
        elif isinstance(error[0], PandasInputError):
            self.pandas_input_error_message()
        elif isinstance(error[0], SampleNamingError):
            self.sample_naming_error_message()
        else:
            self.generic_error_message(error)

    def no_io_path_error_message(self) -> None:
        """Message displayed when the user did not include an input file path, or an output folder path."""
        title = 'Error: no file/folder'
        message = ("Sorry, no input file and/or output folder was provided. "
                   "Please add the path to the necessary file/folder.")
        QMessageBox.critical(self, title, message)

    def no_reference_error_message(self) -> None:
        """Message displayed when the user wants to analyse cutoff based on a reference, but did not specify what
        sample corresponds to the reference."""
        title = "Error: No reference selected"
        message = (
            "Sorry, no reference sample was found on the sample list, but analysis was set to "
            "reference. Please add a reference sample, or change the rule for cutoff calculation."
        )
        QMessageBox.critical(self, title, message)

    def no_sample_error_message(self) -> None:
        """Message displayed when the user did not add any samples to the sample table."""
        title = "Error: No samples selected"
        message = (
            "Sorry, the analysis cannot be performed because no sample names were input. "
            "Please add your sample names.")
        QMessageBox.critical(self, title, message)

    def pandas_input_error_message(self) -> None:
        """Message displayed when the input file cannot be read (likely because it is not a Excel or csv file)."""
        title = 'Error: unexpected input file'
        message = (
            "Sorry, the input file could not be read. Please make sure that "
            "the data is save in a valid format (supported formats are: "
            ".csv, .xlsx).")
        QMessageBox.critical(self, title, message)

    def sample_naming_error_message(self) -> None:
        """Message displayed when none of the sample names passed by the user are found in the input DataFrame."""
        title = 'Error: sample names not in input file'
        message = (
            "Sorry, your sample names were not found in the input file. Please "
            "make sure that the names were typed correctly (case-sensitive).")
        QMessageBox.critical(self, title, message)

    def generic_error_message(self, error: Tuple[Exception, str]) -> None:
        """Error message box used to display any error message (including traceback) for any uncaught errors."""
        title = 'An error occurred!'
        name, trace = error
        QMessageBox.critical(self, title,
                             f"{str(name)}\n\nfull traceback:\n{trace}")

    def not_implemented_error_message(self) -> None:
        """Error message box used when the user accesses a functionality that hasn't been implemented yet."""
        title = "Not yet implemented"
        mes = "Sorry, this functionality has not been implemented yet."
        QMessageBox.critical(self, title, mes)

    # ###
    # ### HELP & QUIT
    # ###

    @staticmethod
    def get_help() -> None:
        """Opens SCOUTS documentation on the browser. Called when the user clicks the "help" button"""
        webbrowser.open('https://scouts.readthedocs.io/en/master/')

    def closeEvent(self, event: QEvent) -> None:
        """Defines the message box for when the user wants to quit SCOUTS."""
        title = 'Quit SCOUTS'
        mes = "Are you sure you want to quit?"
        reply = QMessageBox.question(self, title, mes,
                                     QMessageBox.Yes | QMessageBox.No,
                                     QMessageBox.No)
        if reply == QMessageBox.Yes:
            self.stacked_pages.setEnabled(False)
            message = self.quit_message()
            waiter = Waiter(waiter_func=self.threadpool.activeThreadCount)
            waiter.signals.started.connect(message.show)
            waiter.signals.finished.connect(message.destroy)
            waiter.signals.finished.connect(sys.exit)
            self.threadpool.start(waiter)
        event.ignore()

    def quit_message(self) -> QDialog:
        """Displays a window while SCOUTS is exiting"""
        message = QDialog(self)
        message.setWindowTitle('Exiting SCOUTS')
        message.resize(300, 50)
        label = QLabel('SCOUTS is exiting, please wait...', message)
        label.setStyleSheet(self.style['label'])
        label.adjustSize()
        label.setAlignment(Qt.AlignCenter)
        label.move(int((message.width() - label.width()) / 2),
                   int((message.height() - label.height()) / 2))
        return message
    def _gui(self):
        layout = QVBoxLayout()
        self.setLayout(layout)

        slider_layout = QHBoxLayout()
        layout.addLayout(slider_layout)

        slider = ClickSlider(self)
        slider.setOrientation(Qt.Horizontal)
        slider.valueChanged.connect(self._slider_changed)
        slider_layout.addWidget(slider)
        self.slider = slider

        max_time = QLabel(self)
        self.max_time = max_time
        max_time.setText('--:--')
        slider_layout.addWidget(max_time)

        form = QFormLayout()
        layout.addLayout(form)

        time = QTimeEdit(self)
        time.setDisplayFormat('mm:ss.zzz')
        time.setAlignment(Qt.AlignRight)
        time.timeChanged.connect(self._edit_time_changed)
        self.time = time
        form.addRow(QLabel('Time', self),time)

        speed = QDoubleSpinBox(self)
        speed.setMinimum(0.1)
        speed.setMaximum(2.0)
        speed.setSingleStep(0.1)
        speed.setValue(1)
        speed.setAlignment(Qt.AlignRight)
        self.speed = speed
        speed.valueChanged.connect(self._speed_changed)
        form.addRow(QLabel('Speed', self), speed)

        playback = QHBoxLayout()
        layout.addLayout(playback)

        back_fast = QToolButton(self)
        playback.addWidget(back_fast)
        abf = QAction('<<', back_fast)
        abf.setShortcut(QKeySequence(Qt.Key_F1))
        abf.triggered.connect(self.back_fast)
        back_fast.setDefaultAction(abf)

        back = QToolButton(self)
        playback.addWidget(back)
        ab = QAction('<', back)
        ab.setShortcut(QKeySequence(Qt.Key_F2))
        ab.triggered.connect(self.back)
        back.setDefaultAction(ab)

        play = QToolButton(self)
        playback.addWidget(play)
        self.play_button = play
        play.setCheckable(True)
        play.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
        ap = QAction('Play', play)
        ap.setShortcut(QKeySequence(Qt.Key_F5))
        ap.triggered.connect(self.play)
        play.setDefaultAction(ap)

        forward = QToolButton(self)
        playback.addWidget(forward)
        af = QAction('>', forward)
        af.setShortcut(QKeySequence(Qt.Key_F3))
        af.triggered.connect(self.forward)
        forward.setDefaultAction(af)

        forward_fast = QToolButton(self)
        playback.addWidget(forward_fast)
        aff = QAction('>>', forward_fast)
        aff.setShortcut(QKeySequence(Qt.Key_F4))
        aff.triggered.connect(self.forward_fast)
        forward_fast.setDefaultAction(aff)

        speed_up = QAction('Speed up', forward_fast)
        speed_up.setShortcut(QKeySequence(Qt.Key_F7))
        speed_up.triggered.connect(self.speed.stepUp)

        speed_down = QAction('Speed down', forward_fast)
        speed_down.setShortcut(QKeySequence(Qt.Key_F6))
        speed_down.triggered.connect(self.speed.stepDown)
        
        self.utils = [
            slider,
            back_fast,
            back,
            play,
            forward,
            forward_fast,
            time,
            speed
        ]
        self.playback_actions = [abf, ab, ap, af, aff, speed_down, speed_up]
        self.set_enabled_utils(False)

        self.prevent = False
        self.timer = QTimer(self)
        self.timer.timeout.connect(self._update)
        self.timer.start(1)
        self.player = None
class Example(QWidget):

    def __init__(self):
        super().__init__()
        
        self.initUI()

    def initUI(self):

        QToolTip.setFont(QFont('SansSerif', 12))
        
        Title = QLabel('Выберите параметры обучения нейросети')
        Title.setToolTip('Для корректной работы функций обучения и оптимизации \n'
                         'в каталоге с программой должны находится подкаталоги \n'
                         'train, val, test. В каждом из этих каталогов должно \n'
                         'быть столько подкаталогов с изображениями, сколько \n'
                         'необходимо распознавать классов')
        Title1 = QLabel('Выберите параметры исследования изображения')
        Title1.setToolTip('Для корректной работы функции классификации и локализации \n'
                          'изображения для исследования и модель нейросети должны \n'
                          'находиться в одном каталоге с программой, формат изображения \n'
                          '.jpg, формат модели нейросети .h5, указывать формат в полях не нужно')
        TitleEp = QLabel('Эпохи:')
        TitleEp.setToolTip('Эпоха — один «проход» данных через нейросеть. \n'
                           'Изменение этого параметра позволяет избежать \n'
                           'недообученности или переобученности нейросети')
        TitleBa = QLabel('Размер мини-выборки:')
        TitleBa.setToolTip('Количество изображений загружаемых в нейросеть '
                           'за раз')
        TitleTr = QLabel('Количество изображений для обучения:')
        TitleTr.setToolTip('Количество изображений во всех подкаталогах '
                           'каталога train')
        TitleVa = QLabel('Количество изображений для проверки:')
        TitleVa.setToolTip('Количество изображений во всех подкаталогах '
                           'каталога val')
        TitleTe = QLabel('Количество изображений для тестирования:')
        TitleTe.setToolTip('Количество изображений во всех подкаталогах '
                           'каталога test')
        TitleSc = QLabel('Масштабирование пирамиды изображений:')
        TitleSc.setToolTip('Коэффициент масштабирования изображения')
        TitleSs = QLabel('Шаг скользящего окна:')
        TitleSs.setToolTip('Расстояние в пикселях, на которое смещается \n'
                           'окно классификатора по изображению за одну итерацию')
        TitleNi = QLabel('Имя изображения для исследования:')
        TitleNi.setToolTip('Наименование изображения без расширения. \n'
                           'Изображение должно иметь формат jpg и \n'
                           'находится в одном каталоге с программой, иначе \n'
                           'необходимо указывать полный путь до изображения')
        TitleNm = QLabel('Имя модели нейросети:')
        TitleNm.setToolTip('Наименование модели нейросети без расширения. \n'
                           'Модель должна иметь формат h5 и находится \n'
                           'в одном каталоге с программой, иначе необходимо \n'
                           'указывать полный путь до модели нейросети')
        TitleCl = QLabel('Количество классов:')
        
        self.InputEpochs = QSpinBox(self)
        self.InputEpochs.setRange(5,50)
        self.InputEpochs.setValue(10)

        self.InputBatch = QSpinBox(self)
        self.InputBatch.setRange(5,100)
        self.InputBatch.setValue(15)

        self.InputTrain = QSpinBox(self)
        self.InputTrain.setRange(100,100000)
        self.InputTrain.setValue(1050)

        self.InputValidation = QSpinBox(self)
        self.InputValidation.setRange(100,100000)
        self.InputValidation.setValue(225)

        self.InputTest = QSpinBox(self)
        self.InputTest.setRange(100,100000)
        self.InputTest.setValue(225)

        self.InputScale = QDoubleSpinBox(self)
        self.InputScale.setRange(1.1,5)
        self.InputScale.setValue(1.5)

        self.InputStep = QSpinBox(self)
        self.InputStep.setRange(1,150)
        self.InputStep.setValue(30)

        self.InputClass = QSpinBox(self)
        self.InputClass.setRange(3,20)
        self.InputClass.setValue(3)
        
        self.ImageName = QLineEdit("ImageName", self)
        self.ImageName.setMaxLength(20)

        self.ModelName = QLineEdit("TestModel", self)
        self.ModelName.setMaxLength(20)
        
        btn = QPushButton('Обучить нейросеть', self)
        btn.setToolTip('В результате обучения модель нейросети '
                       'будет сохранена в каталоге с программой')
        btn.resize(btn.sizeHint())
        btn.clicked.connect(self.buttonClicked)
        
        btn1 = QPushButton('Оптимизировать нейросеть', self)
        btn1.setToolTip('В результате оптимизации 3 лучшие модели '
                        'будут сохранены в каталоге с программой')
        btn1.resize(btn1.sizeHint())
        btn1.clicked.connect(self.buttonClicked1)
        
        btn2 = QPushButton('Поиск и распознавание', self)
        btn2.resize(btn2.sizeHint())
        btn2.clicked.connect(self.buttonClicked2)

        grid = QGridLayout(self)

        grid.setSpacing(10)

        grid.addWidget(Title, 1, 0, 1, 4)
        grid.addWidget(TitleEp, 2, 0)
        grid.addWidget(TitleBa, 3, 0)
        grid.addWidget(TitleCl, 4, 0)
        grid.addWidget(self.InputEpochs, 2, 1)
        grid.addWidget(self.InputBatch, 3, 1)
        grid.addWidget(self.InputClass, 4, 1)
        grid.addWidget(TitleTr, 2, 2)
        grid.addWidget(TitleVa, 3, 2)
        grid.addWidget(TitleTe, 4, 2)
        grid.addWidget(self.InputTrain, 2, 3)
        grid.addWidget(self.InputValidation, 3, 3)
        grid.addWidget(self.InputTest, 4, 3)
        grid.addWidget(btn, 5, 0, 1, 2)
        grid.addWidget(btn1, 5, 2, 1, 2)
        
        grid.addWidget(Title1, 6, 0, 1, 4)
        grid.addWidget(TitleSc, 7, 0)
        grid.addWidget(self.InputScale, 7, 1)
        grid.addWidget(TitleSs, 7, 2)
        grid.addWidget(self.InputStep, 7, 3)
        grid.addWidget(TitleNi, 8, 0)
        grid.addWidget(self.ImageName, 8, 1)
        grid.addWidget(TitleNm, 8, 2)
        grid.addWidget(self.ModelName, 8, 3)
        grid.addWidget(btn2, 9, 1, 1, 2)
        
        self.setLayout(grid)
        
        self.setWindowTitle('Система поиска и распознавания сорных растений')
        self.setWindowIcon(QIcon('icon.png'))
        self.show()
    
    def buttonClicked(self):

        train_dir = 'train' # Каталог с данными для обучения
        val_dir = 'val' # Каталог с данными для проверки
        test_dir = 'test' # Каталог с данными для тестирования
        img_width, img_height = 150, 150 # Размеры изображения
        input_shape = (img_width, img_height, 3) # Размерность тензора на основе изображения для входных данных в нейронную сеть
        
        epochs = self.InputEpochs.value()
        Nclasses = self.InputClass.value()
        batch_size = self.InputBatch.value()
        nb_train_samples = self.InputTrain.value()
        nb_validation_samples = self.InputValidation.value()
        nb_test_samples = self.InputTest.value()
        
        model = Sequential()
        model.add(Conv2D(32, (3, 3), input_shape=input_shape))
        model.add(Activation('relu'))
        model.add(MaxPooling2D(pool_size=(2, 2)))

        model.add(Conv2D(64, (3, 3)))
        model.add(Activation('relu'))
        model.add(MaxPooling2D(pool_size=(2, 2)))

        model.add(Conv2D(64, (3, 3)))
        model.add(Activation('relu'))
        model.add(MaxPooling2D(pool_size=(2, 2)))

        model.add(Conv2D(128, (3, 3)))
        model.add(Activation('relu'))
        model.add(MaxPooling2D(pool_size=(2, 2)))

        model.add(Flatten())
        model.add(Dense(768))
        model.add(Activation('selu'))
        model.add(Dropout(0.5))
        model.add(Dense(Nclasses))
        model.add(Activation('softmax'))

        model.compile(loss='categorical_crossentropy',
            optimizer='adam',
            metrics=['accuracy'])

        datagen = ImageDataGenerator(rescale=1. / 255)

        train_generator = datagen.flow_from_directory(
            train_dir,
            target_size=(img_width, img_height),
            batch_size=batch_size,
            class_mode='categorical')

        val_generator = datagen.flow_from_directory(
            val_dir,
            target_size=(img_width, img_height),
            batch_size=batch_size,
            class_mode='categorical')

        test_generator = datagen.flow_from_directory(
            test_dir,
            target_size=(img_width, img_height),
            batch_size=batch_size,
            class_mode='categorical')

        model.fit_generator(
            train_generator,
            steps_per_epoch=nb_train_samples // batch_size,
            epochs=epochs,
            validation_data=val_generator,
            validation_steps=nb_validation_samples // batch_size)

        scores = model.evaluate_generator(test_generator, nb_test_samples // batch_size)

        print("Аккуратность на тестовых данных: %.2f%%" % (scores[1]*100))

        model.save('TestModel.h5')

    def buttonClicked1(self):

        train_dir = 'train'
        val_dir = 'val'
        test_dir = 'test'
        img_width, img_height = 150, 150
        input_shape = (img_width, img_height, 3)

        epochs = self.InputEpochs.value()
        Nclasses = self.InputClass.value()
        batch_size = self.InputBatch.value()
        nb_train_samples = self.InputTrain.value()
        nb_validation_samples = self.InputValidation.value()
        nb_test_samples = self.InputTest.value()

        l=0

        def build_model(hp):  
            model = Sequential()

            num_hidden_layers = hp.Int('num_hidden_layers', 1, 3, default=1)
            num_conv_layers = hp.Int('num_conv_layers', 2, 6, default=2)

            model.add(Conv2D(32, (3, 3), input_shape=input_shape))
            model.add(Activation('relu'))
            model.add(MaxPooling2D(pool_size=(2, 2)))

            for i in range(num_conv_layers):
                filters = hp.Int('filters'+str(i), 32, 64, step=16)
                model.add(Conv2D(filters,(3, 3)))
                model.add(Activation('relu'))
            model.add(MaxPooling2D(pool_size=(2, 2)))

            model.add(Conv2D(128, (3, 3)))
            model.add(Activation('relu'))
            model.add(MaxPooling2D(pool_size=(2, 2)))

            model.add(Flatten())
    
            for j in range(num_hidden_layers):
                model.add(Dense(units=hp.Int('units_hiddenNeurons_'+str(j),
                                             min_value=128,
                                             max_value=1024,
                                             step=64),
                                activation=hp.Choice('activation'+str(j),values=['relu','tanh','elu','selu'])))

            model.add(Dropout(0.5))
            model.add(Dense(Nclasses))
            model.add(Activation('softmax'))
            model.compile(
                loss='categorical_crossentropy',
                optimizer=hp.Choice('optimizer', values=['adam','rmsprop','SGD'],default='adam'),
                metrics=['accuracy'])
            return model

        tuner = RandomSearch(
            build_model,
            objective='val_accuracy',
            max_trials=15,
            directory='test_directory')

        tuner.search_space_summary()

        datagen = ImageDataGenerator(rescale=1. / 255)

        train_generator = datagen.flow_from_directory(
            train_dir,
            target_size=(img_width, img_height),
            batch_size=batch_size,
            class_mode='categorical')

        val_generator = datagen.flow_from_directory(
            val_dir,
            target_size=(img_width, img_height),
            batch_size=batch_size,
            class_mode='categorical')

        test_generator = datagen.flow_from_directory(
            test_dir,
            target_size=(img_width, img_height),
            batch_size=batch_size,
            class_mode='categorical')

        tuner.search(
            train_generator,
            steps_per_epoch=nb_train_samples // batch_size,
            epochs=epochs,
            validation_data=val_generator,
            validation_steps=nb_validation_samples // batch_size)

        tuner.results_summary()

        models = tuner.get_best_models(num_models=3)

        for model in models:
            model.summary()
            l=l+1
            scores = model.evaluate_generator(test_generator, nb_test_samples // batch_size)
            model.save('bestmodel_'+str(l)+'.h5')
            print("Аккуратность на тестовых данных: %.2f%%" % (scores[1]*100))


    def buttonClicked2(self):

        def pyramid(image, scale, minSize=(150, 150)):
            yield image
            while True:
                w = int(image.shape[1] / scale)
                image = imutils.resize(image, width=w)
                if image.shape[0] < minSize[1] or image.shape[1] < minSize[0]:
                    break
                yield image

        def sliding_window(image, stepSize, windowSize):
            # сдвиг окна по изображению
            for y in range(0, image.shape[0], stepSize):
                for x in range(0, image.shape[1], stepSize):
                    yield (x, y, image[y:y + windowSize[1], x:x + windowSize[0]])


        # расстояние между точками
        def dist(x,y):
            return np.sqrt(np.sum(np.square(np.array(center(x))-np.array(center(y)))))

        # вычисляем точку-центр рамки
        def center(frame):
            (x, y, x2, y2, _ , _ , _ ) = frame
            return [ x+((x2-x)//2), y2+((y-y2)//2) ]

        # очистка списка найденных рамок
        def clean(X, i=0, max_dist=150):
            # выбираем основной элемент X[i]
            j = i+1 # и, следующий за ним, элемент X[j]
            if i <= len(X) and i > 0:
                max_dist *= X[i][6]
            while(j<len(X)): # для всех элементов j (!= i)
                d = dist( X[i], X[j] ) # считаем расстояние между точками i,j
                if ( d < max_dist ): # i,j в одном кластере
                    if ( X[i][4] >= X[j][4] ): # сравниваем рейтинг
                        del X[j]  # удаляем элемент j
                    else:
                        del X[i] # удаляем основной элемент i
                    X = clean(X, i=i, max_dist=max_dist) # рекурсивно повторяем уже без элемента i
                    break
                else:
                    j+=1
            if ( i<(len(X)-1) ): # если есть ещё точки в других, относительно X[i], кластерах
                X = clean(X, i=i+1, max_dist=max_dist) # то выполняем проверку
            return X

        if __name__ == "__main__":

            k = 1
            path = os.getcwd()
            classes = os.listdir(path + "/train")
            boxes = []
            scale = self.InputScale.value()
            stepSize = self.InputStep.value()
            imagename = self.ImageName.text()
            modelname = self.ModelName.text()
            font = cv2.FONT_HERSHEY_SIMPLEX
	
            model = load_model(modelname+'.h5')
            img = cv2.imread(imagename+'.jpg')
            width1, height1, channels1 = img.shape
            if (width1 > 1000) or (height1 > 1000):
                img = cv2.resize(img, (0, 0), fx = 0.5, fy = 0.5)
            (winW, winH) = (150, 150)
            clone = img.copy()

            for resized in pyramid(img, scale):
                for (x, y, window) in sliding_window(resized, stepSize, windowSize=(winW, winH)):
                    # если окно не соответствует нашему желаемому размеру окна, игнорируем его
                    if window.shape[0] != winH or window.shape[1] != winW:
                        continue
        		
                    img_tensor = image.img_to_array(window)                 # (height, width, channels)
                    img_tensor = np.expand_dims(img_tensor, axis=0)         # (1, height, width, channels), добавим измерение, потому что модель ожидает эту форму: (batch_size, height, width, channels)
                    img_tensor /= 255.                                      # imshow ожидает значений в диапазоне [0, 1]
		
                    pred = model.predict(img_tensor)
                    nclass = np.argmax(pred)
                    pred = np.amax(pred)
                    if pred >= 0.9:
                        boxes.append([x*k, y*k, (x + winW)*k, (y + winH)*k, pred, classes[nclass], k])

                k *= scale
	

            boxes = clean(boxes)
	
            for (x, y, x2, y2, score, classname, scales) in boxes:
                    cv2.rectangle(clone, (int(x),int(y)),(int(x2), int(y2)),(0, 255, 0), 2)
                    cv2.putText(clone, classname + " %.3f" % score, (int(x),int(y2)), font, 0.7, (0, 255, 0), thickness=2)
            cv2.imshow("Result", clone)
            cv2.waitKey(1)

    def closeEvent(self, event):

        reply = QMessageBox.question(self, 'Выход',
            "Вы уверены что хотите закрыть программу?", QMessageBox.Yes |
            QMessageBox.No, QMessageBox.No)

        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()
Exemple #30
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        parameters = {
            'Gain Scheduling': {
                'GS': 'Gain scheduling',
                'AS': 'Active Set',
                'B12': 'Boundary 1/2',
                'B23': 'Boundary 2/3'
            },
            'Set 1': {
                'P1': 'Proportional 1',
                'I1': 'Integral 1',
                'D1': 'Derivative 1'
            },
            'Set 2': {
                'P2': 'Proportional 2',
                'I2': 'Integral 2',
                'D2': 'Derivative 2'
            },
            'Set 3': {
                'P3': 'Proportional 3',
                'I3': 'Integral 3',
                'D3': 'Derivative 3'
            }
        }

        self.units = {
            'I1': ' s',
            'I2': ' s',
            'I3': ' s',
            'D1': ' s',
            'D2': ' s',
            'D3': ' s'
        }
        self.entries = {
            key: QComboBox() if key == 'GS' else
            QSpinBox(minimum=1, maximum=3) if key == 'AS' else QDoubleSpinBox(
                decimals=0, singleStep=10, minimum=0, maximum=100000)
            for subset in parameters for key in parameters[subset]
        }
        self.entries['GS'].addItems(
            ['None', 'Set', 'Process Variable', 'Setpoint', 'Output'])

        for entry, suffix in self.units.items():
            self.entries[entry].setSuffix(suffix)

        vbox = QVBoxLayout()
        vbox.setSpacing(0)
        vbox.setContentsMargins(10, 10, 10, 10)
        for subset in parameters:
            label = QLabel(text=subset, objectName='Header')
            vbox.addWidget(label)
            vbox.addSpacing(10)
            form = QFormLayout()
            form.setSpacing(5)
            form.setHorizontalSpacing(20)
            form.setContentsMargins(0, 0, 0, 0)
            for key in parameters[subset]:
                form.addRow(parameters[subset][key], self.entries[key])
            vbox.addLayout(form)
            vbox.addSpacing(20)

        refresh_button = QPushButton(text='Refresh', objectName='Refresh')
        refresh_button.clicked.connect(
            lambda: pubsub.pub.sendMessage('gui.request.pid_parameters'))
        vbox.addWidget(refresh_button)

        vbox.addStretch()
        self.setLayout(vbox)

        for key, entry in self.entries.items():
            if key == 'GS':
                entry.currentTextChanged.connect(
                    functools.partial(self.set_pid_parameter, control=key))
            else:
                entry.setKeyboardTracking(False)
                entry.valueChanged.connect(
                    functools.partial(self.set_pid_parameter, control=key))

        pubsub.pub.subscribe(self.update_pid_parameters,
                             'engine.answer.pid_parameters')
Exemple #31
0
class Ui_Transformation(object):
    def setupUi(self, Transformation, instrument):
        Transformation.setObjectName("Transformation")
        Transformation.resize(361, 171)
        self.frame_layout = QVBoxLayout(Transformation)
        self.frame_layout.setContentsMargins(4, 4, 4, 4)
        self.main_layout = QVBoxLayout()
        self.main_layout.setSpacing(4)

        self.name_layout = QHBoxLayout()
        self.name_layout.setSpacing(-1)
        self.name_label = QLabel("Name", Transformation)
        self._make_text_bold(self.name_label)

        self.name_layout.addWidget(self.name_label)
        self.name_line_edit = QLineEdit(Transformation)

        self.name_layout.addWidget(self.name_line_edit)
        self.main_layout.addLayout(self.name_layout)

        self._add_line()

        self.vector_label = QLabel("", Transformation)
        self._make_text_bold(self.vector_label)
        self.main_layout.addWidget(self.vector_label)

        self._set_up_vector_box(Transformation)

        self._add_line()

        self.value_label = QLabel("")
        self._make_text_bold(self.value_label)
        self.main_layout.addWidget(self.value_label)

        self.magnitude_widget = FieldWidget(hide_name_field=True,
                                            instrument=instrument)
        self.magnitude_widget.setFrameShape(QFrame.NoFrame)
        self.magnitude_widget.setMinimumHeight(40)
        self.main_layout.addWidget(self.magnitude_widget)

        self.ui_placeholder_layout = QFormLayout()
        self.value_spinbox = QDoubleSpinBox(Transformation)
        self.value_spinbox.setToolTip("Placeholder value for 3D view to use")
        self.value_spinbox.setDecimals(8)
        self.value_spinbox.setMaximumSize(QSize(100, 16777215))
        self.ui_placeholder_layout.addRow("Value to use in 3D view:",
                                          self.value_spinbox)

        self.main_layout.addLayout(self.ui_placeholder_layout)

        self.set_spinbox_ranges()

        self.frame_layout.addLayout(self.main_layout)

        self.retranslateUi(Transformation)
        QMetaObject.connectSlotsByName(Transformation)

    def _add_line(self):
        line = QFrame()
        line.setFrameShape((QFrame.HLine))
        line.setFrameShadow(QFrame.Sunken)
        self.main_layout.addWidget(line)

    @staticmethod
    def _make_text_bold(label: QLabel):
        font = label.font()
        font.setBold(True)
        label.setFont(font)

    def _set_up_vector_box(self, Transformation):
        self.xyz_layout = QHBoxLayout()

        self.x_layout = QFormLayout()
        self.x_spinbox = QDoubleSpinBox(Transformation)
        self.x_layout.addRow("x:", self.x_spinbox)
        self.xyz_layout.addLayout(self.x_layout)

        self.y_layout = QFormLayout()
        self.y_spinbox = QDoubleSpinBox(Transformation)
        self.y_layout.addRow("y:", self.y_spinbox)
        self.xyz_layout.addLayout(self.y_layout)

        self.z_layout = QFormLayout()
        self.z_spinbox = QDoubleSpinBox(Transformation)
        self.z_layout.addRow("z:", self.z_spinbox)
        self.xyz_layout.addLayout(self.z_layout)

        self.main_layout.addLayout(self.xyz_layout)

    def set_spinbox_ranges(self):
        self.spinboxes = [
            self.x_spinbox,
            self.y_spinbox,
            self.z_spinbox,
            self.value_spinbox,
        ]
        for spinbox in self.spinboxes:
            spinbox.setRange(-10000000, 10000000)
            spinbox.setDecimals(5)

    def retranslateUi(self, Transformation):
        Transformation.setWindowTitle(
            QApplication.translate("Transformation", "GroupBox", None, -1))
        Transformation.setTitle(
            QApplication.translate("Transformation", "Translation", None, -1))
Exemple #32
0
 def testQRealSignal(self):
     foo1 = QDoubleSpinBox()
     effect = QGraphicsBlurEffect()
     effect.blurRadiusChanged['qreal'].connect(foo1.setValue) # check if qreal is a valid type
     effect.setBlurRadius(0.42)
     self.assertAlmostEqual(foo1.value(), effect.blurRadius())