class ChronoTimer(QObject): def __init__(self, parent, duration=None): """ :param parent: :param Nteams: :param duration: (dict) containing optional keys : days, minutes, seconds, hours, weeks, milliseconds, microseconds """ super().__init__() self.area = parent if duration is None: self.type = 'chrono' self.duration = timedelta() else: self.type = 'timer' self.duration = timedelta(**duration) #seconds self.displayed_time = 0 #in seconds self.started = False self.timer = QTimer() self.timer.setInterval(100) self.timer.timeout.connect(self.display_time) self.setup_ui() def setup_ui(self): self.dock_chrono_timer = Dock(self.type.capitalize()) self.area.addDock(self.dock_chrono_timer) self.dock_chrono_timer.float() widget_chrono_timer = QtWidgets.QWidget() self.dock_chrono_timer.addWidget(widget_chrono_timer) self.layout_lcd = QtWidgets.QVBoxLayout() widget_chrono_timer.setLayout(self.layout_lcd) self.dock_chrono_timer.setAutoFillBackground(True) palette = self.dock_chrono_timer.palette() palette.setColor(palette.Background, QtGui.QColor(0, 0, 0)) self.dock_chrono_timer.setPalette(palette) self.time_lcd = QtWidgets.QLCDNumber(8) self.set_lcd_color(self.time_lcd, 'red') self.layout_lcd.addWidget(self.time_lcd) hours, minutes, seconds = self.get_times(self.duration) self.time_lcd.display('{:02d}:{:02d}:{:02d}'.format( hours, minutes, seconds)) self.dock_controls = Dock('Chrono/Timer Controls') self.area.addDock(self.dock_controls) self.dock_controls.setOrientation('vertical', True) self.dock_controls.setMaximumHeight(150) self.widget_controls = QtWidgets.QWidget() self.controls_layout = QtWidgets.QVBoxLayout() self.widget_controls.setLayout(self.controls_layout) hor_layout = QtWidgets.QHBoxLayout() hor_widget = QtWidgets.QWidget() hor_widget.setLayout(hor_layout) self.controls_layout.addWidget(hor_widget) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/icons/Icon_Library/run2.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.start_pb = PushButtonShortcut(icon, 'Start', shortcut='Home', shortcut_widget=self.area) self.start_pb.clicked.connect(self.start) self.start_pb.setToolTip('home ("début") key shorcut') hor_layout.addWidget(self.start_pb) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/icons/Icon_Library/pause.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.pause_pb = PushButtonShortcut(icon, 'Pause', shortcut='Ctrl+p', shortcut_widget=self.area) self.pause_pb.setCheckable(True) self.pause_pb.setToolTip("Ctrl+p key shortcut") self.pause_pb.clicked.connect(self.pause) hor_layout.addWidget(self.pause_pb) icon = QtGui.QIcon() icon.addPixmap(QtGui.QPixmap(":/icons/Icon_Library/Refresh2.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.reset_pb = PushButtonShortcut(icon, 'Reset', shortcut='F5', shortcut_widget=self.area) self.reset_pb.setToolTip('F5 key shortcut') self.reset_pb.clicked.connect(self.reset) hor_layout.addWidget(self.reset_pb) self.dock_controls.addWidget(self.widget_controls) def get_times(self, duration): seconds = int(duration.total_seconds() % 60) total_minutes = duration.total_seconds() // 60 minutes = int(total_minutes % 60) hours = int(total_minutes // 60) return hours, minutes, seconds def get_elapsed_time(self): return time.perf_counter() - self.ini_time def display_time(self): elapsed_time = self.get_elapsed_time() if self.type == 'timer': display_timedelta = self.duration - timedelta(seconds=elapsed_time) else: display_timedelta = self.duration + timedelta(seconds=elapsed_time) self.displayed_time = display_timedelta.total_seconds() if display_timedelta.total_seconds() <= 0: self.reset() return else: hours, minutes, seconds = self.get_times(display_timedelta) self.time_lcd.display('{:02d}:{:02d}:{:02d}'.format( hours, minutes, seconds)) QtWidgets.QApplication.processEvents() def start(self): self.ini_time = time.perf_counter() self.timer.start() self.started = True self.start_pb.setEnabled(False) def pause(self): if self.pause_pb.isChecked(): self.started = False self.timer.stop() self.paused_time = time.perf_counter() else: elapsed_pause_time = time.perf_counter() - self.paused_time self.ini_time += elapsed_pause_time self.timer.start() self.started = True def reset(self): if self.pause_pb.isChecked(): self.pause_pb.setChecked(False) QtWidgets.QApplication.processEvents() self.timer.stop() self.start_pb.setEnabled(True) self.started = False hours, minutes, seconds = self.get_times(self.duration) self.time_lcd.display('{:02d}:{:02d}:{:02d}'.format( hours, minutes, seconds)) def set_lcd_color(self, lcd, color): palette = lcd.palette() #lcd.setPalette(QtGui.QPalette(Qt.red)) if hasattr(Qt, color): palette.setBrush(palette.WindowText, getattr(Qt, color)) palette.setColor(palette.Background, QtGui.QColor(0, 0, 0)) lcd.setPalette(palette)
def setup_widgets(self, parent, name): self.occupancy_images_columns = {} self.occupancy_images_rows = {} dut_names = [] for device in self.config['correlation_planes']: dut_names.append(device['name']) dock_area = DockArea() parent.addTab(dock_area, name) # Send active tab index to converter so that it only does something when user is looking at corresponding receiver parent.currentChanged.connect(lambda value: self.send_command('ACTIVETAB %s' % str(parent.tabText(value)))) dock_status = Dock("Status") dock_status.setMinimumSize(400, 90) dock_status.setMaximumHeight(110) dock_select_duts = Dock("Select DUT's") dock_select_duts.setMinimumSize(400, 90) dock_select_duts.setMaximumHeight(110) dock_corr_column = Dock('Column Correlation') dock_corr_column.setMinimumSize(400, 400) dock_corr_row = Dock('Row Correlation') dock_corr_row.setMinimumSize(400, 400) cb = QtGui.QWidget() layout0 = QtGui.QGridLayout() cb.setLayout(layout0) self.combobox1 = Qt.QComboBox() self.combobox1.addItems(dut_names) self.combobox1.setMinimumSize(100, 50) self.combobox1.setMaximumSize(200, 50) self.combobox2 = Qt.QComboBox() self.combobox2.addItems(dut_names) self.combobox2.setMinimumSize(100, 50) self.combobox2.setMaximumSize(200, 50) self.select_label = QtGui.QLabel('Correlate:') self.select_label1 = QtGui.QLabel(' to ') self.start_button = QtGui.QPushButton('Start') self.stop_button = QtGui.QPushButton('Stop') self.start_button.setMinimumSize(75, 38) self.start_button.setMaximumSize(150, 38) self.stop_button.setMinimumSize(75, 38) self.stop_button.setMaximumSize(150, 38) layout0.setHorizontalSpacing(25) layout0.addWidget(self.select_label, 0, 0, 0, 1) layout0.addWidget(self.combobox1, 0, 1, 0, 1) layout0.addWidget(self.select_label1, 0, 2, 0, 1) layout0.addWidget(self.combobox2, 0, 3, 0, 1) layout0.addWidget(self.start_button, 0, 4, 0, 1) layout0.addWidget(self.stop_button, 0, 5, 0, 1) dock_select_duts.addWidget(cb) self.combobox1.activated.connect(lambda value: self.send_command('combobox1 %d' % value)) self.combobox2.activated.connect(lambda value: self.send_command('combobox2 %d' % value)) self.start_button.clicked.connect(lambda value: self.send_command('START %d' % value)) self.stop_button.clicked.connect(lambda value: self.send_command('STOP %d' % value)) cw = QtGui.QWidget() layout = QtGui.QGridLayout() cw.setLayout(layout) reset_button = QtGui.QPushButton('Reset') reset_button.setMinimumSize(100, 30) reset_button.setMaximumSize(300, 30) layout.setHorizontalSpacing(25) layout.addWidget(reset_button, 0, 1, 0, 1) remove_background_checkbox = QtGui.QCheckBox('Remove background:') layout.addWidget(remove_background_checkbox, 0, 2, 1, 1) remove_background_spinbox = QtGui.QDoubleSpinBox() remove_background_spinbox.setRange(0.0, 100.0) remove_background_spinbox.setValue(99.0) remove_background_spinbox.setSingleStep(1.0) remove_background_spinbox.setDecimals(1) remove_background_spinbox.setPrefix('< ') remove_background_spinbox.setSuffix(' % maximum occupancy') layout.addWidget(remove_background_spinbox, 0, 3, 1, 1) self.transpose_checkbox = QtGui.QCheckBox('Transpose columns and rows (of ref. plane)') layout.addWidget(self.transpose_checkbox, 1, 3, 1, 1) self.convert_checkbox = QtGui.QCheckBox('Axes in ' + u'\u03BC' + 'm') layout.addWidget(self.convert_checkbox, 1, 2, 1, 1) self.rate_label = QtGui.QLabel("Readout Rate: Hz") layout.addWidget(self.rate_label, 0, 4, 1, 1) dock_status.addWidget(cw) reset_button.clicked.connect(lambda: self.send_command('RESET')) self.transpose_checkbox.stateChanged.connect(lambda value: self.send_command('TRANSPOSE %d' % value)) remove_background_checkbox.stateChanged.connect(lambda value: self.send_command('BACKGROUND %d' % value)) remove_background_spinbox.valueChanged.connect(lambda value: self.send_command('PERCENTAGE %f' % value)) # Add plot docks for column correlation occupancy_graphics1 = pg.GraphicsLayoutWidget() occupancy_graphics1.show() view1 = occupancy_graphics1.addViewBox() occupancy_img_col = pg.ImageItem(border='w') poss = np.array([0.0, 0.01, 0.5, 1.0]) color = np.array([[1.0, 1.0, 1.0, 1.0], [0.267004, 0.004874, 0.329415, 1.0], [0.127568, 0.566949, 0.550556, 1.0], [0.993248, 0.906157, 0.143936, 1.0]]) # Zero is white mapp = pg.ColorMap(poss, color) lutt = mapp.getLookupTable(0.0, 1.0, 100) occupancy_img_col.setLookupTable(lutt, update=True) self.plot1 = pg.PlotWidget(viewBox=view1) self.plot1.getAxis('bottom').setLabel(text='Columns') self.plot1.getAxis('left').setLabel(text='Columns') self.plot1.addItem(occupancy_img_col) dock_corr_column.addWidget(self.plot1) self.occupancy_images_columns = occupancy_img_col # Add plot docks for row correlation occupancy_graphics2 = pg.GraphicsLayoutWidget() occupancy_graphics2.show() view2 = occupancy_graphics2.addViewBox() occupancy_img_rows = pg.ImageItem(border='w') occupancy_img_rows.setLookupTable(lutt, update=True) self.plot2 = pg.PlotWidget(viewBox=view2) self.plot2.getAxis('bottom').setLabel(text='Rows') self.plot2.getAxis('left').setLabel(text='Rows') self.plot2.addItem(occupancy_img_rows) dock_corr_row.addWidget(self.plot2) self.occupancy_images_rows = occupancy_img_rows dock_area.addDock(dock_status, 'top') dock_area.addDock(dock_select_duts, 'left') dock_area.addDock(dock_corr_column, 'bottom') dock_area.addDock(dock_corr_row, 'right', dock_corr_column) def scale_and_label_axes(scale_state, dut1, dut2, transpose_state): ''' Rescale axis and change labels (according to tranpose and scale option). ''' dut1_name = self.config['correlation_planes'][dut1]['name'] dut2_name = self.config['correlation_planes'][dut2]['name'] if scale_state == 0: # Column/Row scaling self.plot1.getAxis('bottom').setScale(1.0) self.plot1.getAxis('left').setScale(1.0) self.plot2.getAxis('bottom').setScale(1.0) self.plot2.getAxis('left').setScale(1.0) self.plot1.getAxis('bottom').setTickSpacing() self.plot1.getAxis('left').setTickSpacing() self.plot2.getAxis('bottom').setTickSpacing() self.plot2.getAxis('left').setTickSpacing() if transpose_state == 0: # False self.plot1.getAxis('bottom').setLabel(text=dut1_name + ' Columns') self.plot2.getAxis('bottom').setLabel(text=dut1_name + ' Rows') elif transpose_state == 2: # True self.plot1.getAxis('bottom').setLabel(text=dut1_name + ' Rows') self.plot2.getAxis('bottom').setLabel(text=dut1_name + ' Columns') self.plot1.getAxis('left').setLabel(text=dut2_name + ' Columns') self.plot2.getAxis('left').setLabel(text=dut2_name + ' Rows') elif scale_state == 2: # um scaling col_size_dut_1 = self.correlator_config[self.config['correlation_planes'][dut1]['dut_type']]['column_size'] row_size_dut_1 = self.correlator_config[self.config['correlation_planes'][dut1]['dut_type']]['row_size'] col_size_dut_2 = self.correlator_config[self.config['correlation_planes'][dut1]['dut_type']]['column_size'] row_size_dut_2 = self.correlator_config[self.config['correlation_planes'][dut1]['dut_type']]['row_size'] if transpose_state == 0: # False self.plot1.getAxis('bottom').setScale(row_size_dut_1) self.plot2.getAxis('bottom').setScale(col_size_dut_1) self.plot1.getAxis('left').setScale(col_size_dut_2) self.plot2.getAxis('left').setScale(row_size_dut_2) self.plot1.getAxis('bottom').setLabel(text=dut1_name + ' Columns / ' + u'\u03BC' + 'm') self.plot2.getAxis('bottom').setLabel(text=dut1_name + ' Rows / ' + u'\u03BC' + 'm') self.plot1.getAxis('left').setLabel(text=dut2_name + ' Columns / ' + u'\u03BC' + 'm') self.plot2.getAxis('left').setLabel(text=dut2_name + ' Rows / ' + u'\u03BC' + 'm') elif transpose_state == 2: # True self.plot1.getAxis('bottom').setScale(col_size_dut_1) self.plot2.getAxis('bottom').setScale(row_size_dut_1) self.plot1.getAxis('left').setScale(col_size_dut_2) self.plot2.getAxis('left').setScale(row_size_dut_2) self.plot1.getAxis('bottom').setLabel(text=dut1_name + ' Rows / ' + u'\u03BC' + 'm') self.plot2.getAxis('bottom').setLabel(text=dut1_name + ' Columns / ' + u'\u03BC' + 'm') self.plot1.getAxis('left').setLabel(text=dut2_name + ' Columns / ' + u'\u03BC' + 'm') self.plot2.getAxis('left').setLabel(text=dut2_name + ' Rows / ' + u'\u03BC' + 'm') self.convert_checkbox.stateChanged.connect(lambda value: scale_and_label_axes(value, self.combobox1.currentIndex(), self.combobox2.currentIndex(), self.transpose_checkbox.checkState())) self.combobox1.activated.connect(lambda value: scale_and_label_axes(self.convert_checkbox.checkState(), value, self.combobox2.currentIndex(), self.transpose_checkbox.checkState())) self.combobox2.activated.connect(lambda value: scale_and_label_axes(self.convert_checkbox.checkState(), self.combobox1.currentIndex(), value, self.transpose_checkbox.checkState())) self.transpose_checkbox.stateChanged.connect(lambda value: scale_and_label_axes(self.convert_checkbox.checkState(), self.combobox1.currentIndex(), self.combobox2.currentIndex(), value))