class SiriusScrnView(QWidget): """ Class to read Sirius screen cameras image data. To allow saving a grid correctly, control calibrationgrid_flag, which indicates if the screen is in calibration grid position. You can control it by using the method/Slot updateCalibrationGridFlag. """ save_files = Signal() def __init__(self, parent=None, prefix=_VACA_PREFIX, device=None): """Initialize object.""" QWidget.__init__(self, parent=parent) self.prefix = prefix self.device = SiriusPVName(device) self.scrn_prefix = self.device.substitute(prefix=prefix) self._receivedData = False self.setObjectName(self.scrn_prefix.sec + 'App') self.screen_type_conn = SiriusConnectionSignal( self.scrn_prefix.substitute(propty='ScrnType-Sts')) self.screen_type_conn.new_value_signal.connect( self.updateCalibrationGridFlag) self._calibrationgrid_flag = self.screen_type_conn.getvalue() self.save_files.connect(self._saveGridLocalFiles) self.ch_ImgROIHeight = SiriusConnectionSignal( self.scrn_prefix.substitute(propty='ImgROIHeight-RB')) self.ch_ImgROIWidth = SiriusConnectionSignal( self.scrn_prefix.substitute(propty='ImgROIWidth-RB')) self.ch_ImgROIOffsetX = SiriusConnectionSignal( self.scrn_prefix.substitute(propty='ImgROIOffsetX-RB')) self.ch_ImgROIOffsetY = SiriusConnectionSignal( self.scrn_prefix.substitute(propty='ImgROIOffsetY-RB')) self._setupUi() self.setFocus(True) self.setFocusPolicy(Qt.StrongFocus) self._loadCalibrationGrid(default=True) @property def calibrationgrid_flag(self): """Indicate if the screen device is in calibration grid position.""" return self._calibrationgrid_flag @Slot(int) def updateCalibrationGridFlag(self, new_state): """Update calibrationgrid_flag property.""" self._calibrationgrid_flag = new_state if new_state == 1: self.pushbutton_savegrid.setEnabled(True) else: self.pushbutton_savegrid.setEnabled(False) def _setupUi(self): self.cameraview_widget = QWidget() self.cameraview_widget.setLayout(self._cameraviewLayout()) self.settings_widget = QWidget(self) self.settings_widget.setLayout(self._settingsLayout()) self.settings_widget.setStyleSheet(""" .QLabel{ min-width: 5em;} QLabel{ qproperty-alignment: AlignCenter;}""") self.calibrationgrid_widget = QWidget(self) self.calibrationgrid_widget.setLayout(self._calibrationgridLayout()) self.calibrationgrid_widget.setSizePolicy(QSzPlcy.Expanding, QSzPlcy.Expanding) self.calibrationgrid_widget.layout().setAlignment(Qt.AlignHCenter) self.tab = QTabWidget(self) self.tab.setStyleSheet(""" QTabWidget::pane { border-left: 2px solid gray; border-bottom: 2px solid gray; border-right: 2px solid gray; }""") self.tab.addTab(self.settings_widget, 'Camera Settings') self.tab.addTab(self.calibrationgrid_widget, 'Calibration') self.statistics_groupBox = QGroupBox('Statistics', self) self.statistics_groupBox.setLayout(self._statisticsLayout()) self.statistics_groupBox.setSizePolicy(QSzPlcy.Expanding, QSzPlcy.Expanding) self.statistics_groupBox.setStyleSheet(""" .QLabel{ min-width:0.28em; max-width:0.28em; min-height:1.29em; max-height:1.29em;} QLabel{ qproperty-alignment: AlignCenter;} PyDMWidget{ min-width:4.84em; max-width:4.84em; min-height:1.29em; max-height:1.29em;}""") self.trigger_groupBox = QGroupBox('Trigger', self) if 'TB' in self.device or 'BO' in self.device: trg_prefix = 'AS-Fam:TI-Scrn-TBBO' elif 'TS' in self.device: trg_prefix = 'TS-Fam:TI-Scrn' hbl = QHBoxLayout(self.trigger_groupBox) hbl.addWidget( HLTriggerSimple(parent=self.trigger_groupBox, device=trg_prefix, prefix=self.prefix)) self.trigger_groupBox.setLayout(hbl) self.trigger_groupBox.setStyleSheet(""" PyDMWidget{ min-width:4.84em; max-width:4.84em; min-height:1.29em; max-height:1.29em;}""") vlay = QVBoxLayout() vlay.addWidget(self.statistics_groupBox) vlay.addWidget(self.trigger_groupBox) vlay.setSpacing(10) lay = QGridLayout(self) lay.setHorizontalSpacing(10) lay.setVerticalSpacing(10) lay.addWidget(self.cameraview_widget, 0, 0, 1, 2) lay.addWidget(self.tab, 1, 0) lay.addLayout(vlay, 1, 1) lay.setRowStretch(0, 15) lay.setRowStretch(1, 7) def _cameraviewLayout(self): label = QLabel(self.device, self) label.setStyleSheet("""font-weight: bold;max-height:1.29em;""") label.setAlignment(Qt.AlignCenter) self.image_view = _SiriusImageView( parent=self, image_channel=self.scrn_prefix.substitute(propty='ImgData-Mon'), width_channel=self.scrn_prefix.substitute(propty='ImgROIWidth-RB'), offsetx_channel=self.scrn_prefix.substitute( propty='ImgROIOffsetX-RB'), offsety_channel=self.scrn_prefix.substitute( propty='ImgROIOffsetY-RB'), maxwidth_channel=self.scrn_prefix.substitute( propty='ImgMaxWidth-Cte'), maxheight_channel=self.scrn_prefix.substitute( propty='ImgMaxHeight-Cte')) self.image_view.setObjectName('ScrnView') self.image_view.normalizeData = True self.image_view.readingOrder = self.image_view.Clike self.image_view.maxRedrawRate = 15 self.image_view.setStyleSheet(""" #ScrnView{min-width:30em; min-height:24em;}""") self.image_view.failToSaveGrid.connect(self._showFailToSaveGridMsg) self.image_view.receivedData.connect(self._setReceivedDataFlag) lay = QGridLayout() lay.setContentsMargins(0, 0, 0, 0) lay.addWidget(label, 0, 1) lay.addItem(QSpacerItem(40, 2, QSzPlcy.Preferred, QSzPlcy.Fixed), 1, 1) lay.addWidget(self.image_view, 2, 1) return lay def _calibrationgridLayout(self): self.checkBox_showgrid = QCheckBox('Show', self) self.checkBox_showgrid.setEnabled(False) self.checkBox_showgrid.setStyleSheet(""" min-width:4em; max-width:4em; min-height:1.29em; max-height:1.29em;""") self.checkBox_showgrid.toggled.connect( self.image_view.showCalibrationGrid) self.pushbutton_savegrid = QPushButton('Save', self) self.pushbutton_savegrid.setEnabled(False) self.pushbutton_savegrid.setStyleSheet(""" min-width:4em; max-width:4em; min-height:1.29em; max-height:1.29em;""") self.pushbutton_savegrid.clicked.connect(self._saveCalibrationGrid) self.pushbutton_loadgrid = QPushButton('Load', self) self.pushbutton_loadgrid.setStyleSheet(""" min-width:4em; max-width:4em; min-height:1.29em; max-height:1.29em;""") self.pushbutton_loadgrid.clicked.connect(self._loadCalibrationGrid) hbox_grid = QHBoxLayout() hbox_grid.addWidget(self.checkBox_showgrid) hbox_grid.addWidget(self.pushbutton_savegrid) hbox_grid.addWidget(self.pushbutton_loadgrid) lb = QLabel('Show levels <') lb.setStyleSheet("min-width:7em;max-width:7em;") self.spinbox_gridfilterfactor = QSpinBoxPlus() self.spinbox_gridfilterfactor.setMaximum(100) self.spinbox_gridfilterfactor.setMinimum(0) self.spinbox_gridfilterfactor.setValue( self.image_view.calibration_grid_filterfactor) self.spinbox_gridfilterfactor.editingFinished.connect( self._setCalibrationGridFilterFactor) self.spinbox_gridfilterfactor.setStyleSheet(""" min-width:4em; max-width:4em;""") hbox_filter = QHBoxLayout() hbox_filter.setSpacing(0) hbox_filter.addWidget(lb) hbox_filter.addWidget(self.spinbox_gridfilterfactor) hbox_filter.addWidget(QLabel(' %')) lb = QLabel('Remove border: ') lb.setStyleSheet("min-width:7em;max-width:7em;") self.spinbox_removeborder = QSpinBoxPlus() self.spinbox_removeborder.setMaximum(512) self.spinbox_removeborder.setMinimum(0) self.spinbox_removeborder.setValue( self.image_view.calibration_grid_removeborder) self.spinbox_removeborder.editingFinished.connect( self._setCalibrationGridBorder2Remove) self.spinbox_removeborder.setStyleSheet(""" min-width:4em; max-width:4em;""") hbox_remove = QHBoxLayout() hbox_remove.setSpacing(0) hbox_remove.addWidget(lb) hbox_remove.addWidget(self.spinbox_removeborder) hbox_remove.addWidget(QLabel(' px')) hbox_EnblLED = _create_propty_layout(parent=self, prefix=self.scrn_prefix, propty='EnblLED', propty_type='enbldisabl', width=4.68) lay = QFormLayout() lay.addItem(QSpacerItem(1, 10, QSzPlcy.Ignored, QSzPlcy.Preferred)) lay.addRow(' Grid: ', hbox_grid) lay.addItem(QSpacerItem(1, 10, QSzPlcy.Ignored, QSzPlcy.Preferred)) lay.addRow(' ', hbox_filter) lay.addRow(' ', hbox_remove) lay.addItem(QSpacerItem(1, 20, QSzPlcy.Ignored, QSzPlcy.Preferred)) lay.addRow(' LED: ', hbox_EnblLED) lay.addItem(QSpacerItem(1, 10, QSzPlcy.Ignored, QSzPlcy.Preferred)) lay.setLabelAlignment(Qt.AlignRight) lay.setFormAlignment(Qt.AlignCenter) return lay def _settingsLayout(self): label_CamEnbl = QLabel('Enable: ', self) hbox_CamEnbl = _create_propty_layout(parent=self, prefix=self.scrn_prefix, propty='CamEnbl', propty_type='enbldisabl') label_CamAcqPeriod = QLabel('Acquire\nPeriod [s]:', self) hbox_CamAcqPeriod = _create_propty_layout(parent=self, prefix=self.scrn_prefix, propty='CamAcqPeriod', propty_type='sprb', width=5.0) label_CamExposureTime = QLabel('Exposure\nTime [us]:', self) hbox_CamExposureTime = _create_propty_layout(parent=self, prefix=self.scrn_prefix, propty='CamExposureTime', propty_type='sprb', width=5.0) label_CamGain = QLabel('Gain[dB]:', self) hbox_CamGain = _create_propty_layout(parent=self, prefix=self.scrn_prefix, propty='CamGain', width=5.0, propty_type='sprb') label_AutoGain = QLabel('Auto Gain: ', self) self.pb_autogain = PyDMPushButton( label='', icon=qta.icon('mdi.auto-fix'), parent=self, pressValue=1, init_channel=self.scrn_prefix.substitute(propty='CamAutoGain-Cmd')) self.pb_autogain.setObjectName('autog') self.pb_autogain.setStyleSheet( "#autog{min-width:25px; max-width:25px; icon-size:20px;}") cam_prefix = SiriusPVName(self.scrn_prefix).substitute(dev='ScrnCam') label_Reset = QLabel('Reset: ', self) self.pb_dtl = PyDMPushButton( label='', icon=qta.icon('fa5s.sync'), parent=self, pressValue=1, init_channel=cam_prefix.substitute(propty='Rst-Cmd')) self.pb_dtl.setObjectName('reset') self.pb_dtl.setStyleSheet( "#reset{min-width:25px; max-width:25px; icon-size:20px;}") self.pb_details = QPushButton(qta.icon('fa5s.ellipsis-h'), '', self) self.pb_details.setToolTip('More settings') self.pb_details.setObjectName('detail') self.pb_details.setStyleSheet( "#detail{min-width:25px; max-width:25px; icon-size:20px;}") self.pb_details.setSizePolicy(QSzPlcy.Expanding, QSzPlcy.Preferred) util.connect_window(self.pb_details, _ScrnSettingsDetails, parent=self, prefix=self.prefix, device=self.device) hbox_aux = QHBoxLayout() hbox_aux.addWidget(self.pb_dtl, alignment=Qt.AlignLeft) hbox_aux.addWidget(self.pb_details, alignment=Qt.AlignRight) lay = QFormLayout() lay.setFormAlignment(Qt.AlignCenter) lay.addRow(label_CamEnbl, hbox_CamEnbl) lay.addRow(label_CamAcqPeriod, hbox_CamAcqPeriod) lay.addRow(label_CamExposureTime, hbox_CamExposureTime) lay.addRow(label_CamGain, hbox_CamGain) lay.addRow(label_AutoGain, self.pb_autogain) lay.addRow(label_Reset, hbox_aux) return lay def _statisticsLayout(self): # - Method label_Method = QLabel('CalcMethod:', self) label_Method.setStyleSheet("min-width:7em;") self.comboBox_Method = QComboBox(self) self.comboBox_Method.addItem('DimFei', 0) self.comboBox_Method.addItem('NDStats', 1) self.comboBox_Method.setCurrentIndex(0) self.comboBox_Method.setStyleSheet(""" QComboBox::item {height: 1em;} QComboBox{min-width:6em;}""") self.comboBox_Method.currentIndexChanged.connect( self._handleShowStatistics) # - Centroid label_Centroid = QLabel('Centroid [mm]: ', self) label_Centroid.setStyleSheet("min-width:7em;") label_i_Center = QLabel('(', self) self.PyDMLabel_CenterXDimFei = PyDMLabel( parent=self, init_channel=self.scrn_prefix.substitute( propty='CenterXDimFei-Mon')) self.PyDMLabel_CenterXDimFei.setStyleSheet( 'min-width:4em; max-width:4em;') self.PyDMLabel_CenterXNDStats = PyDMLabel( parent=self, init_channel=self.scrn_prefix.substitute( propty='CenterXNDStats-Mon')) self.PyDMLabel_CenterXNDStats.setStyleSheet( 'min-width:4em; max-width:4em;') self.PyDMLabel_CenterXNDStats.setVisible(False) label_m_Center = QLabel(',', self) self.PyDMLabel_CenterYDimFei = PyDMLabel( parent=self, init_channel=self.scrn_prefix.substitute( propty='CenterYDimFei-Mon')) self.PyDMLabel_CenterYDimFei.setStyleSheet( 'min-width:4em; max-width:4em;') self.PyDMLabel_CenterYNDStats = PyDMLabel( parent=self, init_channel=self.scrn_prefix.substitute( propty='CenterYNDStats-Mon')) self.PyDMLabel_CenterYNDStats.setStyleSheet( 'min-width:4em; max-width:4em;') self.PyDMLabel_CenterYNDStats.setVisible(False) label_f_Center = QLabel(')', self) # - Sigma label_Sigma = QLabel('Sigma [mm]: ', self) label_Sigma.setStyleSheet("min-width:7em;") label_i_Sigma = QLabel('(', self) self.PyDMLabel_SigmaXDimFei = PyDMLabel( parent=self, init_channel=self.scrn_prefix.substitute( propty='SigmaXDimFei-Mon')) self.PyDMLabel_SigmaXDimFei.setStyleSheet( 'min-width:4em; max-width:4em;') self.PyDMLabel_SigmaXNDStats = PyDMLabel( parent=self, init_channel=self.scrn_prefix.substitute( propty='SigmaXNDStats-Mon')) self.PyDMLabel_SigmaXNDStats.setStyleSheet( 'min-width:4em; max-width:4em;') self.PyDMLabel_SigmaXNDStats.setVisible(False) label_m_Sigma = QLabel(',', self) self.PyDMLabel_SigmaYDimFei = PyDMLabel( parent=self, init_channel=self.scrn_prefix.substitute( propty='SigmaYDimFei-Mon')) self.PyDMLabel_SigmaYDimFei.setStyleSheet( 'min-width:4em; max-width:4em;') self.PyDMLabel_SigmaYNDStats = PyDMLabel( parent=self, init_channel=self.scrn_prefix.substitute( propty='SigmaYNDStats-Mon')) self.PyDMLabel_SigmaYNDStats.setStyleSheet( 'min-width:4em; max-width:4em;') self.PyDMLabel_SigmaYNDStats.setVisible(False) label_f_Sigma = QLabel(')', self) # - Theta label_Theta = QLabel('Theta [rad]: ') label_Theta.setStyleSheet("min-width:7em;") label_i_Theta = QLabel('(', self) self.PyDMLabel_ThetaDimFei = PyDMLabel( parent=self, init_channel=self.scrn_prefix.substitute(propty='ThetaDimFei-Mon')) self.PyDMLabel_ThetaDimFei.setStyleSheet("max-width:12em;") self.PyDMLabel_ThetaNDStats = PyDMLabel( parent=self, init_channel=self.scrn_prefix.substitute( propty='ThetaNDStats-Mon')) self.PyDMLabel_ThetaNDStats.setStyleSheet("max-width:12em;") self.PyDMLabel_ThetaNDStats.setVisible(False) label_f_Theta = QLabel(')', self) lay = QGridLayout() lay.addWidget(label_Method, 1, 1, 1, 3) lay.addWidget(self.comboBox_Method, 1, 3, 1, 3) lay.addWidget(label_Centroid, 3, 1, alignment=Qt.AlignCenter) lay.addWidget(label_i_Center, 3, 2) lay.addWidget(self.PyDMLabel_CenterXDimFei, 3, 3) lay.addWidget(self.PyDMLabel_CenterXNDStats, 3, 3) lay.addWidget(label_m_Center, 3, 4) lay.addWidget(self.PyDMLabel_CenterYDimFei, 3, 5) lay.addWidget(self.PyDMLabel_CenterYNDStats, 3, 5) lay.addWidget(label_f_Center, 3, 6) lay.addWidget(label_Sigma, 5, 1, alignment=Qt.AlignCenter) lay.addWidget(label_i_Sigma, 5, 2) lay.addWidget(self.PyDMLabel_SigmaXDimFei, 5, 3) lay.addWidget(self.PyDMLabel_SigmaXNDStats, 5, 3) lay.addWidget(label_m_Sigma, 5, 4) lay.addWidget(self.PyDMLabel_SigmaYDimFei, 5, 5) lay.addWidget(self.PyDMLabel_SigmaYNDStats, 5, 5) lay.addWidget(label_f_Sigma, 5, 6) lay.addWidget(label_Theta, 7, 1, alignment=Qt.AlignCenter) lay.addWidget(label_i_Theta, 7, 2) lay.addWidget(self.PyDMLabel_ThetaDimFei, 7, 3, 1, 3) lay.addWidget(self.PyDMLabel_ThetaNDStats, 7, 3, 1, 3) lay.addWidget(label_f_Theta, 7, 6) return lay def _handleShowStatistics(self, visible): self.PyDMLabel_CenterXDimFei.setVisible(not visible) self.PyDMLabel_CenterXNDStats.setVisible(visible) self.PyDMLabel_CenterYDimFei.setVisible(not visible) self.PyDMLabel_CenterYNDStats.setVisible(visible) self.PyDMLabel_ThetaDimFei.setVisible(not visible) self.PyDMLabel_ThetaNDStats.setVisible(visible) self.PyDMLabel_SigmaXDimFei.setVisible(not visible) self.PyDMLabel_SigmaXNDStats.setVisible(visible) self.PyDMLabel_SigmaYDimFei.setVisible(not visible) self.PyDMLabel_SigmaYNDStats.setVisible(visible) def _saveCalibrationGrid(self): t = Thread(target=self._saveCalibrationGrid_thread, daemon=True) t.start() def _saveCalibrationGrid_thread(self): roi_h = float(self.ch_ImgROIHeight.value) roi_w = float(self.ch_ImgROIWidth.value) roi_offsetx = float(self.ch_ImgROIOffsetX.value) roi_offsety = float(self.ch_ImgROIOffsetY.value) cond = roi_h != float(self.image_view.image_maxheight) or \ roi_w != float(self.image_view.image_maxwidth) or \ roi_offsetx != 0 or roi_offsety != 0 if cond: # Disable camera acquisition and wait for disabling self.PyDMStateButton_CamEnbl.send_value_signal[int].emit(0) state = self.SiriusLedState_CamEnbl.state while state == 1: time.sleep(0.1) state = self.SiriusLedState_CamEnbl.state # Change ROI to get entire image self.ch_ImgROIHeight.send_value_signal[float].emit( float(self.image_view.image_maxheight)) self.ch_ImgROIWidth.send_value_signal[float].emit( float(self.image_view.image_maxwidth)) self.ch_ImgROIOffsetX.send_value_signal[float].emit(0) self.ch_ImgROIOffsetY.send_value_signal[float].emit(0) # Enable led and wait for status self.PyDMStateButton_EnblLED.send_value_signal[int].emit(1) while not self.SiriusLedState_EnblLED.state: time.sleep(0.1) # Enable camera acquisition and wait for receiveing first frame self._receivedData = False self.PyDMStateButton_CamEnbl.send_value_signal[int].emit(1) while not self._receivedData: time.sleep(0.1) # Save grid self.image_view.saveCalibrationGrid() if cond: # Disable camera acquisition and wait for disabling self.PyDMStateButton_CamEnbl.send_value_signal[int].emit(0) state = self.SiriusLedState_CamEnbl.state while state == 1: time.sleep(0.1) state = self.SiriusLedState_CamEnbl.state # Change ROI to original size self.ch_ImgROIHeight.send_value_signal[float].emit(roi_h) self.ch_ImgROIWidth.send_value_signal[float].emit(roi_w) self.ch_ImgROIOffsetX.send_value_signal[float].emit(roi_offsetx) self.ch_ImgROIOffsetY.send_value_signal[float].emit(roi_offsety) # Enable camera acquisition self.PyDMStateButton_CamEnbl.send_value_signal[int].emit(1) # Enable showing saved grid time.sleep(0.1) self.checkBox_showgrid.setEnabled(True) self.save_files.emit() def _saveGridLocalFiles(self): home = os.path.expanduser('~') folder_month = datetime.now().strftime('%Y-%m') folder_day = datetime.now().strftime('%Y-%m-%d') path = os.path.join(home, 'mounts', 'screens-iocs', folder_month, folder_day) if not os.path.exists(path): os.makedirs(path) fn, _ = QFileDialog.getSaveFileName( self, 'Save Grid As...', path + '/' + self.device + datetime.now().strftime('_%Y-%m-%d_%Hh%Mmin'), '*.npy') if not fn: return False path_default = os.path.join(home, 'mounts', 'screens-iocs', 'default') if not os.path.exists(path_default): os.makedirs(path_default) fn_default = path_default + '/' + self.device grid = self.image_view.calibrationGrid width = self.image_view.imageWidth data = np.append(width, grid) np.save(fn, data) np.save(fn_default, data) def _loadCalibrationGrid(self, default=False): home = os.path.expanduser('~') if not default: folder_month = datetime.now().strftime('%Y-%m') path = os.path.join(home, 'mounts', 'screens-iocs', folder_month) fn, _ = QFileDialog.getOpenFileName(self, 'Load Grid...', path, '*.npy') if not fn: return if self.device not in fn: ans = QMessageBox.question( self, 'Warning', 'The name of the selected file does not contain the name' + ' of this screen. Are you sure you\'re loading this grid?', QMessageBox.Yes, QMessageBox.Cancel) if ans == QMessageBox.Cancel: return else: path = os.path.join(home, 'mounts', 'screens-iocs', 'default') fn = path + '/' + self.device + '.npy' try: data = np.load(fn) self.image_view.calibrationGrid = data except Exception as e: if not default: QMessageBox.critical( self, 'Error', 'Could not load calibration grid from file ' + fn + '. ' + '\nError message: ' + str(e), QMessageBox.Ok) return # Enable showing saved grid self.checkBox_showgrid.setEnabled(True) def _setReceivedDataFlag(self): self._receivedData = True def _setCalibrationGridFilterFactor(self): self.image_view.set_calibration_grid_filterfactor( self.spinbox_gridfilterfactor.value()) def _setCalibrationGridBorder2Remove(self): self.image_view.set_calibration_grid_border2remove( self.spinbox_removeborder.value()) @Slot() def _showFailToSaveGridMsg(self): QMessageBox.warning(self, 'Warning', 'Could not save calibration grid!', QMessageBox.Ok)
def generate_pv_controls(self, pv_name, curve_color): """ Generate a set of widgets to manage the appearance of a curve. The set of widgets includes: 1. A checkbox which shows the curve on the chart if checked, and hide the curve if not checked 2. Three buttons -- Modify..., Focus, and Remove. Modify... will bring up the Curve Settings dialog. Focus adjusts the chart's zooming for the current curve. Remove will delete the curve from the chart Parameters ---------- pv_name: str The name of the PV the current curve is being plotted for curve_color : QColor The color of the curve to paint for the checkbox label to help the user track the curve to the checkbox """ individual_curve_layout = QVBoxLayout() size_policy = QSizePolicy() size_policy.setVerticalPolicy(QSizePolicy.Fixed) size_policy.setHorizontalPolicy(QSizePolicy.Fixed) individual_curve_grpbx = QGroupBox() individual_curve_grpbx.setMinimumWidth(300) individual_curve_grpbx.setMinimumHeight(120) individual_curve_grpbx.setAlignment(Qt.AlignTop) individual_curve_grpbx.setSizePolicy(size_policy) individual_curve_grpbx.setObjectName(pv_name + "_grb") individual_curve_grpbx.setLayout(individual_curve_layout) checkbox = QCheckBox(parent=individual_curve_grpbx) checkbox.setObjectName(pv_name + "_chb") palette = checkbox.palette() palette.setColor(QPalette.Active, QPalette.WindowText, curve_color) checkbox.setPalette(palette) display_name = pv_name.split("://")[1] if len(display_name) > MAX_DISPLAY_PV_NAME_LENGTH: # Only display max allowed number of characters of the PV Name display_name = display_name[ :int(MAX_DISPLAY_PV_NAME_LENGTH / 2) - 1] + "..." + \ display_name[ -int(MAX_DISPLAY_PV_NAME_LENGTH / 2) + 2:] checkbox.setText(display_name) data_text = QLabel(parent=individual_curve_grpbx) data_text.setWordWrap(True) data_text.setObjectName(pv_name + "_lbl") data_text.setPalette(palette) checkbox.setChecked(True) checkbox.toggled.connect( partial(self.handle_curve_chkbox_toggled, checkbox)) if not self.chart.findCurve(pv_name).isVisible(): checkbox.setChecked(False) modify_curve_btn = QPushButton("Modify...", parent=individual_curve_grpbx) modify_curve_btn.setObjectName(pv_name + "_btn_modify") modify_curve_btn.setMaximumWidth(80) modify_curve_btn.clicked.connect( partial(self.display_curve_settings_dialog, pv_name)) focus_curve_btn = QPushButton("Focus", parent=individual_curve_grpbx) focus_curve_btn.setObjectName(pv_name + "_btn_focus") focus_curve_btn.setMaximumWidth(80) focus_curve_btn.clicked.connect(partial(self.focus_curve, pv_name)) clear_curve_btn = QPushButton("Clear", parent=individual_curve_grpbx) clear_curve_btn.setObjectName(pv_name + "_btn_clear") clear_curve_btn.setMaximumWidth(80) clear_curve_btn.clicked.connect(partial(self.clear_curve, pv_name)) # annotate_curve_btn = QPushButton("Annotate...", # parent=individual_curve_grpbx) # annotate_curve_btn.setObjectName(pv_name+"_btn_ann") # annotate_curve_btn.setMaximumWidth(80) # annotate_curve_btn.clicked.connect( # partial(self.annotate_curve, pv_name)) remove_curve_btn = QPushButton("Remove", parent=individual_curve_grpbx) remove_curve_btn.setObjectName(pv_name + "_btn_remove") remove_curve_btn.setMaximumWidth(80) remove_curve_btn.clicked.connect(partial(self.remove_curve, pv_name)) curve_btn_layout = QHBoxLayout() curve_btn_layout.setSpacing(5) curve_btn_layout.addWidget(modify_curve_btn) curve_btn_layout.addWidget(focus_curve_btn) curve_btn_layout.addWidget(clear_curve_btn) # curve_btn_layout.addWidget(annotate_curve_btn) curve_btn_layout.addWidget(remove_curve_btn) individual_curve_layout.addWidget(checkbox) individual_curve_layout.addWidget(data_text) individual_curve_layout.addLayout(curve_btn_layout) self.curve_settings_layout.addWidget(individual_curve_grpbx) self.tab_panel.setCurrentIndex(0)
def generate_pv_controls(self, pv_name, curve_color): """ Generate a set of widgets to manage the appearance of a curve. The set of widgets includes: 1. A checkbox which shows the curve on the chart if checked, and hide the curve if not checked 2. Two buttons -- Modify... and Remove. Modify... will bring up the Curve Settings dialog. Remove will delete the curve from the chart This set of widgets will be hidden initially, until the first curve is plotted. Parameters ---------- pv_name: str The name of the PV the current curve is being plotted for curve_color : QColor The color of the curve to paint for the checkbox label to help the user track the curve to the checkbox """ checkbox = QCheckBox() checkbox.setObjectName(pv_name) palette = checkbox.palette() palette.setColor(QPalette.Active, QPalette.WindowText, curve_color) checkbox.setPalette(palette) display_name = pv_name.split("://")[1] if len(display_name) > MAX_DISPLAY_PV_NAME_LENGTH: # Only display max allowed number of characters of the PV Name display_name = display_name[:int(MAX_DISPLAY_PV_NAME_LENGTH / 2) - 1] + "..." + \ display_name[-int(MAX_DISPLAY_PV_NAME_LENGTH / 2) + 2:] checkbox.setText(display_name) data_text = QLabel() data_text.setObjectName(pv_name) data_text.setPalette(palette) checkbox.setChecked(True) checkbox.clicked.connect( partial(self.handle_curve_chkbox_toggled, checkbox)) curve_btn_layout = QHBoxLayout() modify_curve_btn = QPushButton("Modify...") modify_curve_btn.setObjectName(pv_name) modify_curve_btn.setMaximumWidth(100) modify_curve_btn.clicked.connect( partial(self.display_curve_settings_dialog, pv_name)) focus_curve_btn = QPushButton("Focus") focus_curve_btn.setObjectName(pv_name) focus_curve_btn.setMaximumWidth(100) focus_curve_btn.clicked.connect(partial(self.focus_curve, pv_name)) annotate_curve_btn = QPushButton("Annotate...") annotate_curve_btn.setObjectName(pv_name) annotate_curve_btn.setMaximumWidth(100) annotate_curve_btn.clicked.connect( partial(self.annotate_curve, pv_name)) remove_curve_btn = QPushButton("Remove") remove_curve_btn.setObjectName(pv_name) remove_curve_btn.setMaximumWidth(100) remove_curve_btn.clicked.connect(partial(self.remove_curve, pv_name)) curve_btn_layout.addWidget(modify_curve_btn) curve_btn_layout.addWidget(focus_curve_btn) curve_btn_layout.addWidget(annotate_curve_btn) curve_btn_layout.addWidget(remove_curve_btn) individual_curve_layout = QVBoxLayout() individual_curve_layout.addWidget(checkbox) individual_curve_layout.addWidget(data_text) individual_curve_layout.addLayout(curve_btn_layout) size_policy = QSizePolicy() size_policy.setVerticalPolicy(QSizePolicy.Fixed) individual_curve_grpbx = QGroupBox() individual_curve_grpbx.setSizePolicy(size_policy) individual_curve_grpbx.setObjectName(pv_name) individual_curve_grpbx.setLayout(individual_curve_layout) self.curve_settings_layout.addWidget(individual_curve_grpbx) self.tab_panel.show()
class OpticsCorrWindow(SiriusMainWindow): """Class to include some intelligence in the .ui files.""" def __init__(self, acc, opticsparam, parent=None, prefix=_VACA_PREFIX): """Initialize some widgets.""" super(OpticsCorrWindow, self).__init__(parent) self.prefix = prefix self.acc = acc.upper() self.param = opticsparam self.ioc_prefix = _PVName( self.acc+'-Glob:AP-'+self.param.title()+'Corr') self.ioc_prefix = self.ioc_prefix.substitute(prefix=self.prefix) self.title = self.acc + ' ' + self.param.title() + ' Correction' if self.param == 'tune': self.param_pv = 'DeltaTune{0}-{1}' self.intstrength = 'KL' self.intstrength_calcdesc = 'DeltaKL-Mon' self.intstrength_calcpv = 'DeltaKL{}-Mon' self.fams = list(_Const.SI_QFAMS_TUNECORR) if self.acc == 'SI' \ else list(_Const.BO_QFAMS_TUNECORR) elif self.param == 'chrom': self.param_pv = 'Chrom{0}-{1}' self.intstrength = 'SL' self.intstrength_calcdesc = 'CalcSL-Mon' self.intstrength_calcpv = 'SL{}-Mon' self.fams = list(_Const.SI_SFAMS_CHROMCORR) if self.acc == 'SI' \ else list(_Const.BO_SFAMS_CHROMCORR) self.setWindowTitle(self.title) self.setObjectName(self.acc+'App') self._setupUi() self.setFocus(True) self.setFocusPolicy(Qt.StrongFocus) def _setupUi(self): label = QLabel('<h3>'+self.title+'</h3>', self) label.setStyleSheet(""" min-height:1.55em; max-height: 1.55em; qproperty-alignment: 'AlignVCenter | AlignRight'; background-color: qlineargradient(spread:pad, x1:1, y1:0.0227273, x2:0, y2:0, stop:0 rgba(173, 190, 207, 255), stop:1 rgba(213, 213, 213, 255));""") self.gb_status = QGroupBox('Status', self) self.gb_status.setLayout(self._setupStatusLayout()) self.wid_optics = QWidget() lay_optics = QGridLayout(self.wid_optics) lay_optics.setContentsMargins(0, 0, 0, 0) self.gb_optprm = QGroupBox( 'ΔTune' if self.param == 'tune' else 'Chromaticity', self) self.gb_optprm.setLayout(self._setupOpticsParamLayout()) if self.param == 'tune': self.pb_updref = PyDMPushButton( self, label='Update Reference', pressValue=1, init_channel=self.ioc_prefix.substitute(propty='SetNewRefKL-Cmd')) self.pb_updref.setStyleSheet('min-height:2.4em; max-height:2.4em;') lay_optics.addWidget(self.pb_updref, 0, 0, 1, 2) lay_optics.addWidget(self.gb_optprm, 1, 0) if self.acc == 'SI': self.gb_digmon = QGroupBox('Tune Monitor', self) self.gb_digmon.setLayout(self._setupDigMonLayout()) lay_optics.addWidget(self.gb_digmon, 1, 1) lay_optics.setColumnStretch(0, 3) lay_optics.setColumnStretch(1, 1) else: lay_optics.addWidget(self.gb_optprm, 0, 0) self.gb_fams = QGroupBox('Families', self) self.gb_fams.setLayout(self._setupFamiliesLayout()) self.gb_fams.setSizePolicy(QSzPly.Preferred, QSzPly.Expanding) self.gb_iocctrl = QGroupBox('IOC Control', self) self.gb_iocctrl.setLayout(self._setupIOCControlLayout()) cwt = QWidget() self.setCentralWidget(cwt) if self.acc == 'SI': vlay1 = QVBoxLayout() vlay1.setAlignment(Qt.AlignTop) vlay1.addWidget(self.wid_optics) vlay1.addWidget(self.gb_fams) lay = QGridLayout(cwt) lay.addWidget(label, 0, 0, 1, 2) lay.addLayout(vlay1, 1, 0, alignment=Qt.AlignTop) lay.addWidget(self.gb_iocctrl, 1, 1) lay.addWidget(self.gb_status, 2, 0, 1, 2) lay.setColumnStretch(0, 1) lay.setColumnStretch(1, 1) lay.setRowStretch(0, 1) lay.setRowStretch(1, 15) lay.setRowStretch(2, 5) else: lay = QVBoxLayout(cwt) lay.addWidget(label) lay.addWidget(self.wid_optics) lay.addWidget(self.gb_fams) lay.addWidget(self.gb_iocctrl) lay.addWidget(self.gb_status) self.setStyleSheet(""" PyDMLabel{ qproperty-alignment: AlignCenter; }""") def _setupStatusLayout(self): self.log_label = PyDMLogLabel( self, self.ioc_prefix.substitute(propty='Log-Mon')) lay = QVBoxLayout() lay.addWidget(self.log_label) return lay def _setupOpticsParamLayout(self): self.lb_x = QLabel('<h4>X</h4>', self, alignment=Qt.AlignCenter) self.lb_y = QLabel('<h4>Y</h4>', self, alignment=Qt.AlignCenter) self.lb_sp = QLabel('<h4>SP</h4>', self, alignment=Qt.AlignCenter) self.lb_rb = QLabel('<h4>RB</h4>', self, alignment=Qt.AlignCenter) self.lb_mon = QLabel( '<h4>Estimative</h4>', self, alignment=Qt.AlignCenter) self.sb_paramx = PyDMSpinbox(self, self.ioc_prefix.substitute( propty=self.param_pv.format('X', 'SP'))) self.sb_paramx.showStepExponent = False self.sb_paramy = PyDMSpinbox(self, self.ioc_prefix.substitute( propty=self.param_pv.format('Y', 'SP'))) self.sb_paramy.showStepExponent = False self.lb_paramx = PyDMLabel(self, self.ioc_prefix.substitute( propty=self.param_pv.format('X', 'RB'))) self.lb_paramy = PyDMLabel(self, self.ioc_prefix.substitute( propty=self.param_pv.format('Y', 'RB'))) self.lb_prmmonx = PyDMLabel(self, self.ioc_prefix.substitute( propty=self.param_pv.format('X', 'Mon'))) self.lb_prmmony = PyDMLabel(self, self.ioc_prefix.substitute( propty=self.param_pv.format('Y', 'Mon'))) self.bt_apply = PyDMPushButton( self, label='Apply', pressValue=1, init_channel=self.ioc_prefix.substitute( propty='ApplyDelta-Cmd')) lay = QGridLayout() lay.addWidget(self.lb_sp, 0, 1) lay.addWidget(self.lb_rb, 0, 2) lay.addWidget(self.lb_x, 1, 0) lay.addWidget(self.sb_paramx, 1, 1) lay.addWidget(self.lb_paramx, 1, 2) lay.addWidget(self.lb_y, 2, 0) lay.addWidget(self.sb_paramy, 2, 1) lay.addWidget(self.lb_paramy, 2, 2) lay.addWidget(self.lb_mon, 0, 3) lay.addWidget(self.lb_prmmonx, 1, 3) lay.addWidget(self.lb_prmmony, 2, 3) lay.addWidget(self.bt_apply, 3, 1) lay.setColumnStretch(0, 1) lay.setColumnStretch(1, 5) lay.setColumnStretch(2, 5) lay.setColumnStretch(3, 5) if self.acc == 'SI' and self.param == 'chrom': self._icon_absval = qta.icon( 'mdi.alpha-a', 'mdi.alpha-b', 'mdi.alpha-s', options=[ dict(scale_factor=1.5, offset=(-0.4, 0.0)), dict(scale_factor=1.5, offset=(0.0, 0.0)), dict(scale_factor=1.5, offset=(+0.4, 0.0))]) self._icon_delta = qta.icon('mdi.delta') self._is_setting = 'absolut' self.pb_change_sp = QPushButton(self._icon_absval, '', self) self.pb_change_sp.clicked.connect(self._change_chrom_sp) self.sb_paramx_delta = PyDMSpinbox( self, self.ioc_prefix.substitute(propty='DeltaChromX-SP')) self.sb_paramx_delta.showStepExponent = False self.sb_paramx_delta.setVisible(False) self.sb_paramy_delta = PyDMSpinbox( self, self.ioc_prefix.substitute(propty='DeltaChromY-SP')) self.sb_paramy_delta.showStepExponent = False self.sb_paramy_delta.setVisible(False) self.lb_paramx_delta = PyDMLabel( self, self.ioc_prefix.substitute(propty='DeltaChromX-RB')) self.lb_paramx_delta.setVisible(False) self.lb_paramy_delta = PyDMLabel( self, self.ioc_prefix.substitute(propty='DeltaChromY-RB')) self.lb_paramy_delta.setVisible(False) self.lb_mon.setText('Implem.\nEstimative') self.lb_mon.setStyleSheet('font-weight: bold;') self.lb_calcmon = QLabel( 'Calcd.\nEstimative', self, alignment=Qt.AlignCenter) self.lb_calcmon.setStyleSheet('font-weight: bold;') self.lb_prmcalcmonx = PyDMLabel( self, self.ioc_prefix.substitute(propty='CalcChromX-Mon')) self.lb_prmcalcmony = PyDMLabel( self, self.ioc_prefix.substitute(propty='CalcChromY-Mon')) lay.addWidget(self.pb_change_sp, 0, 0) lay.addWidget(self.sb_paramx_delta, 1, 1) lay.addWidget(self.sb_paramy_delta, 2, 1) lay.addWidget(self.lb_paramx_delta, 1, 2) lay.addWidget(self.lb_paramy_delta, 2, 2) lay.addWidget(self.lb_calcmon, 0, 4) lay.addWidget(self.lb_prmcalcmonx, 1, 4) lay.addWidget(self.lb_prmcalcmony, 2, 4) return lay def _setupDigMonLayout(self): lb_x = QLabel('<h4>X</h4>', self, alignment=Qt.AlignCenter) lb_y = QLabel('<h4>Y</h4>', self, alignment=Qt.AlignCenter) self.lb_tunex = PyDMLabel(self, 'SI-Glob:DI-Tune-H:TuneFrac-Mon') self.lb_tuney = PyDMLabel(self, 'SI-Glob:DI-Tune-V:TuneFrac-Mon') lay = QGridLayout() lay.addWidget(lb_x, 0, 0) lay.addWidget(self.lb_tunex, 0, 1) lay.addWidget(lb_y, 1, 0) lay.addWidget(self.lb_tuney, 1, 1) lay.setColumnStretch(0, 1) lay.setColumnStretch(1, 5) return lay def _setupFamiliesLayout(self): lay = QGridLayout() lb_family = QLabel('<h4>Family</h4>', self, alignment=Qt.AlignCenter) lb_family.setStyleSheet('max-height:1.29em;') lay.addWidget(lb_family, 0, 1) lb_rbdesc = QLabel('<h4>'+self.intstrength+'-RB</h4>', self, alignment=Qt.AlignCenter) lb_rbdesc.setStyleSheet('max-height:1.29em;') lay.addWidget(lb_rbdesc, 0, 2) if self.param == 'tune': lb_refdesc = QLabel('<h4>RefKL-Mon</h4>', self, alignment=Qt.AlignCenter) lb_refdesc.setStyleSheet('max-height:1.29em;') lay.addWidget(lb_refdesc, 0, 3) lb_lastddesc = QLabel('<h4>'+self.intstrength_calcdesc+'</h4>', self, alignment=Qt.AlignCenter) lb_lastddesc.setStyleSheet('max-height:1.29em;') lay.addWidget(lb_lastddesc, 0, 4) row = 1 for fam in self.fams: dev_name = _PVName(self.acc+'-Fam:PS-'+fam) pref_name = dev_name.substitute(prefix=self.prefix) pbt = QPushButton(qta.icon('fa5s.list-ul'), '', self) pbt.setObjectName('pbt') pbt.setStyleSheet(""" #pbt{ min-width:25px; max-width:25px; min-height:25px; max-height:25px; icon-size:20px;}""") _hlautil.connect_window( pbt, _PSDetailWindow, parent=self, psname=dev_name) lay.addWidget(pbt, row, 0) lb_name = QLabel(fam, self, alignment=Qt.AlignCenter) lay.addWidget(lb_name, row, 1) lb_rb = PyDMLabel(self, pref_name.substitute( propty=self.intstrength+'-RB')) lay.addWidget(lb_rb, row, 2) if self.param == 'tune': lb_ref = PyDMLabel(self, self.ioc_prefix.substitute( propty='RefKL'+fam+'-Mon')) lay.addWidget(lb_ref, row, 3) lb_calc = PyDMLabel(self, self.ioc_prefix.substitute( propty=self.intstrength_calcpv.format(fam))) lay.addWidget(lb_calc, row, 4) row += 1 return lay def _setupIOCControlLayout(self): lay = QGridLayout() lb_sts = QLabel('<h4>Status</h4>', self) self.led_sts = _StatusLed(self, self.ioc_prefix.substitute( propty='Status-Mon')) lay.addWidget(lb_sts, 0, 0) lay.addWidget(self.led_sts, 0, 1, alignment=Qt.AlignLeft) lb_conf = QLabel('<h4>Configuration</h4>') self.bt_dtls = QPushButton(qta.icon('fa5s.list-ul'), '', self) _hlautil.connect_window( self.bt_dtls, _CorrParamsDetailWindow, parent=self, acc=self.acc, opticsparam=self.param, prefix=self.prefix, fams=self.fams) lay.addWidget(lb_conf, 2, 0, 1, 2) lay.addWidget(self.bt_dtls, 2, 2, alignment=Qt.AlignRight) lb_cname = QLabel('Name', self) self.le_cname = _ConfigLineEdit( self, self.ioc_prefix.substitute( propty='ConfigName-SP')) self.lb_cname = PyDMLabel(self, self.ioc_prefix.substitute( propty='ConfigName-RB')) lay.addWidget(lb_cname, 3, 0) lay.addWidget(self.le_cname, 3, 1, 1, 2) lay.addWidget(self.lb_cname, 4, 1, 1, 2) row = 5 if self.acc == 'SI': lay.addItem( QSpacerItem(1, 20, QSzPly.Ignored, QSzPly.Fixed), 5, 0) row = 6 if self.param == 'chrom': lb_meas_chrom = QLabel('<h4>Chrom. Measurement</h4>') lay.addWidget(lb_meas_chrom, 6, 0, 1, 3) lb_meas_chrom_dfRF = QLabel('ΔFreq RF [Hz]', self) self.sb_meas_chrom_dfRF = PyDMSpinbox( self, self.ioc_prefix.substitute( propty='MeasChromDeltaFreqRF-SP')) self.sb_meas_chrom_dfRF.showStepExponent = False self.lb_meas_chrom_dfRF = PyDMLabel( self, self.ioc_prefix.substitute( propty='MeasChromDeltaFreqRF-RB')) lay.addWidget(lb_meas_chrom_dfRF, 7, 0) lay.addWidget(self.sb_meas_chrom_dfRF, 7, 1) lay.addWidget(self.lb_meas_chrom_dfRF, 7, 2) lb_meas_chrom_wait = QLabel('Wait Tune [s]', self) self.sb_meas_chrom_wait = PyDMSpinbox( self, self.ioc_prefix.substitute( propty='MeasChromWaitTune-SP')) self.sb_meas_chrom_wait.showStepExponent = False self.lb_meas_chrom_wait = PyDMLabel( self, self.ioc_prefix.substitute( propty='MeasChromWaitTune-RB')) lay.addWidget(lb_meas_chrom_wait, 8, 0) lay.addWidget(self.sb_meas_chrom_wait, 8, 1) lay.addWidget(self.lb_meas_chrom_wait, 8, 2) lb_meas_chrom_nrsteps = QLabel('Nr Steps', self) self.sb_meas_chrom_nrsteps = PyDMSpinbox( self, self.ioc_prefix.substitute( propty='MeasChromNrSteps-SP')) self.sb_meas_chrom_nrsteps.showStepExponent = False self.lb_meas_chrom_nrsteps = PyDMLabel( self, self.ioc_prefix.substitute( propty='MeasChromNrSteps-RB')) lay.addWidget(lb_meas_chrom_nrsteps, 9, 0) lay.addWidget(self.sb_meas_chrom_nrsteps, 9, 1) lay.addWidget(self.lb_meas_chrom_nrsteps, 9, 2) lay.addItem( QSpacerItem(1, 20, QSzPly.Ignored, QSzPly.Fixed), 10, 0) lb_meas_chrom_x = QLabel('Meas. Chrom X', self) self.lb_meas_chrom_x = PyDMLabel( self, self.ioc_prefix.substitute( propty='MeasChromX-Mon')) lay.addWidget(lb_meas_chrom_x, 11, 0) lay.addWidget(self.lb_meas_chrom_x, 11, 1) lb_meas_chrom_y = QLabel('Meas. Chrom Y', self) self.lb_meas_chrom_y = PyDMLabel( self, self.ioc_prefix.substitute( propty='MeasChromY-Mon')) lay.addWidget(lb_meas_chrom_y, 12, 0) lay.addWidget(self.lb_meas_chrom_y, 12, 1) lay.addItem( QSpacerItem(1, 20, QSzPly.Ignored, QSzPly.Fixed), 13, 0) self.lb_meas_chrom_sts = PyDMLabel( self, self.ioc_prefix.substitute( propty='MeasChromStatus-Mon')) self.bt_meas_chrom_start = PyDMPushButton( self, icon=qta.icon('fa5s.play'), label='', init_channel=self.ioc_prefix.substitute( propty='MeasChrom-Cmd'), pressValue=_Const.MeasCmd.Start) self.bt_meas_chrom_start.setObjectName('start') self.bt_meas_chrom_start.setStyleSheet( '#start{min-width:25px; max-width:25px; icon-size:20px;}') self.bt_meas_chrom_stop = PyDMPushButton( self, icon=qta.icon('fa5s.stop'), label='', init_channel=self.ioc_prefix.substitute( propty='MeasChrom-Cmd'), pressValue=_Const.MeasCmd.Stop) self.bt_meas_chrom_stop.setObjectName('stop') self.bt_meas_chrom_stop.setStyleSheet( '#stop{min-width:25px; max-width:25px; icon-size:20px;}') self.bt_meas_chrom_rst = PyDMPushButton( self, icon=qta.icon('fa5s.sync'), label='', init_channel=self.ioc_prefix.substitute( propty='MeasChrom-Cmd'), pressValue=_Const.MeasCmd.Reset) self.bt_meas_chrom_rst.setObjectName('rst') self.bt_meas_chrom_rst.setStyleSheet( '#rst{min-width:25px; max-width:25px; icon-size:20px;}') hbox_cmd = QHBoxLayout() hbox_cmd.addWidget(self.bt_meas_chrom_start) hbox_cmd.addWidget(self.bt_meas_chrom_stop) hbox_cmd.addWidget(self.bt_meas_chrom_rst) lay.addWidget(self.lb_meas_chrom_sts, 14, 0, 1, 2) lay.addLayout(hbox_cmd, 14, 2) lay.addItem( QSpacerItem(1, 20, QSzPly.Ignored, QSzPly.Fixed), 15, 0) row = 15 # configuration measurement lb_meas_conf = QLabel('<h4>Config. Measurement</h4>') lay.addWidget(lb_meas_conf, row+1, 0, 1, 3) mag_type = 'Q' if self.param == 'tune' else 'S' unit = '[1/m]' if self.param == 'tune' else '[1/m2]' lb_meas_conf_dfamF = QLabel( 'Fam. Δ'+self.intstrength+' '+mag_type+'F '+unit, self) self.sb_meas_conf_dfamF = PyDMSpinbox( self, self.ioc_prefix.substitute( propty='MeasConfigDelta'+self.intstrength + 'Fam'+mag_type+'F-SP')) self.sb_meas_conf_dfamF.showStepExponent = False self.lb_meas_conf_dfamF = PyDMLabel( self, self.ioc_prefix.substitute( propty='MeasConfigDelta'+self.intstrength + 'Fam'+mag_type+'F-RB')) lay.addWidget(lb_meas_conf_dfamF, row+2, 0) lay.addWidget(self.sb_meas_conf_dfamF, row+2, 1) lay.addWidget(self.lb_meas_conf_dfamF, row+2, 2) lb_meas_conf_dfamD = QLabel( 'Fam. Δ'+self.intstrength+' '+mag_type+'D '+unit, self) self.sb_meas_conf_dfamD = PyDMSpinbox( self, self.ioc_prefix.substitute( propty='MeasConfigDelta'+self.intstrength + 'Fam'+mag_type+'D-SP')) self.sb_meas_conf_dfamD.showStepExponent = False self.lb_meas_conf_dfamD = PyDMLabel( self, self.ioc_prefix.substitute( propty='MeasConfigDelta'+self.intstrength + 'Fam'+mag_type+'D-RB')) lay.addWidget(lb_meas_conf_dfamD, row+3, 0) lay.addWidget(self.sb_meas_conf_dfamD, row+3, 1) lay.addWidget(self.lb_meas_conf_dfamD, row+3, 2) lb_meas_conf_wait = QLabel('Wait [s]', self) self.sb_meas_conf_wait = PyDMSpinbox( self, self.ioc_prefix.substitute(propty='MeasConfigWait-SP')) self.sb_meas_conf_wait.showStepExponent = False self.lb_meas_conf_wait = PyDMLabel( self, self.ioc_prefix.substitute(propty='MeasConfigWait-RB')) lay.addWidget(lb_meas_conf_wait, row+4, 0) lay.addWidget(self.sb_meas_conf_wait, row+4, 1) lay.addWidget(self.lb_meas_conf_wait, row+4, 2) lb_meas_conf_cname = QLabel('Name to save', self) self.le_meas_conf_name = PyDMLineEdit( self, self.ioc_prefix.substitute(propty='MeasConfigName-SP')) self.lb_meas_conf_name = PyDMLabel( self, self.ioc_prefix.substitute(propty='MeasConfigName-RB')) lay.addWidget(lb_meas_conf_cname, row+5, 0) lay.addWidget(self.le_meas_conf_name, row+5, 1, 1, 2) lay.addWidget(self.lb_meas_conf_name, row+6, 1, 1, 2) lb_meas_conf_save = QLabel('Force Save', self) self.bt_meas_conf_save = PyDMPushButton( self, icon=qta.icon('mdi.content-save'), label='', init_channel=self.ioc_prefix.substitute( propty='MeasConfigSave-Cmd'), pressValue=1) self.bt_meas_conf_save.setObjectName('save') self.bt_meas_conf_save.setStyleSheet( '#save{min-width:25px; max-width:25px; icon-size:20px;}') lay.addWidget(lb_meas_conf_save, row+7, 0) lay.addWidget( self.bt_meas_conf_save, row+7, 1, alignment=Qt.AlignLeft) lay.addItem( QSpacerItem(1, 20, QSzPly.Ignored, QSzPly.Fixed), row+8, 0) self.lb_meas_conf_sts = PyDMLabel( self, self.ioc_prefix.substitute( propty='MeasConfigStatus-Mon')) self.bt_meas_conf_start = PyDMPushButton( self, icon=qta.icon('fa5s.play'), label='', init_channel=self.ioc_prefix.substitute( propty='MeasConfig-Cmd'), pressValue=_Const.MeasCmd.Start) self.bt_meas_conf_start.setObjectName('start') self.bt_meas_conf_start.setStyleSheet( '#start{min-width:25px; max-width:25px; icon-size:20px;}') self.bt_meas_conf_stop = PyDMPushButton( self, icon=qta.icon('fa5s.stop'), label='', init_channel=self.ioc_prefix.substitute( propty='MeasConfig-Cmd'), pressValue=_Const.MeasCmd.Stop) self.bt_meas_conf_stop.setObjectName('stop') self.bt_meas_conf_stop.setStyleSheet( '#stop{min-width:25px; max-width:25px; icon-size:20px;}') self.bt_meas_conf_rst = PyDMPushButton( self, icon=qta.icon('fa5s.sync'), label='', init_channel=self.ioc_prefix.substitute( propty='MeasConfig-Cmd'), pressValue=_Const.MeasCmd.Reset) self.bt_meas_conf_rst.setObjectName('rst') self.bt_meas_conf_rst.setStyleSheet( '#rst{min-width:25px; max-width:25px; icon-size:20px;}') hbox_cmd = QHBoxLayout() hbox_cmd.addWidget(self.bt_meas_conf_start) hbox_cmd.addWidget(self.bt_meas_conf_stop) hbox_cmd.addWidget(self.bt_meas_conf_rst) lay.addWidget(self.lb_meas_conf_sts, row+9, 0, 1, 2) lay.addLayout(hbox_cmd, row+9, 2) lay.addItem( QSpacerItem(1, 20, QSzPly.Ignored, QSzPly.Fixed), row+10, 0) # correction settings lb_corr = QLabel('<h4>Settings</h4>') lay.addWidget(lb_corr, row+11, 0, 1, 3) lb_meth = QLabel('Method', self) self.cb_method = PyDMEnumComboBox( self, self.ioc_prefix.substitute(propty='CorrMeth-Sel')) self.lb_method = PyDMLabel( self, self.ioc_prefix.substitute(propty='CorrMeth-Sts')) lay.addWidget(lb_meth, row+12, 0) lay.addWidget(self.cb_method, row+12, 1) lay.addWidget(self.lb_method, row+12, 2) lb_grp = QLabel('Grouping', self) self.cb_group = PyDMEnumComboBox( self, self.ioc_prefix.substitute(propty='CorrGroup-Sel')) self.lb_group = PyDMLabel( self, self.ioc_prefix.substitute(propty='CorrGroup-Sts')) lay.addWidget(lb_grp, row+13, 0) lay.addWidget(self.cb_group, row+13, 1) lay.addWidget(self.lb_group, row+13, 2) if self.param == 'tune': lb_sync = QLabel('Sync', self) self.bt_sync = PyDMStateButton( self, self.ioc_prefix.substitute(propty='SyncCorr-Sel')) self.bt_sync.shape = 1 self.lb_sync = PyDMLabel( self, self.ioc_prefix.substitute(propty='SyncCorr-Sts')) lay.addWidget(lb_sync, row+14, 0) lay.addWidget(self.bt_sync, row+14, 1) lay.addWidget(self.lb_sync, row+14, 2) row = row + 15 lay.addItem( QSpacerItem(1, 20, QSzPly.Ignored, QSzPly.Expanding), row, 0) return lay def _change_chrom_sp(self): cond = self._is_setting == 'absolut' self._is_setting = 'delta' if cond else 'absolut' icon = self._icon_delta if cond else self._icon_absval textX = '<h4>Δ-SP</h4>' if cond else '<h4>SP</h4>' textY = '<h4>Δ-RB</h4>' if cond else '<h4>RB</h4>' self.sb_paramx.setVisible(not cond) self.lb_paramx.setVisible(not cond) self.sb_paramy.setVisible(not cond) self.lb_paramy.setVisible(not cond) self.sb_paramx_delta.setVisible(cond) self.lb_paramx_delta.setVisible(cond) self.sb_paramy_delta.setVisible(cond) self.lb_paramy_delta.setVisible(cond) self.pb_change_sp.setIcon(icon) self.lb_sp.setText(textX) self.lb_rb.setText(textY)