def setupui(self): vbl = QVBoxLayout(self) tip = 'Configure ' + ('Acquisition' if self.is_orb else 'Correctors') pv = 'TrigAcqConfig-Cmd' if self.is_orb else 'CorrConfig-Cmd' conf = PyDMPushButton(self, init_channel=self.devpref.substitute(propty=pv), pressValue=1) conf.setToolTip(tip) conf.setIcon(qta.icon('fa5s.sync')) conf.setObjectName('conf') conf.setStyleSheet( '#conf{min-width:25px; max-width:25px; icon-size:20px;}') vbl.addWidget(conf) pv = 'Orb' if self.is_orb else 'Corr' pdm_led = SiriusLedAlert( self, self.devpref.substitute(propty=pv + 'Status-Mon')) hbl = QHBoxLayout() hbl.setSpacing(9) hbl.addWidget(pdm_led) hbl.addWidget(QLabel('Global Status', self)) hbl.addStretch() hbl.addWidget(conf) vbl.addItem(hbl) grpbx = self.creategroupbox() vbl.addWidget(grpbx)
def _interlock_layout(self): interlock_layout = QGridLayout() intlk_cnt = 8 if 'Sept' not in self._devname else 7 for i in range(intlk_cnt): label = PyDMLabel( self, getattr(self, '_intlk' + str(i + 1) + '_lbcte_pv')) led = PyDMLed(self, getattr(self, '_intlk' + str(i + 1) + '_mon_pv')) led.onColor = led.LightGreen led.offColor = led.Red interlock_layout.addWidget(led, i, 0) interlock_layout.addWidget(label, i, 1) self.reset_bt = PyDMPushButton(parent=self, init_channel=self._reset_cmd_pv, pressValue=1) self.reset_bt.setIcon(qta.icon('fa5s.sync')) self.reset_bt.setObjectName('reset_bt') self.reset_bt.setStyleSheet( '#reset_bt{min-width:25px; max-width:25px; icon-size:20px;}') interlock_layout.addWidget(self.reset_bt, i + 1, 0, 1, 2, alignment=Qt.AlignHCenter) return interlock_layout
def _setupConfigurationWidget(self): statebutton_Test = PyDMStateButton( self, self.dcct_prefix.substitute(propty='Test-Sel')) statebutton_Test.shape = 1 statebutton_Test.setStyleSheet('min-width:6em; max-width:6em;') label_Test = PyDMLabel(self, self.dcct_prefix.substitute(propty='Test-Sts')) hlay_test = QHBoxLayout() hlay_test.addWidget(statebutton_Test) hlay_test.addWidget(label_Test) self.bt_dl = PyDMPushButton( parent=self, pressValue=1, icon=qta.icon('fa5s.sync'), init_channel=self.dcct_prefix.substitute(propty='Download-Cmd')) self.bt_dl.setObjectName('bt_dl') self.bt_dl.setStyleSheet( '#bt_dl{min-width:25px; max-width:25px; icon-size:20px;}') gbox_test = QGroupBox('Configurations') lay = QFormLayout(gbox_test) lay.setLabelAlignment(Qt.AlignRight) lay.setFormAlignment(Qt.AlignCenter) lay.addRow('Enable test current: ', hlay_test) lay.addRow('Download Configurations: ', self.bt_dl) return gbox_test
def _auxCommandsWidget(self): self._ld_speedlim = QLabel('Max Phase Speed\n[mm/s]', self) self._sb_speedlim = PyDMSpinbox( self, self.dev_pref.substitute(propty='MaxPhaseSpeed-SP')) self._sb_speedlim.showStepExponent = False self._sb_speedlim.setStyleSheet('max-width:4.5em;') self._lb_speedlim = PyDMLabel( self, self.dev_pref.substitute(propty='MaxPhaseSpeed-RB')) self._ld_homeaxis = QLabel('Do homing', self) self._pb_home = PyDMPushButton(self, label='', icon=qta.icon('mdi.keyboard-return')) self._pb_home.setToolTip('Execute homing for selected axis.') self._pb_home.channel = self.dev_pref.substitute(propty='DevCtrl-Cmd') self._pb_home.pressValue = 10 # Home self._pb_home.setObjectName('Home') self._pb_home.setStyleSheet( '#Home{min-width:30px; max-width:30px; icon-size:25px;}') self._ld_standby = QLabel('Enable Standby Mode', self) self._pb_standby = PyDMPushButton( self, label='', icon=qta.icon('mdi.alpha-a-box-outline')) self._pb_standby.setToolTip( 'Enable standby mode for automatic motion.') self._pb_standby.channel = \ self.dev_pref.substitute(propty='DevCtrl-Cmd') self._pb_standby.pressValue = 5 # Standby self._pb_standby.setObjectName('Standby') self._pb_standby.setStyleSheet( '#Standby{min-width:30px; max-width:30px; icon-size:25px;}') self._ld_lastcomm = QLabel('Last Command', self) self._lb_lastcomm = PyDMLabel( self, self.dev_pref.substitute(propty='LastDevCtrlCmd-Mon')) gbox_auxcmd = QGroupBox('Auxiliary Commands', self) lay_auxcmd = QGridLayout(gbox_auxcmd) lay_auxcmd.addWidget(self._ld_speedlim, 0, 0) lay_auxcmd.addWidget(self._sb_speedlim, 0, 1) lay_auxcmd.addWidget(self._lb_speedlim, 0, 2) lay_auxcmd.addItem(QSpacerItem(1, 10, QSzPlcy.Ignored, QSzPlcy.Fixed), 1, 0) lay_auxcmd.addWidget(self._ld_homeaxis, 2, 0) lay_auxcmd.addWidget(self._pb_home, 2, 1, 1, 2, alignment=Qt.AlignCenter) lay_auxcmd.addWidget(self._ld_standby, 3, 0) lay_auxcmd.addWidget(self._pb_standby, 3, 1, 1, 2, alignment=Qt.AlignCenter) lay_auxcmd.addWidget(self._ld_lastcomm, 4, 0) lay_auxcmd.addWidget(self._lb_lastcomm, 4, 1, 1, 2) return gbox_auxcmd
def setupui(self): self.layoutg = QGridLayout(self) grpbx = self._create_formlayout_groupbox( 'General Configurations', (('BPMMode-Sel', 'Operation Mode'), ('TriggerRep-Sel', 'Repeat Acquisitions'), ('TriggerHwDly-SP', 'Delay [us]'), ('SamplesPre-SP', 'Pre-Trigger NrSamples'), ('SamplesPost-SP', 'Post-Trigger NrSamples'), ('Trigger-Sel', 'Trigger Type'))) self.layoutg.addWidget(grpbx, 0, 0) grpbx = QGroupBox('Acquisition Control', self) gdl = QGridLayout(grpbx) pb1 = PyDMPushButton(grpbx, init_channel=self.get_pvname('TriggerEvent-Sel'), label='Start', pressValue=0) gdl.addWidget(pb1, 0, 0) pb2 = PyDMPushButton(grpbx, init_channel=self.get_pvname('TriggerEvent-Sel'), label='Stop', pressValue=1) gdl.addWidget(pb2, 0, 1) pb1 = PyDMPushButton(grpbx, init_channel=self.get_pvname('TriggerEvent-Sel'), label='Abort', pressValue=2) gdl.addWidget(pb1, 1, 0) lab = QLabel('Status:') lab.setAlignment(Qt.AlignCenter) gdl.addWidget(lab, 2, 0) lab = PyDMLabel(grpbx, init_channel=self.get_pvname('Status-Sts')) lab.setAlignment(Qt.AlignCenter) gdl.addWidget(lab, 2, 1) self.layoutg.addWidget(grpbx, 1, 0) grpbx = self._create_formlayout_groupbox('MultiBunch Configurations', ( ('Channel-Sel', 'Acquisition Rate'), ('Shots-SP', 'Number of Shots'), ('UpdateTime-SP', 'Update Interval'), ('TbtTagEn-Sel', 'Sync Timing', False), ('TbtTagDly-SP', 'TbT Delay', False), ('TbtDataMaskEn-Sel', 'Mask Data', False), ('TbtDataMaskSamplesBeg-SP', 'Mask Begin', False), ('TbtDataMaskSamplesEnd-SP', 'Mask End', False), )) grpbx.rules = self.basic_rule('BPMMode-Sts', True) self.layoutg.addWidget(grpbx, 2, 0) grpbx = self._create_formlayout_groupbox( 'Auto Trigger Configurations', (('DataTrigChan-Sel', 'Type of Rate as Trigger'), ('TriggerDataSel-SP', 'Channel'), ('TriggerDataPol-Sel', 'Slope'), ('TriggerDataThres-SP', 'Threshold'), ('TriggerDataHyst-SP', 'Hysteresis'))) grpbx.rules = self.basic_rule('Trigger-Sts', True, val=2) self.layoutg.addWidget(grpbx, 3, 0)
def _setupFull(self): lay = QGridLayout(self) lay.addWidget(QLabel('Off', self, alignment=Qt.AlignCenter), 0, 1) lay.addWidget(QLabel('On', self, alignment=Qt.AlignCenter), 0, 2) lay.addWidget(QLabel('Status', self, alignment=Qt.AlignCenter), 0, 3) self._checkbox_off = dict() self._checkbox_on = dict() self._labels_sts = dict() for idx, name in enumerate(self._handler.DEF_ON_ORDER): cb_off = QCheckBox(self) cb_off.setObjectName(name) self._checkbox_off[name] = cb_off cb_on = QCheckBox(self) cb_on.setObjectName(name) self._checkbox_on[name] = cb_on desc = self._handler.HANDLER_DESC[name] splitd = desc.split('(') lbl_txt = splitd[0] tip = '' if len(splitd) > 1: lbl_txt, tip = splitd lb_dsc = QLabel(lbl_txt, self, alignment=Qt.AlignLeft) if tip: lb_dsc.setToolTip(tip[:-1]) lb_sts = QLabel('', self, alignment=Qt.AlignCenter) lb_sts.setObjectName(name) self._labels_sts[name] = lb_sts lay.addWidget(lb_dsc, idx + 1, 0) lay.addWidget(cb_off, idx + 1, 1, alignment=Qt.AlignCenter) lay.addWidget(cb_on, idx + 1, 2, alignment=Qt.AlignCenter) lay.addWidget(lb_sts, idx + 1, 3) self._pb_off = PyDMPushButton(self, label='', icon=self._icon_off, init_channel=self._inj_prefix.substitute( propty='InjSysTurnOff-Cmd'), pressValue=0) self._pb_off.setObjectName('bt') self._pb_off.setStyleSheet( '#bt{min-width:25px; max-width:25px; icon-size:20px;}') self._pb_on = PyDMPushButton(self, label='', icon=self._icon_on, init_channel=self._inj_prefix.substitute( propty='InjSysTurnOn-Cmd'), pressValue=0) self._pb_on.setObjectName('bt') self._pb_on.setStyleSheet( '#bt{min-width:25px; max-width:25px; icon-size:20px;}') self._led_sts = InjSysStbyLed(self) lay.addWidget(self._pb_off, 6, 1) lay.addWidget(self._pb_on, 6, 2) lay.addWidget(self._led_sts, 6, 3)
def __init__(self, parent=None, init_channel=None, label='', icon=None, pressValue=1, releaseValue=None, relative=False): PyDMPushButton.__init__( self, parent=parent, label=label, icon=icon, pressValue=pressValue, relative=relative, init_channel=init_channel) self._releaseValue = releaseValue self.clicked.disconnect(self.sendValue) self.pressed.connect(self.sendValue) self.released.connect(self.sendReleaseValue)
def _statusWidget(self): label_Conn = QLabel('Connection:', self) hbox_Conn = create_propty_layout(parent=self, prefix=self.cam_prefix, propty='Connection', propty_type='mon') label_Temp = QLabel('Temperature State:', self) self.lb_Temp = PyDMLabel(self, self.cam_prefix.substitute(propty='Temp-Mon')) self.lb_Temp.setStyleSheet('min-width:7.1em; max-width:7.1em;') self.lb_Temp.setAlignment(Qt.AlignCenter) self.led_TempState = SiriusLedAlert( self, self.cam_prefix.substitute(propty='TempState-Mon')) self.led_TempState.setStyleSheet('min-width:1.29em; max-width:1.29em;') self.lb_TempState = PyDMLabel( self, self.cam_prefix.substitute(propty='TempState-Mon')) self.lb_TempState.setStyleSheet('min-width:2.5em; max-width:2.5em;') hbox_Temp = QHBoxLayout() hbox_Temp.addWidget(self.lb_Temp) hbox_Temp.addWidget(self.led_TempState) hbox_Temp.addWidget(self.lb_TempState) label_LastErr = QLabel('Last Error:', self) hbox_LastErr = create_propty_layout(parent=self, prefix=self.cam_prefix, propty='LastErr', propty_type='mon', cmd={ 'label': 'Clear Last Error', 'pressValue': 1, 'name': 'ClearLastErr' }) label_Reset = QLabel('Reset Camera:', self) self.pb_dtl = PyDMPushButton( label='', icon=qta.icon('fa5s.sync'), parent=self, pressValue=1, init_channel=self.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;}") wid = QWidget() flay = QFormLayout(wid) flay.setLabelAlignment(Qt.AlignRight) flay.setFormAlignment(Qt.AlignHCenter) flay.addRow(label_Conn, hbox_Conn) flay.addRow(label_Temp, hbox_Temp) flay.addRow(label_LastErr, hbox_LastErr) flay.addRow(label_Reset, self.pb_dtl) return wid
def insertDeviceMonitorRow(self, switchIp, pvName): row = self.insertNewRow() #Set each widget properties and insert on respective table row #Swich Ip Label w = QLabel() w.setText(switchIp) w.setAlignment(QtCore.Qt.AlignCenter) self.table.setCellWidget(row, 0, w) #Device name label creation self.table.setColumnWidth(1, 150) w = QLabel() w.setText(pvName) w.setAlignment(QtCore.Qt.AlignCenter) self.table.setCellWidget(row, 1, w) #Status byte indicator creation w = PyDMByteIndicator(init_channel='ca://' + pvName + ':PwrState-Sts') w.circles = True w.showLabels = False w.onColor = QtGui.QColor(0, 255, 0) w.offColor = QtGui.QColor(255, 0, 0) w.alarmSensitiveBorder = True w.alarmSensitiveContent = True self.table.setCellWidget(row, 2, w) #Raw status label creation self.table.setColumnWidth(3, 150) w = PyDMLabel(init_channel='ca://' + pvName + ':PwrState-Raw') w.alarmSensitiveBorder = True w.setAlignment(QtCore.Qt.AlignCenter) self.table.setCellWidget(row, 3, w) #Turn On push button creation w = PyDMPushButton(label='Turn On', init_channel='ca://' + pvName + ':PwrState-Sel', pressValue=1) w.alarmSensitiveContent = True self.table.setCellWidget(row, 4, w) #Turn Off push button creation w = PyDMPushButton(label='Turn Off', init_channel='ca://' + pvName + ':PwrState-Sel', pressValue=0) w.alarmSensitiveContent = True self.table.setCellWidget(row, 5, w)
def _get_multturn_acq_grpbx(self): grp_bx = QWidget(self) fbl = QFormLayout(grp_bx) lbl = QLabel('Downsampling', grp_bx, alignment=Qt.AlignCenter) wid = self.create_pair(grp_bx, 'MTurnDownSample') fbl.addRow(lbl, wid) lbl = QLabel('Index', grp_bx, alignment=Qt.AlignCenter) wid = self.create_pair(grp_bx, 'MTurnIdx') fbl.addRow(lbl, wid) lbl = QLabel('Index Time', grp_bx, alignment=Qt.AlignCenter) wid = QWidget(grp_bx) pdm_lbl = SiriusLabel( wid, self.devpref.substitute(propty='MTurnIdxTime-Mon')) pdm_lbl.showUnits = True pdm_lbl.setAlignment(Qt.AlignCenter) conf = PyDMPushButton( wid, pressValue=1, init_channel=self.devpref.substitute(propty='MTurnAcquire-Cmd')) conf.setToolTip('Update MTurn PVs') conf.setIcon(qta.icon('fa5s.sync')) conf.setObjectName('conf') conf.setStyleSheet( '#conf{min-width:25px; max-width:25px; icon-size:20px;}') hbl = QHBoxLayout(wid) hbl.addWidget(pdm_lbl) hbl.addWidget(conf) fbl.addRow(lbl, wid) lbl = QLabel('TbT Sync', grp_bx, alignment=Qt.AlignCenter) wid = self.create_pair_butled(grp_bx, 'MTurnSyncTim') fbl.addRow(lbl, wid) self._set_detailed([lbl, wid]) lbl = QLabel('TbT Mask', grp_bx, alignment=Qt.AlignCenter) wid = self.create_pair_butled(grp_bx, 'MTurnUseMask') fbl.addRow(lbl, wid) self._set_detailed([lbl, wid]) lbl = QLabel('Mask Begin', grp_bx, alignment=Qt.AlignCenter) wid = self.create_pair(grp_bx, 'MTurnMaskSplBeg') fbl.addRow(lbl, wid) self._set_detailed([lbl, wid]) lbl = QLabel('Mask End', grp_bx, alignment=Qt.AlignCenter) wid = self.create_pair(grp_bx, 'MTurnMaskSplEnd') fbl.addRow(lbl, wid) self._set_detailed([lbl, wid]) return grp_bx
def _configLayout(self): self.bt_rst = PyDMPushButton( parent=self, init_channel=self.device.substitute(propty='Rst-Cmd'), pressValue=1, icon=qta.icon('fa5s.sync')) self.bt_rst.setObjectName('bt_rst') self.bt_rst.setStyleSheet( '#bt_rst{min-width:25px; max-width:25px; icon-size:20px;}') lay = QFormLayout() lay.setLabelAlignment(Qt.AlignRight) lay.setFormAlignment(Qt.AlignCenter) lay.addRow('Restore Default', self.bt_rst) return lay
def _setupCoeffSettingsWidget(self): ld_coefchoo = QLabel('Choose Set', self, alignment=Qt.AlignRight) cb_coefchoo = PyDMEnumComboBox(self, self.dev_pref + ':LDSET') pb_coefload = PyDMPushButton(parent=self, label='Apply Set', icon=qta.icon('mdi.upload'), init_channel=self.dev_pref + ':BO_CPCOEFF', pressValue=1) pb_coefload.setStyleSheet("icon-size:20px;") pb_coefvrfy = PyDMPushButton(parent=self, label='Verify Set', icon=qta.icon('mdi.check-circle-outline'), init_channel=self.dev_pref + ':BO_CVERIFY', pressValue=1) pb_coefvrfy.setStyleSheet("icon-size:20px;") ld_gen = QLabel('<h4>Generate Coefficients</h4>', self, alignment=Qt.AlignCenter) ld_gengain = QLabel('Gain [0-1]', self, alignment=Qt.AlignRight) sb_gengain = PyDMSpinbox(self, self.dev_pref + ':FLT_GAIN') sb_gengain.showStepExponent = False ld_genphs = QLabel('Phase [°]', self, alignment=Qt.AlignRight) sb_genphs = PyDMSpinbox(self, self.dev_pref + ':FLT_PHASE') sb_genphs.showStepExponent = False ld_genfreq = QLabel('Frequency [0-1]', self, alignment=Qt.AlignRight) sb_genfreq = PyDMSpinbox(self, self.dev_pref + ':FLT_FREQ') sb_genfreq.showStepExponent = False ld_genntap = QLabel('Number of taps', self, alignment=Qt.AlignRight) sb_genntap = PyDMSpinbox(self, self.dev_pref + ':FLT_TAPS') sb_genntap.showStepExponent = False wid = QWidget(self) lay_genset = QGridLayout(wid) lay_genset.setVerticalSpacing(6) lay_genset.setHorizontalSpacing(9) lay_genset.addWidget(ld_gen, 0, 1, 1, 2) lay_genset.addWidget(ld_gengain, 1, 1) lay_genset.addWidget(sb_gengain, 1, 2) lay_genset.addWidget(ld_genphs, 2, 1) lay_genset.addWidget(sb_genphs, 2, 2) lay_genset.addWidget(ld_genfreq, 3, 1) lay_genset.addWidget(sb_genfreq, 3, 2) lay_genset.addWidget(ld_genntap, 4, 1) lay_genset.addWidget(sb_genntap, 4, 2) lay_genset.addWidget(ld_coefchoo, 5, 1) lay_genset.addWidget(cb_coefchoo, 5, 2) lay = QGridLayout() lay_genset.addLayout(lay, 6, 1, 1, 2) lay.addWidget(pb_coefload, 0, 0) lay.addWidget(pb_coefvrfy, 0, 2) lay.setColumnStretch(1, 2) lay_genset.setRowStretch(7, 2) lay_genset.setColumnStretch(0, 2) lay_genset.setColumnStretch(3, 2) return wid
def connection_changed(self, connected): build = (self._node is None) and (self._connected != connected and connected is True) super(SystemLog, self).connection_changed(connected) if not build: return self._node = nodeFromAddress(self.channel) self._path = self.channel.replace('SystemLog', 'ClearLog') vb = QVBoxLayout() self.setLayout(vb) gb = QGroupBox('System Log (20 most recent entries)') vb.addWidget(gb) vb = QVBoxLayout() gb.setLayout(vb) self._systemLog = QTreeWidget() vb.addWidget(self._systemLog) self._systemLog.setColumnCount(2) self._systemLog.setHeaderLabels(['Field', 'Value']) self._systemLog.setColumnWidth(0, 200) self._pb = PyDMPushButton(label='Clear Log', pressValue=1, init_channel=self._path) vb.addWidget(self._pb)
class ICTChannelEntry(QFrame): def __init__(self, side, num): self.side = side self.num = num self.layout = QHBoxLayout() self.setLayout(self.layout) self.objectName = 'ICT_Channel_' + str(side) + str(num) # Add the toggle button colorButtonTable = { "CLOSED": [ "rgb(0, 255, 0)", # Background "rgb(0, 0, 0)" # Foreground ], "OPEN": ["rgb(255, 0, 0)", "rgb(255, 255, 255)"] } colorButtonLabelTable = {"ENABLED": "ONLINE", "DISABLED": "OFFLINE"} # Add the OFF button self.offBtn = PyDMPushButton( parent=self, label='TURN OFF', pressValue='1', init_channel='ca://$\{BASE\}:Output{0}{1}:SetState'.format( num, side)) self.offBtn.setStyleSheet("\ PyDMPushButton { \ background-color: rgb(255, 0, 0); \ color: rgb(255, 255, 255); \ }") self.layout.addWidget(self.offBtn) # Add the ON button self.onBtn = PyDMPushButton( parent=self, label='TURN ON', pressValue='0', init_channel='ca://$\{BASE\}:Output{0}{1}:SetState'.format( num, side)) self.onBtn.setStyleSheet("\ PyDMPushButton { \ background-color: rgb(0, 255, 0); \ color: rgb(0, 0, 0); \ }") self.layout.addWidget(self.onBtn) self.setLayout(self.layout)
def connection_changed(self, connected): build = (self._node is None) and (self._connected != connected and connected is True) super(DebugTree, self).connection_changed(connected) if not build: return self._node = nodeFromAddress(self.channel) self._path = self.channel vb = QVBoxLayout() self.setLayout(vb) self._tree = QTreeWidget() vb.addWidget(self._tree) self._tree.setColumnCount(5) self._tree.setHeaderLabels( ['Node', 'Mode', 'Type', 'Variable', 'Command', 'Units']) self._tree.itemExpanded.connect(self._expandCb) hb = QHBoxLayout() vb.addLayout(hb) if self._node.isinstance(pyrogue.Root): hb.addWidget( PyDMPushButton(label='Read All', pressValue=True, init_channel=self._path + '.ReadAll')) else: hb.addWidget( PyDMPushButton(label='Read Recursive', pressValue=True, init_channel=self._path + '.ReadDevice')) self.setUpdatesEnabled(False) DebugDev(path=self._path, top=self, parent=self._tree, dev=self._node, noExpand=False) self.setUpdatesEnabled(True)
def _setupSummary(self): self._pb_off = PyDMPushButton(self, label='', icon=self._icon_off, init_channel=self._inj_prefix.substitute( propty='InjSysTurnOff-Cmd'), pressValue=0) self._pb_off.setObjectName('bt') self._pb_off.setStyleSheet( '#bt{min-width:25px; max-width:25px; icon-size:20px;}') self._pb_on = PyDMPushButton(self, label='', icon=self._icon_on, init_channel=self._inj_prefix.substitute( propty='InjSysTurnOn-Cmd'), pressValue=0) self._pb_on.setObjectName('bt') self._pb_on.setStyleSheet( '#bt{min-width:25px; max-width:25px; icon-size:20px;}') self._led_sts = InjSysStbyLed(self) self._led_sts.setStyleSheet( 'QLed{min-width:1.29em; max-width:1.29em;}') lay = QGridLayout(self) lay.setAlignment(Qt.AlignCenter) lay.addWidget(self._pb_off, 0, 0) lay.addWidget(self._pb_on, 0, 1) lay.addWidget(self._led_sts, 1, 0, 1, 2, alignment=Qt.AlignCenter) # menu for cmmtype in ['on', 'off']: order = getattr(self._handler, cmmtype + '_order') menu = QMenu('Select Turn ' + cmmtype.upper() + ' Commands', self) setattr(self, cmmtype + '_menu', menu) self.menu.addMenu(menu) for cmm in order: act = menu.addAction(self._handler.HANDLER_DESC[cmm]) act.setObjectName(cmm) act.setCheckable(True)
def _get_single_pass_acq_grpbx(self): grp_bx = QWidget(self) fbl = QFormLayout(grp_bx) lbl = QLabel('Avg Turns', grp_bx, alignment=Qt.AlignCenter) wid = self.create_pair(grp_bx, 'SPassAvgNrTurns') fbl.addRow(lbl, wid) lbl = QLabel('Mask Begin', grp_bx, alignment=Qt.AlignCenter) wid = self.create_pair(grp_bx, 'SPassMaskSplBeg') fbl.addRow(lbl, wid) self._set_detailed([lbl, wid]) lbl = QLabel('Mask End', grp_bx, alignment=Qt.AlignCenter) wid = self.create_pair(grp_bx, 'SPassMaskSplEnd') fbl.addRow(lbl, wid) self._set_detailed([lbl, wid]) wid = QWidget(grp_bx) self._set_detailed(wid) hbl = QHBoxLayout(wid) pdm_btn1 = PyDMPushButton( init_channel=self.devpref.substitute(propty='SPassBgCtrl-Cmd'), pressValue=0, label='Acquire') pdm_btn2 = PyDMPushButton( init_channel=self.devpref.substitute(propty='SPassBgCtrl-Cmd'), pressValue=1, label='Reset') pdm_lbl = PyDMLabel(wid, self.devpref.substitute(propty='SPassBgSts-Mon')) hbl.addWidget(pdm_btn1) hbl.addWidget(pdm_btn2) hbl.addWidget(pdm_lbl) lbl = QLabel('BG acq.:', grp_bx, alignment=Qt.AlignCenter) fbl.addRow(lbl, wid) lbl = QLabel('Use BG', grp_bx, alignment=Qt.AlignCenter) wid = self.create_pair_butled(grp_bx, 'SPassUseBg') fbl.addRow(lbl, wid) return grp_bx
def _setupUi(self): self._lb_desc = QLabel('<h3>Are you sure to Poweroff ' + self._device.dev + ' ' + self._device.idx + '?</h3>') self._pb_yes = PyDMPushButton(self, label='YES', pressValue=1, init_channel=self._mod_prefix + ':EMER_STOP') self._pb_yes.setObjectName('yes') self._pb_yes.setStyleSheet('#yes{background-color:red;}') self._pb_exit = QPushButton('EXIT', self) self._pb_exit.clicked.connect(self.close) lay = QGridLayout(self) lay.setHorizontalSpacing(20) lay.setVerticalSpacing(20) lay.addWidget(self._lb_desc, 0, 0, 1, 2) lay.addWidget(self._pb_yes, 1, 0, alignment=Qt.AlignCenter) lay.addWidget(self._pb_exit, 1, 1, alignment=Qt.AlignCenter)
def setupui(self): self.fl = QFormLayout(self) self.fl.setLabelAlignment(Qt.AlignVCenter) self._add_row('FFTData-RB.SPAN', 'Number of points') self._add_row('FFTData-RB.INDX', 'Start Index') self._add_row('FFTData-RB.MXIX', 'Maximum Index') self._add_row('FFTData-RB.WIND', 'Window type', enum=True) self._add_row('FFTData-RB.CDIR', 'Direction', enum=True) self._add_row('FFTData-RB.ASUB', 'Subtract Avg', enum=True) pb = PyDMPushButton(self, label='Calculate', pressValue=1) self._make_connections(pb, 'FFTData-RB.PROC') self.fl.addRow(pb)
class ModEmerStopDialog(SiriusDialog): """Modulator Emergency Stop Window.""" def __init__(self, parent=None, device='', prefix=VACA_PREFIX): """Init.""" super().__init__(parent) self.setObjectName('LIApp') self._prefix = prefix self._device = _PVName(device) self._mod_prefix = self._device.substitute(prefix=prefix) self.setWindowTitle(self._device.dev + ' ' + self._device.idx + ' - Emergency Stop') self._setupUi() def _setupUi(self): self._lb_desc = QLabel('<h3>Are you sure to Poweroff ' + self._device.dev + ' ' + self._device.idx + '?</h3>') self._pb_yes = PyDMPushButton(self, label='YES', pressValue=1, init_channel=self._mod_prefix + ':EMER_STOP') self._pb_yes.setObjectName('yes') self._pb_yes.setStyleSheet('#yes{background-color:red;}') self._pb_exit = QPushButton('EXIT', self) self._pb_exit.clicked.connect(self.close) lay = QGridLayout(self) lay.setHorizontalSpacing(20) lay.setVerticalSpacing(20) lay.addWidget(self._lb_desc, 0, 0, 1, 2) lay.addWidget(self._pb_yes, 1, 0, alignment=Qt.AlignCenter) lay.addWidget(self._pb_exit, 1, 1, alignment=Qt.AlignCenter)
def _setupStatusLayout(self): self.log = PyDMLogLabel( self, self.posang_prefix.substitute(propty='Log-Mon')) self.lb_sts0 = QLabel(Const.STATUSLABELS[0], self) self.led_sts0 = SiriusLedAlert( self, self.posang_prefix.substitute(propty='Status-Mon'), bit=0) self.lb_sts1 = QLabel(Const.STATUSLABELS[1], self) self.led_sts1 = SiriusLedAlert( self, self.posang_prefix.substitute(propty='Status-Mon'), bit=1) self.lb_sts2 = QLabel(Const.STATUSLABELS[2], self) self.led_sts2 = SiriusLedAlert( self, self.posang_prefix.substitute(propty='Status-Mon'), bit=2) self.lb_sts3 = QLabel(Const.STATUSLABELS[3], self) self.led_sts3 = SiriusLedAlert( self, self.posang_prefix.substitute(propty='Status-Mon'), bit=3) self.pb_config = PyDMPushButton( self, label='Config Correctors', pressValue=1, init_channel=self.posang_prefix.substitute(propty='ConfigPS-Cmd')) lay = QGridLayout() lay.setVerticalSpacing(12) lay.setHorizontalSpacing(12) lay.addWidget(self.log, 0, 0, 6, 1) lay.addWidget(self.lb_sts0, 1, 2) lay.addWidget(self.led_sts0, 1, 1) lay.addWidget(self.lb_sts1, 2, 2) lay.addWidget(self.led_sts1, 2, 1) lay.addWidget(self.lb_sts2, 3, 2) lay.addWidget(self.led_sts2, 3, 1) lay.addWidget(self.lb_sts3, 4, 2) lay.addWidget(self.led_sts3, 4, 1) lay.addWidget(self.pb_config, 5, 1, 1, 2) if self._tl == 'TS': self.led_corrtype = PyDMLedMultiChannel( self, {self.posang_prefix.substitute( propty='CH1-Cte'): self.corrs['CH1']}) self.lb_corrtype = QLabel( 'Control ' + ('CH-Sept' if self._is_chsept else 'Sept-Sept')) lay.addWidget(self.led_corrtype, 0, 1) lay.addWidget(self.lb_corrtype, 0, 2) return lay
def __init__(self, device: Device): super(FastCCDController, self).__init__(device) camera_layout = QVBoxLayout() camera_panel = QGroupBox('Camera State') camera_panel.setLayout(camera_layout) camera_layout.addWidget( PyDMLabel(init_channel=f'ca://{device.cam.state.pvname}')) camera_layout.addWidget( PyDMPushButton( pressValue=1, init_channel=f'ca://{device.cam.initialize.setpoint_pvname}', label='Initialize')) camera_layout.addWidget( PyDMPushButton( pressValue=1, init_channel=f'ca://{device.cam.shutdown.setpoint_pvname}', label='Shutdown')) dg_layout = QHBoxLayout() dg_panel = QGroupBox('Delay Gen State') dg_panel.setLayout(dg_layout) dg_state_layout = QVBoxLayout() dg_layout.addLayout(dg_state_layout) dg_state_layout.addWidget( PyDMLabel(init_channel=f'ca://{device.dg1.state.pvname}')) dg_state_layout.addWidget( PyDMPushButton( pressValue=1, init_channel=f'ca://{device.dg1.initialize.setpoint_pvname}', label='Initialize')) dg_state_layout.addWidget( PyDMPushButton( pressValue=1, init_channel=f'ca://{device.dg1.reset.setpoint_pvname}', label='Reset')) dg_shutter_layout = QVBoxLayout() dg_layout.addLayout(dg_shutter_layout) dg_shutter_layout.addWidget( PyDMLabel( init_channel=f'ca://{device.dg1.shutter_enabled.pvname}')) dg_shutter_layout.addWidget( PyDMPushButton( pressValue=0, init_channel= f'ca://{device.dg1.shutter_enabled.setpoint_pvname}', label='Enable Trigger')) dg_shutter_layout.addWidget( PyDMPushButton( pressValue=2, init_channel= f'ca://{device.dg1.shutter_enabled.setpoint_pvname}', label='Keep Closed')) dg_shutter_layout.addWidget( PyDMPushButton( pressValue=1, init_channel= f'ca://{device.dg1.shutter_enabled.setpoint_pvname}', label='Keep Open')) self.hlayout.addWidget(camera_panel) self.hlayout.addWidget(dg_panel) self.passive.setVisible( False) # active mode is useless for fastccd at COSMIC-Scattering # Subscribe to the error status PV so we can create notifications # (only relevant for cam init errors for now) self.device.cam.error_status.subscribe(self.report_error, 'value') # TODO: pull from settingsplugin self.db = Broker.named('local').v2 happi_settings = plugin_manager.get_plugin_by_name( "happi_devices", "SettingsPlugin") # Find coupled devices and add them so they'll be used with RE def from_device_container(container) -> Device: try: return from_container(container.device) except Exception as e: logError(e) return None self.async_poll_devices = list( map(from_device_container, happi_settings.search(source='labview'))) self.async_poll_devices += map( from_device_container, happi_settings.search(prefix=device.prefix)) # Remove errored from_container devices (Nones) self.async_poll_devices = list( filter(lambda device: device, self.async_poll_devices)) self.async_poll_devices.remove(device) self.metadata["projections"] = [{ 'name': 'NXsas', 'version': '0.1.0', 'projection': { NXsas.DATA_PROJECTION_KEY: { 'type': 'linked', 'stream': 'primary', 'location': 'event', 'field': f"{device.name}_image" }, NXsas.AZIMUTHAL_ANGLE_PROJECTION_KEY: { 'type': 'linked', 'stream': 'labview', 'location': 'event', 'field': 'detector_rotate' }, # TODO: source this from somewhere NXsas.ENERGY_PROJECTION_KEY: { 'type': 'linked', 'stream': 'labview', 'location': 'event', 'field': 'mono_energy' }, NXsas.INCIDENCE_ANGLE_PROJECTION_KEY: { 'type': 'linked', 'stream': 'labview', 'location': 'event', 'field': 'sample_rotate_steppertheta' }, # TODO: CHECK IF THIS EXISTS # FIXME: Is this the right motor??? NXsas.DETECTOR_TRANSLATION_X_PROJECTION_KEY: { 'type': 'linked', 'stream': 'labview', 'location': 'event', 'field': 'det_translate' }, }, 'configuration': { 'detector_name': 'fastccd', 'sdd': 0.5, 'geometry_mode': 'transmission', 'poni1': 480, 'poni2': 1025 } }]
class InjSysStbyControlWidget(QWidget): """Injection System Control Widget.""" expand = Signal() def __init__(self, parent=None, prefix=VACA_PREFIX, is_summary=False, handler=None): """Init.""" super().__init__(parent) self.prefix = prefix self._inj_prefix = SiriusPVName('AS-Glob:AP-InjCtrl').substitute( prefix=prefix) self._is_summary = is_summary self._last_comm = None self._handler = handler or InjSysStandbyHandler() self._icon_off = qta.icon('mdi.power-off') self._icon_on = qta.icon('mdi.power-on') self._icon_check = qta.icon('fa5s.check') self._pixmap_check = self._icon_check.pixmap( self._icon_check.actualSize(QSize(16, 16))) self._icon_not = qta.icon('fa5s.times') self._pixmap_not = self._icon_not.pixmap( self._icon_not.actualSize(QSize(16, 16))) self.menu = QMenu(self) self.rstord_act = self.menu.addAction('Reset Commands') self.rstord_act.triggered.connect(self._reset_commands_order) if is_summary: self._setupSummary() else: self._setupFull() self._ch_cmdsts = SiriusConnectionSignal( self._inj_prefix.substitute(propty='InjSysCmdSts-Mon')) self._ch_off_order_sp = SiriusConnectionSignal( self._inj_prefix.substitute(propty='InjSysTurnOffOrder-SP')) self._ch_off_order_rb = SiriusConnectionSignal( self._inj_prefix.substitute(propty='InjSysTurnOffOrder-RB')) self._ch_on_order_sp = SiriusConnectionSignal( self._inj_prefix.substitute(propty='InjSysTurnOnOrder-SP')) self._ch_on_order_rb = SiriusConnectionSignal( self._inj_prefix.substitute(propty='InjSysTurnOnOrder-RB')) if not is_summary: self._ch_cmdone = SiriusConnectionSignal( self._inj_prefix.substitute(propty='InjSysCmdDone-Mon')) self._ch_cmdsts.new_value_signal[int].connect( self._handle_cmdsts_buttons_enbl) self._ch_off_order_rb.new_value_signal[str].connect( self._handle_buttons_color) self._ch_on_order_rb.new_value_signal[str].connect( self._handle_buttons_color) self._ch_off_order_rb.new_value_signal[str].connect( self._handle_actions_state) self._ch_on_order_rb.new_value_signal[str].connect( self._handle_actions_state) if not is_summary: self._ch_cmdone.new_value_signal[str].connect( self._handle_cmdone_labels) self._ch_cmdsts.new_value_signal[int].connect( self._handle_cmdsts_labels) def _setupSummary(self): self._pb_off = PyDMPushButton(self, label='', icon=self._icon_off, init_channel=self._inj_prefix.substitute( propty='InjSysTurnOff-Cmd'), pressValue=0) self._pb_off.setObjectName('bt') self._pb_off.setStyleSheet( '#bt{min-width:25px; max-width:25px; icon-size:20px;}') self._pb_on = PyDMPushButton(self, label='', icon=self._icon_on, init_channel=self._inj_prefix.substitute( propty='InjSysTurnOn-Cmd'), pressValue=0) self._pb_on.setObjectName('bt') self._pb_on.setStyleSheet( '#bt{min-width:25px; max-width:25px; icon-size:20px;}') self._led_sts = InjSysStbyLed(self) self._led_sts.setStyleSheet( 'QLed{min-width:1.29em; max-width:1.29em;}') lay = QGridLayout(self) lay.setAlignment(Qt.AlignCenter) lay.addWidget(self._pb_off, 0, 0) lay.addWidget(self._pb_on, 0, 1) lay.addWidget(self._led_sts, 1, 0, 1, 2, alignment=Qt.AlignCenter) # menu for cmmtype in ['on', 'off']: order = getattr(self._handler, cmmtype + '_order') menu = QMenu('Select Turn ' + cmmtype.upper() + ' Commands', self) setattr(self, cmmtype + '_menu', menu) self.menu.addMenu(menu) for cmm in order: act = menu.addAction(self._handler.HANDLER_DESC[cmm]) act.setObjectName(cmm) act.setCheckable(True) def _setupFull(self): lay = QGridLayout(self) lay.addWidget(QLabel('Off', self, alignment=Qt.AlignCenter), 0, 1) lay.addWidget(QLabel('On', self, alignment=Qt.AlignCenter), 0, 2) lay.addWidget(QLabel('Status', self, alignment=Qt.AlignCenter), 0, 3) self._checkbox_off = dict() self._checkbox_on = dict() self._labels_sts = dict() for idx, name in enumerate(self._handler.DEF_ON_ORDER): cb_off = QCheckBox(self) cb_off.setObjectName(name) self._checkbox_off[name] = cb_off cb_on = QCheckBox(self) cb_on.setObjectName(name) self._checkbox_on[name] = cb_on desc = self._handler.HANDLER_DESC[name] splitd = desc.split('(') lbl_txt = splitd[0] tip = '' if len(splitd) > 1: lbl_txt, tip = splitd lb_dsc = QLabel(lbl_txt, self, alignment=Qt.AlignLeft) if tip: lb_dsc.setToolTip(tip[:-1]) lb_sts = QLabel('', self, alignment=Qt.AlignCenter) lb_sts.setObjectName(name) self._labels_sts[name] = lb_sts lay.addWidget(lb_dsc, idx + 1, 0) lay.addWidget(cb_off, idx + 1, 1, alignment=Qt.AlignCenter) lay.addWidget(cb_on, idx + 1, 2, alignment=Qt.AlignCenter) lay.addWidget(lb_sts, idx + 1, 3) self._pb_off = PyDMPushButton(self, label='', icon=self._icon_off, init_channel=self._inj_prefix.substitute( propty='InjSysTurnOff-Cmd'), pressValue=0) self._pb_off.setObjectName('bt') self._pb_off.setStyleSheet( '#bt{min-width:25px; max-width:25px; icon-size:20px;}') self._pb_on = PyDMPushButton(self, label='', icon=self._icon_on, init_channel=self._inj_prefix.substitute( propty='InjSysTurnOn-Cmd'), pressValue=0) self._pb_on.setObjectName('bt') self._pb_on.setStyleSheet( '#bt{min-width:25px; max-width:25px; icon-size:20px;}') self._led_sts = InjSysStbyLed(self) lay.addWidget(self._pb_off, 6, 1) lay.addWidget(self._pb_on, 6, 2) lay.addWidget(self._led_sts, 6, 3) @Slot(int) def _handle_cmdsts_buttons_enbl(self, new_sts): if new_sts == _Const.InjSysCmdSts.On: self._pb_on.setEnabled(False) self._pb_on.setIcon( qta.icon('fa5s.spinner', animation=qta.Spin(self._pb_on))) self._pb_off.setEnabled(False) elif new_sts == _Const.InjSysCmdSts.Off: self._pb_on.setEnabled(False) self._pb_off.setEnabled(False) self._pb_off.setIcon( qta.icon('fa5s.spinner', animation=qta.Spin(self._pb_off))) else: if not self._pb_on.isEnabled(): self._pb_on.setEnabled(True) self._pb_off.setEnabled(True) self._pb_on.setIcon(self._icon_on) self._pb_off.setIcon(self._icon_off) @Slot(str) def _handle_cmdone_labels(self, new_done): for name in self._handler.DEF_ON_ORDER: lbl = self._labels_sts[name] if name in new_done: lbl.setPixmap(self._pixmap_check) elif self._ch_cmdsts.value == _Const.InjSysCmdSts.Idle: lbl.setPixmap(self._pixmap_not) @Slot(int) def _handle_cmdsts_labels(self, new_sts): if new_sts == _Const.InjSysCmdSts.On: self._last_comm = new_sts for name in self._handler.DEF_ON_ORDER: if self._ch_on_order_rb.value is None: break lbl = self._labels_sts[name] if name in self._ch_on_order_rb.value: icon = qta.icon('fa5s.spinner') pixmap = icon.pixmap(icon.actualSize(QSize(16, 16))) lbl.setPixmap(pixmap) else: lbl.setPixmap(QPixmap()) elif new_sts == _Const.InjSysCmdSts.Off: self._last_comm = new_sts for name in self._handler.DEF_OFF_ORDER: if self._ch_off_order_rb.value is None: break lbl = self._labels_sts[name] if name in self._ch_off_order_rb.value: icon = qta.icon('fa5s.spinner') pixmap = icon.pixmap(icon.actualSize(QSize(16, 16))) lbl.setPixmap(pixmap) else: lbl.setPixmap(QPixmap()) else: done = self._ch_cmdone.value for name in self._handler.DEF_ON_ORDER: if done is None or name in done: continue lbl = self._labels_sts[name] if self._last_comm == _Const.InjSysCmdSts.On and \ name in self._ch_on_order_rb.value: lbl.setPixmap(self._pixmap_not) elif self._last_comm == _Const.InjSysCmdSts.Off and \ name in self._ch_off_order_rb.value: lbl.setPixmap(self._pixmap_not) self._last_comm = None @Slot() def _set_commands_order(self): if self._is_summary: if self.sender() in self.on_menu.actions(): on_order = [ a.objectName() for a in self.on_menu.actions() if a.isChecked() ] self._ch_on_order_sp.send_value_signal[str].emit( ','.join(on_order)) elif self.sender() in self.off_menu.actions(): off_order = [ a.objectName() for a in self.off_menu.actions() if a.isChecked() ] self._ch_off_order_sp.send_value_signal[str].emit( ','.join(off_order)) else: if self.sender() in self._checkbox_on.values(): checked = [ w.objectName() for w in self._checkbox_on.values() if w.isChecked() ] on_order = [ h for h in self._handler.DEF_ON_ORDER if h in checked ] self._ch_on_order_sp.send_value_signal[str].emit( ','.join(on_order)) elif self.sender() in self._checkbox_off.values(): checked = [ w.objectName() for w in self._checkbox_off.values() if w.isChecked() ] off_order = [ h for h in self._handler.DEF_OFF_ORDER if h in checked ] self._ch_off_order_sp.send_value_signal[str].emit( ','.join(off_order)) @Slot() def _reset_commands_order(self): self._ch_off_order_sp.send_value_signal[str].emit(','.join( self._handler.DEF_OFF_ORDER)) self._ch_on_order_sp.send_value_signal[str].emit(','.join( self._handler.DEF_ON_ORDER)) if self._is_summary: for menu in [self.off_menu, self.on_menu]: for act in menu.actions(): act.toggled.disconnect() act.setChecked(True) act.toggled.connect(self._set_commands_order) else: for group in [self._checkbox_off, self._checkbox_on]: for wid in group.values(): wid.toggled.disconnect() wid.setChecked(True) wid.toggled.connect(self._set_commands_order) @Slot() def _handle_buttons_color(self): off_color = 'yellow' if self._ch_off_order_rb.value != \ ','.join(self._handler.DEF_OFF_ORDER) else 'white' self._pb_off.setStyleSheet( '#bt{min-width:25px; max-width:25px; icon-size:20px;' 'background-color: ' + off_color + ';}') on_color = 'yellow' if self._ch_on_order_rb.value != \ ','.join(self._handler.DEF_ON_ORDER) else 'white' self._pb_on.setStyleSheet( '#bt{min-width:25px; max-width:25px; icon-size:20px;' 'background-color: ' + on_color + ';}') @Slot(str) def _handle_actions_state(self, sts): state = 'on' if 'On' in self.sender().address else 'off' channel = getattr(self, '_ch_' + state + '_order_rb') if channel.value is None: return if self._is_summary: group = getattr(self, state + '_menu').actions() else: group = getattr(self, '_checkbox_' + state).values() for obj in group: obj.disconnect() ost = obj.objectName() in sts obj.setChecked(ost) obj.toggled.connect(self._set_commands_order) def contextMenuEvent(self, event): """Show a custom context menu.""" self.menu.popup(self.mapToGlobal(event.pos()))
def _setupLifetimeSettigsWidget(self): self._ld_calcmode = QLabel('Calc Mode:', self, alignment=Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._cb_calcmode = PyDMEnumComboBox( self, self.devname.substitute(propty='LtFitMode-Sel')) self._lb_calcmode = SiriusLabel( self, self.devname.substitute(propty='LtFitMode-Sts')) self._lb_calcmode.setAlignment(Qt.AlignCenter) self._ld_curroffset = QLabel('Current\nOffset [mA]:', self, alignment=Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._sb_curroffset = SiriusSpinbox( self, self.devname.substitute(propty='CurrOffset-SP')) self._sb_curroffset.showStepExponent = False self._lb_curroffset = PyDMLabel( self, self.devname.substitute(propty='CurrOffset-RB')) self._lb_curroffset.setAlignment(Qt.AlignCenter) self._ld_buffer = QLabel('<h4>Buffer</h4>', self, alignment=Qt.AlignCenter) self._pb_plussett = QPushButton('+', self) self._pb_plussett.setStyleSheet('max-height:0.9em; max-width:0.9em;') self._pb_plussett.released.connect(self._handle_intvl_sett_visibility) self._ld_maxintvl = QLabel('Max. Sampling\nInterval [s]:', self, alignment=Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._ld_maxintvl.setToolTip( "Timestamp settings use 2 parameters to define the\n" "timestamp interval.\n\n" "If 'Max. Sampling Interval' == -1:\n" " use 'Last Time' and 'First Time' parameters.\n" "Else:\n" " use 'Max. Sampling Interval' and last timestamp set.\n\n" "Default: use 'Max. Sampling Interval' and 'Last Time'.") hlay_maxintvl = QHBoxLayout() hlay_maxintvl.addWidget(self._pb_plussett) hlay_maxintvl.addWidget(self._ld_maxintvl) self._sb_maxintvl = PyDMSpinbox( self, self.devname.substitute(propty='MaxSplIntvl-SP')) self._sb_maxintvl.precisionFromPV = True self._sb_maxintvl.showStepExponent = False self._lb_maxintvl = PyDMLabel( self, self.devname.substitute(propty='MaxSplIntvl-RB')) self._lb_maxintvl.setAlignment(Qt.AlignCenter) self._lb_maxintvl.precisionFromPV = True self._ld_firstsmpl = QLabel('First Time [s]:', self, alignment=Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._ld_firstsmpl.setVisible(False) self._le_firstsmpl = PyDMLineEdit( self, self.devname.substitute(propty='FrstSplTime-SP')) self._le_firstsmpl.setVisible(False) self._lb_firstsmpl_dcct = PyDMLabel( self, self.devname.substitute(propty='FrstSplTime-RB')) self._lb_firstsmpl_dcct.setVisible(False) self._lb_firstsmpl_bpm = PyDMLabel( self, self.devname.substitute(propty='FrstSplTimeBPM-RB')) self._lb_firstsmpl_bpm.setVisible(False) self._pb_firstnow = QPushButton(qta.icon('mdi.clock-end'), '', self) self._pb_firstnow.setObjectName('firstnow') self._pb_firstnow.setStyleSheet( '#firstnow{min-width:25px; max-width:25px; icon-size:20px;}') self._pb_firstnow.setToolTip('Click to set current timestamp') self._pb_firstnow.released.connect(self._update_first_time) self._pb_firstnow.setVisible(False) hbox_sp_first = QHBoxLayout() hbox_sp_first.addWidget(self._le_firstsmpl) hbox_sp_first.addWidget(self._pb_firstnow) self._ld_lastsmpl = QLabel('Last Time [s]:', self, alignment=Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._ld_lastsmpl.setToolTip( "If 'Last Time' == -1, use current timestamp.") self._ld_lastsmpl.setVisible(False) self._le_lastsmpl = PyDMLineEdit( self, self.devname.substitute(propty='LastSplTime-SP')) self._le_lastsmpl.setVisible(False) self._lb_lastsmpl_dcct = PyDMLabel( self, self.devname.substitute(propty='LastSplTime-RB')) self._lb_lastsmpl_dcct.setVisible(False) self._lb_lastsmpl_bpm = PyDMLabel( self, self.devname.substitute(propty='LastSplTimeBPM-RB')) self._lb_lastsmpl_bpm.setVisible(False) self._pb_lastnow = QPushButton(qta.icon('mdi.clock-end'), '', self) self._pb_lastnow.setObjectName('lastnow') self._pb_lastnow.setStyleSheet( '#lastnow{min-width:25px; max-width:25px; icon-size:20px;}') self._pb_lastnow.setToolTip('Click to set current timestamp') self._pb_lastnow.released.connect(self._update_last_time) self._pb_lastnow.setVisible(False) hbox_sp_last = QHBoxLayout() hbox_sp_last.addWidget(self._le_lastsmpl) hbox_sp_last.addWidget(self._pb_lastnow) self._ld_smplintvl = QLabel('Samples\nInterval [s]:', self, alignment=Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._lb_smplintvl_dcct = PyDMLabel( self, self.devname.substitute(propty='SplIntvl-Mon')) self._lb_smplintvl_bpm = PyDMLabel( self, self.devname.substitute(propty='SplIntvlBPM-Mon')) self._lb_smplintvl_bpm.setVisible(False) self._ld_intvlbtwspl = QLabel('Interval Between\nSamples [s]:', self, alignment=Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._sb_intvlbtwspl = PyDMSpinbox( self, self.devname.substitute(propty='MinIntvlBtwSpl-SP')) self._sb_intvlbtwspl.precisionFromPV = True self._sb_intvlbtwspl.showStepExponent = False self._lb_intvlbtwspl = PyDMLabel( self, self.devname.substitute(propty='MinIntvlBtwSpl-RB')) self._lb_intvlbtwspl.setAlignment(Qt.AlignCenter) self._lb_intvlbtwspl.precisionFromPV = True self._ld_bufautoreset = QLabel('Auto Reset:', self, alignment=Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._cb_bufautoreset = PyDMEnumComboBox( self, self.devname.substitute(propty='BuffAutoRst-Sel')) self._lb_bufautoreset = PyDMLabel( self, self.devname.substitute(propty='BuffAutoRst-Sts')) self._ld_bufdcurr = QLabel('Auto Reset Delta\nCurrent [mA]:', self, alignment=Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._sb_bufdcurr = PyDMSpinbox( self, self.devname.substitute(propty='BuffAutoRstDCurr-SP')) self._sb_bufdcurr.showStepExponent = False self._lb_bufdcurr = PyDMLabel( self, self.devname.substitute(propty='BuffAutoRstDCurr-RB')) self._ld_bufsize = QLabel('Size:', self, alignment=Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._lb_bufsize_dcct = PyDMLabel( self, self.devname.substitute(propty='BuffSize-Mon')) self._lb_bufsize_dcct.setAlignment(Qt.AlignCenter) self._lb_bufsize_bpm = PyDMLabel( self, self.devname.substitute(propty='BuffSizeBPM-Mon')) self._lb_bufsize_bpm.setAlignment(Qt.AlignCenter) self._lb_bufsize_bpm.setVisible(False) self._pb_bufreset = PyDMPushButton( self, label='', icon=qta.icon('mdi.delete-empty'), pressValue=1, init_channel=self.devname.substitute(propty='BuffRst-Cmd')) self._pb_bufreset.setObjectName('reset') self._pb_bufreset.setStyleSheet( "#reset{min-width:25px; max-width:25px; icon-size:20px;}") self._ld_sep = QLabel('/', self) self._lb_bufsizetot_dcct = PyDMLabel( self, self.devname.substitute(propty='BuffSizeTot-Mon')) self._lb_bufsizetot_dcct.setStyleSheet("min-width:5em; max-width:5em;") self._lb_bufsizetot_dcct.setAlignment(Qt.AlignCenter) self._lb_bufsizetot_dcct.precision = 0 self._lb_bufsizetot_bpm = PyDMLabel( self, self.devname.substitute(propty='BuffSizeTotBPM-Mon')) self._lb_bufsizetot_bpm.setStyleSheet("min-width:5em; max-width:5em;") self._lb_bufsizetot_bpm.setAlignment(Qt.AlignCenter) self._lb_bufsizetot_bpm.precision = 0 self._lb_bufsizetot_bpm.setVisible(False) glay_bufsize = QGridLayout() glay_bufsize.addWidget(self._lb_bufsize_dcct, 0, 0) glay_bufsize.addWidget(self._lb_bufsize_bpm, 0, 0) glay_bufsize.addWidget(self._pb_bufreset, 0, 1) glay_bufsize.addWidget(self._ld_sep, 0, 2) glay_bufsize.addWidget(self._lb_bufsizetot_dcct, 0, 3) glay_bufsize.addWidget(self._lb_bufsizetot_bpm, 0, 3) glay_bufsize.setColumnStretch(0, 5) glay_bufsize.setColumnStretch(1, 2) glay_bufsize.setColumnStretch(2, 1) glay_bufsize.setColumnStretch(3, 5) gbox = QGroupBox('Lifetime Settings', self) lay = QGridLayout(gbox) lay.addWidget(self._ld_calcmode, 0, 0) lay.addWidget(self._cb_calcmode, 0, 1) lay.addWidget(self._lb_calcmode, 0, 2) lay.addWidget(self._ld_curroffset, 1, 0) lay.addWidget(self._sb_curroffset, 1, 1) lay.addWidget(self._lb_curroffset, 1, 2) lay.addItem(QSpacerItem(1, 1, QSzPlcy.Expanding, QSzPlcy.Minimum), 2, 1) lay.addWidget(self._ld_buffer, 3, 0, 1, 3) lay.addLayout(hlay_maxintvl, 4, 0) lay.addWidget(self._sb_maxintvl, 4, 1) lay.addWidget(self._lb_maxintvl, 4, 2) lay.addWidget(self._ld_firstsmpl, 5, 0) lay.addLayout(hbox_sp_first, 5, 1, 1, 2) lay.addWidget(self._lb_firstsmpl_dcct, 6, 1, 1, 2) lay.addWidget(self._lb_firstsmpl_bpm, 6, 1, 1, 2) lay.addWidget(self._ld_lastsmpl, 7, 0) lay.addLayout(hbox_sp_last, 7, 1, 1, 2) lay.addWidget(self._lb_lastsmpl_dcct, 8, 1, 1, 2) lay.addWidget(self._lb_lastsmpl_bpm, 8, 1, 1, 2) lay.addWidget(self._ld_smplintvl, 9, 0) lay.addWidget(self._lb_smplintvl_dcct, 9, 1) lay.addWidget(self._lb_smplintvl_bpm, 9, 1) lay.addWidget(self._ld_intvlbtwspl, 10, 0) lay.addWidget(self._sb_intvlbtwspl, 10, 1) lay.addWidget(self._lb_intvlbtwspl, 10, 2) lay.addItem(QSpacerItem(20, 5, QSzPlcy.Minimum, QSzPlcy.Fixed), 11, 1) lay.addWidget(self._ld_bufautoreset, 12, 0) lay.addWidget(self._cb_bufautoreset, 12, 1) lay.addWidget(self._lb_bufautoreset, 12, 2) lay.addWidget(self._ld_bufdcurr, 13, 0) lay.addWidget(self._sb_bufdcurr, 13, 1) lay.addWidget(self._lb_bufdcurr, 13, 2) lay.addItem(QSpacerItem(20, 5, QSzPlcy.Minimum, QSzPlcy.Fixed), 14, 1) lay.addWidget(self._ld_bufsize, 15, 0) lay.addLayout(glay_bufsize, 15, 1, 1, 2) return gbox
def setglobalparameters(self): wid = QWidget(self.centralWidget()) wid.setSizePolicy(QSzPol.Preferred, QSzPol.Maximum) lay = QGridLayout(wid) evg_dev = SiriusPVName(LLTimeSearch.get_evg_name()) evg_pref = evg_dev.substitute(prefix=self.prefix) sp = PyDMPushButton( self, init_channel=evg_pref.substitute(propty='UpdateEvt-Cmd'), pressValue=1) sp.setIcon(qta.icon('fa5s.sync')) sp.setToolTip('Update Events Table') sp.setObjectName('but') sp.setStyleSheet( '#but{min-width:25px; max-width:25px; icon-size:20px;}') rb = PyDMLed( self, init_channel=evg_pref.substitute(propty='EvtSyncStatus-Mon')) rb.setOffColor(rb.Red) rb.setOnColor(rb.LightGreen) lay.addWidget( self._create_prop_widget('<h4>Update Evts</h4>', wid, (sp, rb)), 0, 0) sp = PyDMStateButton( self, init_channel=evg_pref.substitute(propty='ContinuousEvt-Sel')) rb = PyDMLed( self, init_channel=evg_pref.substitute(propty='ContinuousEvt-Sts')) lay.addWidget( self._create_prop_widget('<h4>Continuous</h4>', wid, (sp, rb)), 0, 1) sp = PyDMStateButton( self, init_channel=evg_pref.substitute(propty='InjectionEvt-Sel')) rb = PyDMLed( self, init_channel=evg_pref.substitute(propty='InjectionEvt-Sts')) lay.addWidget( self._create_prop_widget('<h4>Injection</h4>', wid, (sp, rb)), 0, 2) bucketlist_wid = BucketList(self.centralWidget(), evg_dev, self.prefix) bucketlist_wid.setSizePolicy(QSzPol.MinimumExpanding, QSzPol.Preferred) lay.addWidget(bucketlist_wid, 0, 3, 2, 1) hlay = QHBoxLayout() lab = QLabel('Inj Count:', wid) pydmlab = PyDMLabel( wid, init_channel=evg_pref.substitute(propty='InjCount-Mon')) pydmlab.setStyleSheet('min-width:5em;') pydmlab.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) hlay.addStretch() hlay.addWidget(lab) hlay.addWidget(pydmlab) hlay.addStretch() pydmlab = PyDMLabel( wid, init_channel=evg_pref.substitute(propty='STATEMACHINE')) pydmlab.setStyleSheet('min-width:10em;') hlay.addWidget(pydmlab) hlay.addStretch() pydmlab = PyDMLabel( wid, init_channel=evg_pref.substitute(propty='SeqCount-SP')) pydmlab.rules =\ '[{"name": "VisibleRule", "property": "Visible", ' +\ '"expression": "ch[0]==5", "channels": [{"channel": "' +\ evg_pref.substitute(propty_name='STATEMACHINE') +\ '", "trigger": true}]}]' pydmlab.setStyleSheet('min-width:3em;') hlay.addWidget(pydmlab) hlay.addStretch() lay.addItem(hlay, 1, 0, 1, 3) return wid
class CurrLTWindow(SiriusMainWindow): """Current and Lifetime Window.""" def __init__(self, parent=None, prefix=_VACA_PREFIX): """Initialize some widgets.""" super(CurrLTWindow, self).__init__(parent) self.prefix = prefix self.device = _PVName('SI-Glob:AP-CurrInfo') self.devname = self.device.substitute(prefix=self.prefix) self.setObjectName('SIApp') self.setWindowTitle('SI Current Info: Current and Lifetime') self._setupUi() self.setFocus(True) self.setFocusPolicy(Qt.StrongFocus) def _setupUi(self): self.label_title = QLabel('SI Current and Lifetime') self.label_title.setStyleSheet(""" font-size:1.2em; font-weight:bold; 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.label_title.setAlignment(Qt.AlignRight | Qt.AlignVCenter) self.settings = QWidget() vlay_sett = QVBoxLayout(self.settings) vlay_sett.setContentsMargins(0, 0, 0, 0) vlay_sett.addWidget(self._setupCurrentSettingsWidget()) vlay_sett.addWidget(self._setupLifetimeSettigsWidget()) vlay_sett.addWidget(self._setupGraphSettingsWidget()) self.pb_showsett = QPushButton('<', self) self.pb_showsett.setObjectName('showsett') self.pb_showsett.setToolTip('Hide settings') self.pb_showsett.setStyleSheet( '#showsett{min-width:0.7em;max-width:0.7em;}') self.pb_showsett.released.connect(self._handle_settings_vis) self.pb_showeff = QPushButton('v', self) self.pb_showeff.setObjectName('showeff') self.pb_showeff.setToolTip('Show efficiency graph') self.pb_showeff.setStyleSheet( '#showeff{min-width:0.7em;max-width:0.7em;}') self.pb_showeff.released.connect(self._handle_efficiency_vis) hbox_visi = QHBoxLayout() hbox_visi.addStretch() hbox_visi.addWidget(self.pb_showsett) hbox_visi.addWidget(self.pb_showeff) self.eff_graph = EffMonitor(self, self.prefix, self.device.sec) self.eff_graph.setVisible(False) cw = QWidget() self.setCentralWidget(cw) lay = QGridLayout(cw) lay.addWidget(self.label_title, 0, 0, 1, 2) lay.addLayout(self._setupGraphPanelLayout(), 1, 0) lay.addWidget(self.settings, 1, 1) lay.addLayout(hbox_visi, 2, 0, 1, 2, alignment=Qt.AlignRight) lay.addWidget(self.eff_graph, 3, 0, 1, 2) lay.setColumnStretch(0, 6) lay.setColumnStretch(1, 1) def _setupGraphPanelLayout(self): # Main Panel # # Labels self._ld_current = QLabel('Current', self, alignment=Qt.AlignCenter) self._ld_current.setStyleSheet("font-weight:bold; max-height1.5em;") self._lb_current = PyDMLabel( self, self.devname.substitute(propty='Current-Mon')) self._lb_current.setStyleSheet("font-size:40px;") self._lb_current.precision = 0 self._lb_current.showUnits = True self._ld_lifetime = QLabel('Lifetime', self) self._ld_lifetime.setStyleSheet("font-weight:bold; max-height1.5em;") self._ld_lifetime.setAlignment(Qt.AlignCenter) self._lb_lifetime = QLabel('0:00:00', self) self._lb_lifetime.channel = self.devname.substitute( propty='Lifetime-Mon') self._lb_lifetime.setStyleSheet("font-size:40px;") self.lifetime_dcct_pv = SiriusConnectionSignal( self.devname.substitute(propty='Lifetime-Mon')) self.lifetime_dcct_pv.new_value_signal[float].connect( self._format_lifetime_label) self.lifetime_bpm_pv = SiriusConnectionSignal( self.devname.substitute(propty='LifetimeBPM-Mon')) self.lifetime_bpm_pv.new_value_signal[float].connect( self._format_lifetime_label) # # Graph self.graph = SiriusTimePlot(self, background='w') self.graph.plotItem.getAxis('left').setLabel('Current [mA]', color='blue') self.graph.plotItem.getAxis('right').setLabel('Lifetime [h]', color='red') self.graph.showLegend = False self.graph.showXGrid = True self.graph.showYGrid = True self.graph.autoRangeY = True self.graph.setObjectName('graph') self.graph.setStyleSheet('#graph{min-width:40em;min-height:32em;}') self.graph.bufferSize = 60 * 60 * 10 self.graph.timeSpan = 30 * 60 t_end = Time.now() t_init = t_end - 30 * 60 t_end_iso = t_end.get_iso8601() t_init_iso = t_init.get_iso8601() pvname = self.devname.substitute(propty='Current-Mon') self.graph.addYChannel(y_channel=pvname, axis='left', name='Current', color='blue', lineWidth=1) self._curve_current = self.graph.curveAtIndex(0) self.graph.fill_curve_with_archdata(self._curve_current, pvname, t_init=t_init_iso, t_end=t_end_iso) pvname = _PVName('SI-01M1:DI-BPM:Sum-Mon').substitute( prefix=self.prefix) self.graph.addYChannel(y_channel=pvname, axis='left', name='Current', color='blue', lineWidth=1) self._curve_bpmsum = self.graph.curveAtIndex(1) self.graph.fill_curve_with_archdata(self._curve_bpmsum, pvname, t_init=t_init_iso, t_end=t_end_iso) self.graph.addYChannel(y_channel='FAKE:Lifetime', axis='right', name='Lifetime', color='red', lineWidth=1) self._curve_lifetimedcct = self.graph.curveAtIndex(2) self.graph.fill_curve_with_archdata( self._curve_lifetimedcct, self.devname.substitute(propty='Lifetime-Mon'), t_init=t_init_iso, t_end=t_end_iso, factor=3600) self.graph.addYChannel(y_channel='FAKE:LifetimeBPM', axis='right', name='Lifetime', color='red', lineWidth=1) self._curve_lifetimebpm = self.graph.curveAtIndex(3) self.graph.fill_curve_with_archdata( self._curve_lifetimebpm, self.devname.substitute(propty='LifetimeBPM-Mon'), t_init=t_init_iso, t_end=t_end_iso, factor=3600) self.lifetime_dcct_pv.new_value_signal[float].connect( self._update_graph) self.lifetime_bpm_pv.new_value_signal[float].connect( self._update_graph) self._flag_need_dcctx = True self._flag_need_dccty = True self._flag_need_bpmx = True self._flag_need_bpmy = True self.dcct_wavx = _np.array([]) self.dcct_wavy = _np.array([]) self.bpm_wavx = _np.array([]) self.bpm_wavy = _np.array([]) self.dcct_buff_y_pv = SiriusConnectionSignal( self.devname.substitute(propty='BufferValue-Mon')) self.dcct_buff_x_pv = SiriusConnectionSignal( self.devname.substitute(propty='BufferTimestamp-Mon')) self.bpm_buff_y_pv = SiriusConnectionSignal( self.devname.substitute(propty='BufferValueBPM-Mon')) self.bpm_buff_x_pv = SiriusConnectionSignal( self.devname.substitute(propty='BufferTimestampBPM-Mon')) self.dcct_buff_y_pv.new_value_signal[_np.ndarray].connect( self._update_waveforms) self.dcct_buff_x_pv.new_value_signal[_np.ndarray].connect( self._update_waveforms) self.bpm_buff_y_pv.new_value_signal[_np.ndarray].connect( self._update_waveforms) self.bpm_buff_x_pv.new_value_signal[_np.ndarray].connect( self._update_waveforms) self.graph.addYChannel(y_channel='FAKE:DCCTBuffer', axis='left', name='DCCTBuffer', color='blue', lineStyle=Qt.NoPen, symbolSize=10, symbol='o') self._curve_dcct_buff = self.graph.curveAtIndex(4) self.graph.addYChannel(y_channel='FAKE:BPMBuffer', axis='left', name='BPMBuffer', color='blue', lineStyle=Qt.NoPen, symbolSize=10, symbol='o') self._curve_bpm_buff = self.graph.curveAtIndex(5) self._curve_bpmsum.setVisible(False) self._curve_lifetimebpm.setVisible(False) self._curve_bpm_buff.setVisible(False) lay = QGridLayout() lay.addItem(QSpacerItem(1, 1, QSzPlcy.Expanding, QSzPlcy.Minimum), 0, 0) lay.addWidget(self._ld_current, 0, 1) lay.addItem(QSpacerItem(1, 1, QSzPlcy.Expanding, QSzPlcy.Minimum), 0, 2) lay.addItem(QSpacerItem(1, 1, QSzPlcy.Expanding, QSzPlcy.Minimum), 0, 3) lay.addWidget(self._ld_lifetime, 0, 4) lay.addItem(QSpacerItem(1, 1, QSzPlcy.Expanding, QSzPlcy.Minimum), 0, 5) lay.addWidget(self._lb_current, 1, 1) lay.addWidget(self._lb_lifetime, 1, 4) lay.addWidget(self.graph, 2, 0, 1, 6) return lay def _setupCurrentSettingsWidget(self): self._ld_storedebeam = QLabel('Stored EBeam?', self) self._ld_storedebeam.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._led_storedebeam = SiriusLedState( self, self.devname.substitute(propty='StoredEBeam-Mon')) self._ld_dcctfault = QLabel('DCCT Fault Check:', self) self._ld_dcctfault.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._bt_dcctfault = PyDMStateButton( self, self.devname.substitute(propty='DCCTFltCheck-Sel')) self._bt_dcctfault.shape = PyDMStateButton.Rounded self._led_dcctfault = SiriusLedState( self, self.devname.substitute(propty='DCCTFltCheck-Sts')) self._ld_seldcct = QLabel('Select DCCT:', self) self._ld_seldcct.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._cb_seldcct = PyDMEnumComboBox( self, self.devname.substitute(propty='DCCT-Sel')) self._lb_seldcct = PyDMLabel( self, self.devname.substitute(propty='DCCT-Sts')) self._lb_seldcct.setAlignment(Qt.AlignCenter) self._lb_seldcct.precision = 0 self._led_dcct13c4 = SiriusLedAlert( self, _PVName('SI-13C4:DI-DCCT:ReliableMeas-Mon').substitute( prefix=self.prefix)) self._lb_dcct13c4 = QLabel('DCCT 13C4', self) self._lb_dcct13c4.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._pb_13c4_detail = QPushButton(self) self._pb_13c4_detail.setObjectName('DCCT13C4_dtl') self._pb_13c4_detail.setStyleSheet( "#DCCT13C4_dtl{min-width:25px; max-width:25px; icon-size:20px;}") self._pb_13c4_detail.setIcon(qta.icon('fa5s.ellipsis-h')) connect_window(self._pb_13c4_detail, DCCTMain, self, prefix=self.prefix, device='SI-13C4:DI-DCCT') hlay_dcct13c4 = QHBoxLayout() hlay_dcct13c4.addItem( QSpacerItem(1, 1, QSzPlcy.Expanding, QSzPlcy.Minimum)) hlay_dcct13c4.addWidget(self._led_dcct13c4) hlay_dcct13c4.addWidget(self._lb_dcct13c4) hlay_dcct13c4.addItem( QSpacerItem(1, 1, QSzPlcy.Expanding, QSzPlcy.Minimum)) hlay_dcct13c4.addWidget(self._pb_13c4_detail) hlay_dcct13c4.addItem( QSpacerItem(1, 1, QSzPlcy.Expanding, QSzPlcy.Minimum)) self._led_dcct14c4 = SiriusLedAlert( self, _PVName('SI-14C4:DI-DCCT:ReliableMeas-Mon').substitute( prefix=self.prefix)) self._lb_dcct14c4 = QLabel('DCCT 14C4', self) self._lb_dcct14c4.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._pb_14c4_detail = QPushButton(self) self._pb_14c4_detail.setObjectName('DCCT14C4_dtl') self._pb_14c4_detail.setStyleSheet( "#DCCT14C4_dtl{min-width:25px; max-width:25px; icon-size:20px;}") self._pb_14c4_detail.setIcon(qta.icon('fa5s.ellipsis-h')) connect_window(self._pb_14c4_detail, DCCTMain, self, prefix=self.prefix, device='SI-14C4:DI-DCCT') hlay_dcct14c4 = QHBoxLayout() hlay_dcct14c4.addItem( QSpacerItem(1, 1, QSzPlcy.Expanding, QSzPlcy.Minimum)) hlay_dcct14c4.addWidget(self._led_dcct14c4) hlay_dcct14c4.addWidget(self._lb_dcct14c4) hlay_dcct14c4.addItem( QSpacerItem(1, 1, QSzPlcy.Expanding, QSzPlcy.Minimum)) hlay_dcct14c4.addWidget(self._pb_14c4_detail) hlay_dcct14c4.addItem( QSpacerItem(1, 1, QSzPlcy.Expanding, QSzPlcy.Minimum)) gbox = QGroupBox('Current Settings and Status', self) lay = QGridLayout(gbox) lay.addWidget(self._ld_storedebeam, 0, 0) lay.addWidget(self._led_storedebeam, 0, 1) lay.addWidget(self._ld_dcctfault, 1, 0) lay.addWidget(self._bt_dcctfault, 1, 1) lay.addWidget(self._led_dcctfault, 1, 2) lay.addWidget(self._ld_seldcct, 2, 0) lay.addWidget(self._cb_seldcct, 2, 1) lay.addWidget(self._lb_seldcct, 2, 2) lay.addItem(QSpacerItem(1, 1, QSzPlcy.Expanding, QSzPlcy.Minimum), 3, 0) lay.addLayout(hlay_dcct13c4, 4, 0, 1, 3) lay.addLayout(hlay_dcct14c4, 5, 0, 1, 3) lay.setColumnStretch(0, 2) lay.setColumnStretch(1, 1) lay.setColumnStretch(2, 1) return gbox def _setupLifetimeSettigsWidget(self): self._ld_calcmode = QLabel('Calc Mode:', self, alignment=Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._cb_calcmode = PyDMEnumComboBox( self, self.devname.substitute(propty='LtFitMode-Sel')) self._lb_calcmode = SiriusLabel( self, self.devname.substitute(propty='LtFitMode-Sts')) self._lb_calcmode.setAlignment(Qt.AlignCenter) self._ld_curroffset = QLabel('Current\nOffset [mA]:', self, alignment=Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._sb_curroffset = SiriusSpinbox( self, self.devname.substitute(propty='CurrOffset-SP')) self._sb_curroffset.showStepExponent = False self._lb_curroffset = PyDMLabel( self, self.devname.substitute(propty='CurrOffset-RB')) self._lb_curroffset.setAlignment(Qt.AlignCenter) self._ld_buffer = QLabel('<h4>Buffer</h4>', self, alignment=Qt.AlignCenter) self._pb_plussett = QPushButton('+', self) self._pb_plussett.setStyleSheet('max-height:0.9em; max-width:0.9em;') self._pb_plussett.released.connect(self._handle_intvl_sett_visibility) self._ld_maxintvl = QLabel('Max. Sampling\nInterval [s]:', self, alignment=Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._ld_maxintvl.setToolTip( "Timestamp settings use 2 parameters to define the\n" "timestamp interval.\n\n" "If 'Max. Sampling Interval' == -1:\n" " use 'Last Time' and 'First Time' parameters.\n" "Else:\n" " use 'Max. Sampling Interval' and last timestamp set.\n\n" "Default: use 'Max. Sampling Interval' and 'Last Time'.") hlay_maxintvl = QHBoxLayout() hlay_maxintvl.addWidget(self._pb_plussett) hlay_maxintvl.addWidget(self._ld_maxintvl) self._sb_maxintvl = PyDMSpinbox( self, self.devname.substitute(propty='MaxSplIntvl-SP')) self._sb_maxintvl.precisionFromPV = True self._sb_maxintvl.showStepExponent = False self._lb_maxintvl = PyDMLabel( self, self.devname.substitute(propty='MaxSplIntvl-RB')) self._lb_maxintvl.setAlignment(Qt.AlignCenter) self._lb_maxintvl.precisionFromPV = True self._ld_firstsmpl = QLabel('First Time [s]:', self, alignment=Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._ld_firstsmpl.setVisible(False) self._le_firstsmpl = PyDMLineEdit( self, self.devname.substitute(propty='FrstSplTime-SP')) self._le_firstsmpl.setVisible(False) self._lb_firstsmpl_dcct = PyDMLabel( self, self.devname.substitute(propty='FrstSplTime-RB')) self._lb_firstsmpl_dcct.setVisible(False) self._lb_firstsmpl_bpm = PyDMLabel( self, self.devname.substitute(propty='FrstSplTimeBPM-RB')) self._lb_firstsmpl_bpm.setVisible(False) self._pb_firstnow = QPushButton(qta.icon('mdi.clock-end'), '', self) self._pb_firstnow.setObjectName('firstnow') self._pb_firstnow.setStyleSheet( '#firstnow{min-width:25px; max-width:25px; icon-size:20px;}') self._pb_firstnow.setToolTip('Click to set current timestamp') self._pb_firstnow.released.connect(self._update_first_time) self._pb_firstnow.setVisible(False) hbox_sp_first = QHBoxLayout() hbox_sp_first.addWidget(self._le_firstsmpl) hbox_sp_first.addWidget(self._pb_firstnow) self._ld_lastsmpl = QLabel('Last Time [s]:', self, alignment=Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._ld_lastsmpl.setToolTip( "If 'Last Time' == -1, use current timestamp.") self._ld_lastsmpl.setVisible(False) self._le_lastsmpl = PyDMLineEdit( self, self.devname.substitute(propty='LastSplTime-SP')) self._le_lastsmpl.setVisible(False) self._lb_lastsmpl_dcct = PyDMLabel( self, self.devname.substitute(propty='LastSplTime-RB')) self._lb_lastsmpl_dcct.setVisible(False) self._lb_lastsmpl_bpm = PyDMLabel( self, self.devname.substitute(propty='LastSplTimeBPM-RB')) self._lb_lastsmpl_bpm.setVisible(False) self._pb_lastnow = QPushButton(qta.icon('mdi.clock-end'), '', self) self._pb_lastnow.setObjectName('lastnow') self._pb_lastnow.setStyleSheet( '#lastnow{min-width:25px; max-width:25px; icon-size:20px;}') self._pb_lastnow.setToolTip('Click to set current timestamp') self._pb_lastnow.released.connect(self._update_last_time) self._pb_lastnow.setVisible(False) hbox_sp_last = QHBoxLayout() hbox_sp_last.addWidget(self._le_lastsmpl) hbox_sp_last.addWidget(self._pb_lastnow) self._ld_smplintvl = QLabel('Samples\nInterval [s]:', self, alignment=Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._lb_smplintvl_dcct = PyDMLabel( self, self.devname.substitute(propty='SplIntvl-Mon')) self._lb_smplintvl_bpm = PyDMLabel( self, self.devname.substitute(propty='SplIntvlBPM-Mon')) self._lb_smplintvl_bpm.setVisible(False) self._ld_intvlbtwspl = QLabel('Interval Between\nSamples [s]:', self, alignment=Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._sb_intvlbtwspl = PyDMSpinbox( self, self.devname.substitute(propty='MinIntvlBtwSpl-SP')) self._sb_intvlbtwspl.precisionFromPV = True self._sb_intvlbtwspl.showStepExponent = False self._lb_intvlbtwspl = PyDMLabel( self, self.devname.substitute(propty='MinIntvlBtwSpl-RB')) self._lb_intvlbtwspl.setAlignment(Qt.AlignCenter) self._lb_intvlbtwspl.precisionFromPV = True self._ld_bufautoreset = QLabel('Auto Reset:', self, alignment=Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._cb_bufautoreset = PyDMEnumComboBox( self, self.devname.substitute(propty='BuffAutoRst-Sel')) self._lb_bufautoreset = PyDMLabel( self, self.devname.substitute(propty='BuffAutoRst-Sts')) self._ld_bufdcurr = QLabel('Auto Reset Delta\nCurrent [mA]:', self, alignment=Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._sb_bufdcurr = PyDMSpinbox( self, self.devname.substitute(propty='BuffAutoRstDCurr-SP')) self._sb_bufdcurr.showStepExponent = False self._lb_bufdcurr = PyDMLabel( self, self.devname.substitute(propty='BuffAutoRstDCurr-RB')) self._ld_bufsize = QLabel('Size:', self, alignment=Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._lb_bufsize_dcct = PyDMLabel( self, self.devname.substitute(propty='BuffSize-Mon')) self._lb_bufsize_dcct.setAlignment(Qt.AlignCenter) self._lb_bufsize_bpm = PyDMLabel( self, self.devname.substitute(propty='BuffSizeBPM-Mon')) self._lb_bufsize_bpm.setAlignment(Qt.AlignCenter) self._lb_bufsize_bpm.setVisible(False) self._pb_bufreset = PyDMPushButton( self, label='', icon=qta.icon('mdi.delete-empty'), pressValue=1, init_channel=self.devname.substitute(propty='BuffRst-Cmd')) self._pb_bufreset.setObjectName('reset') self._pb_bufreset.setStyleSheet( "#reset{min-width:25px; max-width:25px; icon-size:20px;}") self._ld_sep = QLabel('/', self) self._lb_bufsizetot_dcct = PyDMLabel( self, self.devname.substitute(propty='BuffSizeTot-Mon')) self._lb_bufsizetot_dcct.setStyleSheet("min-width:5em; max-width:5em;") self._lb_bufsizetot_dcct.setAlignment(Qt.AlignCenter) self._lb_bufsizetot_dcct.precision = 0 self._lb_bufsizetot_bpm = PyDMLabel( self, self.devname.substitute(propty='BuffSizeTotBPM-Mon')) self._lb_bufsizetot_bpm.setStyleSheet("min-width:5em; max-width:5em;") self._lb_bufsizetot_bpm.setAlignment(Qt.AlignCenter) self._lb_bufsizetot_bpm.precision = 0 self._lb_bufsizetot_bpm.setVisible(False) glay_bufsize = QGridLayout() glay_bufsize.addWidget(self._lb_bufsize_dcct, 0, 0) glay_bufsize.addWidget(self._lb_bufsize_bpm, 0, 0) glay_bufsize.addWidget(self._pb_bufreset, 0, 1) glay_bufsize.addWidget(self._ld_sep, 0, 2) glay_bufsize.addWidget(self._lb_bufsizetot_dcct, 0, 3) glay_bufsize.addWidget(self._lb_bufsizetot_bpm, 0, 3) glay_bufsize.setColumnStretch(0, 5) glay_bufsize.setColumnStretch(1, 2) glay_bufsize.setColumnStretch(2, 1) glay_bufsize.setColumnStretch(3, 5) gbox = QGroupBox('Lifetime Settings', self) lay = QGridLayout(gbox) lay.addWidget(self._ld_calcmode, 0, 0) lay.addWidget(self._cb_calcmode, 0, 1) lay.addWidget(self._lb_calcmode, 0, 2) lay.addWidget(self._ld_curroffset, 1, 0) lay.addWidget(self._sb_curroffset, 1, 1) lay.addWidget(self._lb_curroffset, 1, 2) lay.addItem(QSpacerItem(1, 1, QSzPlcy.Expanding, QSzPlcy.Minimum), 2, 1) lay.addWidget(self._ld_buffer, 3, 0, 1, 3) lay.addLayout(hlay_maxintvl, 4, 0) lay.addWidget(self._sb_maxintvl, 4, 1) lay.addWidget(self._lb_maxintvl, 4, 2) lay.addWidget(self._ld_firstsmpl, 5, 0) lay.addLayout(hbox_sp_first, 5, 1, 1, 2) lay.addWidget(self._lb_firstsmpl_dcct, 6, 1, 1, 2) lay.addWidget(self._lb_firstsmpl_bpm, 6, 1, 1, 2) lay.addWidget(self._ld_lastsmpl, 7, 0) lay.addLayout(hbox_sp_last, 7, 1, 1, 2) lay.addWidget(self._lb_lastsmpl_dcct, 8, 1, 1, 2) lay.addWidget(self._lb_lastsmpl_bpm, 8, 1, 1, 2) lay.addWidget(self._ld_smplintvl, 9, 0) lay.addWidget(self._lb_smplintvl_dcct, 9, 1) lay.addWidget(self._lb_smplintvl_bpm, 9, 1) lay.addWidget(self._ld_intvlbtwspl, 10, 0) lay.addWidget(self._sb_intvlbtwspl, 10, 1) lay.addWidget(self._lb_intvlbtwspl, 10, 2) lay.addItem(QSpacerItem(20, 5, QSzPlcy.Minimum, QSzPlcy.Fixed), 11, 1) lay.addWidget(self._ld_bufautoreset, 12, 0) lay.addWidget(self._cb_bufautoreset, 12, 1) lay.addWidget(self._lb_bufautoreset, 12, 2) lay.addWidget(self._ld_bufdcurr, 13, 0) lay.addWidget(self._sb_bufdcurr, 13, 1) lay.addWidget(self._lb_bufdcurr, 13, 2) lay.addItem(QSpacerItem(20, 5, QSzPlcy.Minimum, QSzPlcy.Fixed), 14, 1) lay.addWidget(self._ld_bufsize, 15, 0) lay.addLayout(glay_bufsize, 15, 1, 1, 2) return gbox def _setupGraphSettingsWidget(self): self._ld_ltfrom = QLabel('Show lifetime from:', self, alignment=Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._cb_ltfrom = QComboBox() self._cb_ltfrom.addItem('DCCT') self._cb_ltfrom.addItem('BPM') self._cb_ltfrom.currentTextChanged.connect( self._handle_lifetime_type_sel) self._ld_showsmpl = QLabel('Show samples: ', self, alignment=Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self._cb_showsmpl = QCheckBox(self) self._cb_showsmpl.setChecked(True) self._cb_showsmpl.stateChanged.connect(self._handle_samples_visibility) gbox = QGroupBox('Graphs Settings', self) lay = QGridLayout(gbox) lay.addItem(QSpacerItem(1, 1, QSzPlcy.Expanding, QSzPlcy.Minimum), 0, 0) lay.addWidget(self._ld_ltfrom, 0, 1) lay.addWidget(self._cb_ltfrom, 0, 2) lay.addItem(QSpacerItem(1, 1, QSzPlcy.Expanding, QSzPlcy.Minimum), 0, 3) lay.addItem(QSpacerItem(1, 1, QSzPlcy.Minimum, QSzPlcy.Expanding), 1, 1, 1, 2) lay.addWidget(self._ld_showsmpl, 2, 1) lay.addWidget(self._cb_showsmpl, 2, 2) return gbox # ---------- auxiliar methods ---------- def _format_lifetime_label(self, value): """Format lifetime label.""" if self._lb_lifetime.channel != self.sender().address: return lt = 0 if _np.isnan(value) else value H = int(lt // 3600) m = int((lt % 3600) // 60) s = int((lt % 3600) % 60) lt_str = '{:d}:{:02d}:{:02d}'.format(H, m, s) self._lb_lifetime.setText(lt_str) @Slot(str) def _handle_lifetime_type_sel(self, text): """Handle lifetime type selection.""" cond = bool(text == 'DCCT') self._curve_current.setVisible(cond) self._curve_lifetimedcct.setVisible(cond) self._curve_dcct_buff.setVisible(cond) self._lb_bufsizetot_dcct.setVisible(cond) self._lb_bufsize_dcct.setVisible(cond) self._lb_smplintvl_dcct.setVisible(cond) self._curve_bpmsum.setVisible(not cond) self._curve_lifetimebpm.setVisible(not cond) self._curve_bpm_buff.setVisible(not cond) self._lb_bufsizetot_bpm.setVisible(not cond) self._lb_bufsize_bpm.setVisible(not cond) self._lb_smplintvl_bpm.setVisible(not cond) visi = self._pb_plussett.text() == '-' self._lb_firstsmpl_dcct.setVisible(cond and visi) self._lb_lastsmpl_dcct.setVisible(cond and visi) self._lb_firstsmpl_bpm.setVisible(not cond and visi) self._lb_lastsmpl_bpm.setVisible(not cond and visi) if not cond: self.graph.plotItem.getAxis('left').setLabel('01M1 BPM Sum', color='blue') self._lb_lifetime.channel = \ self.devname.substitute(propty='LifetimeBPM-Mon') else: self.graph.plotItem.getAxis('left').setLabel('Current [mA]', color='blue') self._lb_lifetime.channel = \ self.devname.substitute(propty='Lifetime-Mon') def _handle_intvl_sett_visibility(self): """Handle sampling interval settings.""" text = self.sender().text() visi = text == '+' self._ld_firstsmpl.setVisible(visi) self._le_firstsmpl.setVisible(visi) self._pb_firstnow.setVisible(visi) self._ld_lastsmpl.setVisible(visi) self._le_lastsmpl.setVisible(visi) self._pb_lastnow.setVisible(visi) showingdcct = self._cb_ltfrom.currentText() == 'DCCT' self._lb_firstsmpl_dcct.setVisible(showingdcct and visi) self._lb_lastsmpl_dcct.setVisible(showingdcct and visi) self._lb_firstsmpl_bpm.setVisible(not showingdcct and visi) self._lb_lastsmpl_bpm.setVisible(not showingdcct and visi) self.sender().setText('+' if text == '-' else '-') @Slot(int) def _handle_samples_visibility(self, state): """Handle samples visibility.""" showingdcct = self._cb_ltfrom.currentText() == 'DCCT' self._curve_dcct_buff.setVisible(showingdcct and state) self._curve_bpm_buff.setVisible(not showingdcct and state) def _handle_settings_vis(self): vis = self.settings.isVisible() text = '>' if vis else '<' ttip = 'Show' if vis else 'Hide' self.pb_showsett.setText(text) self.pb_showsett.setToolTip(ttip + ' settings') self.settings.setVisible(not vis) self.sender().parent().adjustSize() self.centralWidget().adjustSize() self.adjustSize() def _handle_efficiency_vis(self): vis = self.eff_graph.isVisible() text = 'v' if vis else '^' ttip = 'Show' if vis else 'Hide' self.pb_showeff.setText(text) self.pb_showeff.setToolTip(ttip + ' efficiency graph') self.eff_graph.setVisible(not vis) self.sender().parent().adjustSize() self.centralWidget().adjustSize() self.adjustSize() def _update_first_time(self): """Update first sample time to current timestamp.""" now = _time.time() self._le_firstsmpl.send_value_signal[float].emit(now) def _update_last_time(self): """Update last sample time to current timestamp.""" now = _time.time() self._le_lastsmpl.send_value_signal[float].emit(now) @Slot(float) def _update_graph(self, value): """Receive new lifetime values and update curves in hours.""" if 'BPM' in self.sender().address: self._curve_lifetimebpm.receiveNewValue(value / 3600) else: self._curve_lifetimedcct.receiveNewValue(value / 3600) @Slot(_np.ndarray) def _update_waveforms(self, value): """Update samples waveforms.""" address = self.sender().address if 'BPM' in address: if 'Timestamp' in address: self.bpm_wavx = value + _time.time() self._flag_need_bpmx = False elif 'Value' in address: self.bpm_wavy = value self._flag_need_bpmy = False if not self._flag_need_bpmy and not self._flag_need_bpmx: if len(self.bpm_wavx) != len(self.bpm_wavy): return self.graph.fill_curve_buffer(self._curve_bpm_buff, self.bpm_wavx, self.bpm_wavy) self._flag_need_bpmx = True self._flag_need_bpmy = True else: if 'Timestamp' in address: self.dcct_wavx = value + _time.time() self._flag_need_dcctx = False elif 'Value' in address: self.dcct_wavy = value self._flag_need_dccty = False if not self._flag_need_dccty and not self._flag_need_dcctx: if len(self.dcct_wavx) != len(self.dcct_wavy): return self.graph.fill_curve_buffer(self._curve_dcct_buff, self.dcct_wavx, self.dcct_wavy) self._flag_need_dcctx = True self._flag_need_dccty = True
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 _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 fillWidget(self, name): if name in self.filled_widgets: return if name == 'detail': self.detail_bt = QPushButton(self) if self._name.dev == 'DCLink': self.detail_bt.setIcon(qta.icon('fa5s.list-ul')) self.detail_bt.setToolTip(self._name) else: self.detail_bt.setText(self._name) self.detail_wid.layout().addWidget(self.detail_bt) elif name == 'bbb' and self._bbb_name: self.bbb_lb = QLabel(self._bbb_name, self) self.bbb_wid.layout().addWidget(self.bbb_lb) elif name == 'udc' and self._udc_name: self.udc_lb = QLabel(self._udc_name, self) self.udc_wid.layout().addWidget(self.udc_lb) elif name == 'opmode' and self._has_opmode: opmode_list = list() if 'Voltage' not in self._analog_name: self.opmode_cb = SiriusEnumComboBox(self, self._opmode_sel) opmode_list.append(self.opmode_cb) self.opmode_lb = PyDMLabel(self, self._opmode_sts) opmode_list.append(self.opmode_lb) for wid in opmode_list: self.opmode_wid.layout().addWidget(wid) elif name == 'ctrlmode' and self._has_ctrlmode: self.ctrlmode_lb = PyDMLabel(self, self._ctrlmode_sts) self.ctrlmode_wid.layout().addWidget(self.ctrlmode_lb) elif name == 'state' and self._has_pwrstate: self.state_bt = PyDMStateButton(self, self._pwrstate_sel) self.state_led = SiriusLedState(self, self._pwrstate_sts) self.state_wid.layout().addWidget(self.state_bt) self.state_wid.layout().addWidget(self.state_led) elif name == 'pulse' and self._is_pulsed: self.pulse_bt = PyDMStateButton(self, self._pulse_sel) self.pulse_led = SiriusLedState(self, self._pulse_sts) self.pulse_wid.layout().addWidget(self.pulse_bt) self.pulse_wid.layout().addWidget(self.pulse_led) elif name == 'intlk': if self._is_pulsed: self.intlk_led = PyDMLedMultiChannel( self, channels2values={ch: 1 for ch in self._intlk}) self.intlk_wid.layout().addWidget(self.intlk_led) elif self._is_linac: if IsLinacSpect.match(self.devname): self.intlk_led = LISpectIntlkLed(self) else: self.intlk_led = PyDMLedMultiChannel(self, channels2values={ self._intlk: { 'value': _PS_LI_INTLK, 'comp': 'lt' } }) self.intlk_wid.layout().addWidget(self.intlk_led) elif self._is_regatron: if not self._is_reg_slave: self.generr_led = SiriusLedAlert(self, self._generr) self.genwrn_led = SiriusLedAlert(self, self._genwrn) self.intlk_wid.layout().addWidget(self.generr_led) self.intlk_wid.layout().addWidget(self.genwrn_led) elif self._is_fofb: self.intlk_led = PyDMLedMultiChannel( self, channels2values={ch: 1 for ch in self._intlk}) self.intlk_wid.layout().addWidget(self.intlk_led) else: self.soft_intlk_led = SiriusLedAlert(self, self._soft_intlk) self.hard_intlk_led = SiriusLedAlert(self, self._hard_intlk) self.intlk_wid.layout().addWidget(self.soft_intlk_led) self.intlk_wid.layout().addWidget(self.hard_intlk_led) elif name == 'conn' and self._is_linac: self.conn_led = PyDMLedMultiChannel( self, channels2values={self._conn: 0}) self.conn_wid.layout().addWidget(self.conn_led) elif name == 'reset' and self._has_reset: self.reset_bt = PyDMPushButton(parent=self, init_channel=self._reset_intlk, pressValue=1) self.reset_bt.setIcon(qta.icon('fa5s.sync')) self.reset_bt.setObjectName('reset_bt') self.reset_bt.setStyleSheet( '#reset_bt{min-width:25px; max-width:25px; icon-size:20px;}') self.reset_wid.layout().addWidget(self.reset_bt) elif name == 'ctrlloop' and self._has_ctrlloop: if self._is_fofb: self.ctrlloop_bt = PyDMStateButton(self, self._ctrlloop_sel) else: self.ctrlloop_bt = PyDMStateButton(self, self._ctrlloop_sel, invert=True) self.ctrlloop_lb = PyDMLabel(self, self._ctrlloop_sts) self.ctrlloop_wid.layout().addWidget(self.ctrlloop_bt) self.ctrlloop_wid.layout().addWidget(self.ctrlloop_lb) elif name == 'wfmupdate' and self._has_wfmupdt: self.wfmupdate_bt = PyDMStateButton(self, self._wfmupdate_sel) self.wfmupdate_led = SiriusLedState(self, self._wfmupdate_sts) self.wfmupdate_wid.layout().addWidget(self.wfmupdate_bt) self.wfmupdate_wid.layout().addWidget(self.wfmupdate_led) elif name == 'updparms' and self._has_parmupdt: self.updparms_bt = PyDMPushButton(parent=self, init_channel=self._updparms_cmd, pressValue=1) self.updparms_bt.setIcon(qta.icon('fa5s.redo-alt')) self.updparms_bt.setObjectName('updparms_bt') self.updparms_bt.setStyleSheet( '#updparms_bt{min-width:25px;max-width:25px;icon-size:20px;}') self.updparms_wid.layout().addWidget(self.updparms_bt) elif name == 'setpoint' and self._has_analsp: self.setpoint = PyDMSpinboxScrollbar(self, self._analog_sp) if self._is_fofb: self.setpoint.spinbox.precisionFromPV = False self.setpoint.spinbox.precision = 6 self.setpoint_wid.layout().addWidget(self.setpoint) elif name == 'readback' and self._has_analrb: self.readback = PyDMLabel(self, self._analog_rb) if self._is_fofb: self.readback.precisionFromPV = False self.readback.precision = 6 self.readback_wid.layout().addWidget(self.readback) elif name == 'monitor' and self._has_analmon: self.monitor = PyDMLabel(self, self._analog_mon) self.monitor_wid.layout().addWidget(self.monitor) elif name == 'strength_sp' and self._has_strength: self.strength_sp_le = PyDMSpinboxScrollbar(self, self._strength_sp) self.strength_sp_wid.layout().addWidget(self.strength_sp_le) elif name == 'strength_rb' and self._has_strength: self.strength_rb_lb = PyDMLabel(parent=self, init_channel=self._strength_rb) self.strength_rb_lb.showUnits = True self.strength_rb_wid.layout().addWidget(self.strength_rb_lb) elif name == 'strength_mon' and self._has_strength_mon: self.strength_mon_lb = PyDMLabel(parent=self, init_channel=self._strength_mon) self.strength_mon_lb.showUnits = True self.strength_mon_wid.layout().addWidget(self.strength_mon_lb) elif name == 'trim' and self._has_trim: self.trim_bt = QPushButton(qta.icon('fa5s.angle-right'), '', self) self.trim_wid.layout().addWidget(self.trim_bt) self.filled_widgets.add(name)
class PUDetailWidget(QWidget): """Detailed widget for controlling a pulsed magnet.""" def __init__(self, devname, parent=None): """Receive a parent and a pulsed mangnet name.""" super().__init__(parent) self._devname = _PVName(devname) self._section = self._devname.sec self._prefix = _VACA_PREFIX self._pdev = self._devname.substitute(prefix=self._prefix) self.setObjectName(self._section + 'App') self.setWindowIcon( qta.icon('mdi.current-ac', color=util.get_appropriate_color(self._section))) self._create_pvs() self._setup_ui() self.setStyleSheet(""" #pulses_box, #pwrstate_box { max-width: 8em; } """) self.setFocusPolicy(Qt.StrongFocus) def _create_pvs(self): """Create variables with pvs that'll be used.""" self._voltage_sp_pv = self._pdev.substitute(propty='Voltage-SP') self._voltage_rb_pv = self._pdev.substitute(propty='Voltage-RB') self._voltage_mon_pv = self._pdev.substitute(propty='Voltage-Mon') self._kick_sp_pv = self._pdev.substitute(propty='Kick-SP') self._kick_rb_pv = self._pdev.substitute(propty='Kick-RB') self._kick_mon_pv = self._pdev.substitute(propty='Kick-Mon') self._pwrstate_sel_pv = self._pdev.substitute(propty='PwrState-Sel') self._pwrstate_sts_pv = self._pdev.substitute(propty='PwrState-Sts') self._enablepulses_sel_pv = self._pdev.substitute(propty='Pulse-Sel') self._enablepulses_sts_pv = self._pdev.substitute(propty='Pulse-Sts') self._reset_cmd_pv = self._pdev.substitute(propty='Reset-Cmd') self._intlk1_mon_pv = self._pdev.substitute(propty='Intlk1-Mon') self._intlk2_mon_pv = self._pdev.substitute(propty='Intlk2-Mon') self._intlk3_mon_pv = self._pdev.substitute(propty='Intlk3-Mon') self._intlk4_mon_pv = self._pdev.substitute(propty='Intlk4-Mon') self._intlk5_mon_pv = self._pdev.substitute(propty='Intlk5-Mon') self._intlk6_mon_pv = self._pdev.substitute(propty='Intlk6-Mon') self._intlk7_mon_pv = self._pdev.substitute(propty='Intlk7-Mon') self._intlk1_lbcte_pv = self._pdev.substitute(propty='Intlk1Label-Cte') self._intlk2_lbcte_pv = self._pdev.substitute(propty='Intlk2Label-Cte') self._intlk3_lbcte_pv = self._pdev.substitute(propty='Intlk3Label-Cte') self._intlk4_lbcte_pv = self._pdev.substitute(propty='Intlk4Label-Cte') self._intlk5_lbcte_pv = self._pdev.substitute(propty='Intlk5Label-Cte') self._intlk6_lbcte_pv = self._pdev.substitute(propty='Intlk6Label-Cte') self._intlk7_lbcte_pv = self._pdev.substitute(propty='Intlk7Label-Cte') if 'Sept' not in self._devname: self._intlk8_mon_pv = self._pdev.substitute(propty='Intlk8-Mon') self._intlk8_lbcte_pv = \ self._pdev.substitute(propty='Intlk8Label-Cte') self._ctrlmode_pv = self._pdev.substitute(propty='CtrlMode-Mon') self._trigname = self._devname.substitute(dis='TI') def _setup_ui(self): self.header_label = QLabel("<h1>" + self._devname + "</h1>") self.header_label.setObjectName("header_label") interlock_box = QGroupBox(parent=self, title="Interlock") interlock_box.setObjectName("interlock_box") interlock_box.setLayout(self._interlock_layout()) pwrstate_box = QGroupBox(parent=self, title="Power") pwrstate_box.setObjectName("pwrstate_box") pwrstate_box.setLayout(self._pwrstate_layout()) pulses_box = QGroupBox(parent=self, title="Pulses") pulses_box.setObjectName("pulses_box") pulses_box.setLayout(self._pulses_layout()) voltage_box = QGroupBox(parent=self, title="Voltage") voltage_box.setObjectName("voltage_box") voltage_box.setLayout(self._voltage_layout()) kick_box = QGroupBox(parent=self, title="Kick") kick_box.setObjectName("kick_box") kick_box.setLayout(self._kick_layout()) timing_box = QGroupBox(parent=self, title='Trigger') timing_box.setObjectName('timing_box') hbl = QHBoxLayout(timing_box) hbl.addWidget(HLTriggerSimple(timing_box, self._trigname, self._prefix)) self.layout = QGridLayout(self) self.layout.addWidget(self.header_label, 0, 0, 1, 3) self.layout.addWidget(interlock_box, 1, 0, 3, 1) vbl1 = QVBoxLayout() vbl1.addWidget(pwrstate_box) vbl1.addWidget(pulses_box) self.layout.addLayout(vbl1, 1, 1, 2, 1) vbl2 = QVBoxLayout() vbl2.addWidget(voltage_box) vbl2.addWidget(kick_box) self.layout.addLayout(vbl2, 1, 2, 2, 1) self.layout.addWidget(timing_box, 3, 1, 1, 3) self.layout.addLayout(self._ctrlmode_layout(), 4, 1, 1, 3) def _interlock_layout(self): interlock_layout = QGridLayout() intlk_cnt = 8 if 'Sept' not in self._devname else 7 for i in range(intlk_cnt): label = PyDMLabel( self, getattr(self, '_intlk' + str(i + 1) + '_lbcte_pv')) led = PyDMLed(self, getattr(self, '_intlk' + str(i + 1) + '_mon_pv')) led.onColor = led.LightGreen led.offColor = led.Red interlock_layout.addWidget(led, i, 0) interlock_layout.addWidget(label, i, 1) self.reset_bt = PyDMPushButton(parent=self, init_channel=self._reset_cmd_pv, pressValue=1) self.reset_bt.setIcon(qta.icon('fa5s.sync')) self.reset_bt.setObjectName('reset_bt') self.reset_bt.setStyleSheet( '#reset_bt{min-width:25px; max-width:25px; icon-size:20px;}') interlock_layout.addWidget(self.reset_bt, i + 1, 0, 1, 2, alignment=Qt.AlignHCenter) return interlock_layout def _pwrstate_layout(self): pwrstate_layout = QHBoxLayout() self.state_button = PyDMStateButton(parent=self, init_channel=self._pwrstate_sel_pv) self.state_led = SiriusLedState(self, self._pwrstate_sts_pv) pwrstate_layout.addWidget(self.state_button) pwrstate_layout.addWidget(self.state_led) return pwrstate_layout def _pulses_layout(self): pulses_layout = QHBoxLayout() self.pulses_state_button = PyDMStateButton( parent=self, init_channel=self._enablepulses_sel_pv) self.pulses_state_led = SiriusLedState( parent=self, init_channel=self._enablepulses_sts_pv) pulses_layout.addWidget(self.pulses_state_button) pulses_layout.addWidget(self.pulses_state_led) return pulses_layout def _voltage_layout(self): voltage_layout = QVBoxLayout() self.voltage_sp_widget = PyDMSpinboxScrollbar(self, self._voltage_sp_pv) self.voltage_rb_label = PyDMLabel(self, self._voltage_rb_pv) self.voltage_rb_label.showUnits = True self.voltage_rb_label.precisionFromPV = True self.voltage_mon_label = PyDMLabel(self, self._voltage_mon_pv) self.voltage_mon_label.showUnits = True self.voltage_mon_label.precisionFromPV = True voltage_layout = QFormLayout() voltage_layout.setLabelAlignment(Qt.AlignRight) voltage_layout.setFormAlignment(Qt.AlignHCenter) voltage_layout.addRow('SP:', self.voltage_sp_widget) voltage_layout.addRow('RB:', self.voltage_rb_label) voltage_layout.addRow('Mon:', self.voltage_mon_label) return voltage_layout def _kick_layout(self): self.kick_sp_widget = PyDMSpinboxScrollbar(self, self._kick_sp_pv) self.kick_rb_label = PyDMLabel(self, self._kick_rb_pv) self.kick_rb_label.showUnits = True self.kick_rb_label.precisionFromPV = True self.kick_mon_label = PyDMLabel(self, self._kick_mon_pv) self.kick_mon_label.showUnits = True self.kick_mon_label.precisionFromPV = True kick_layout = QFormLayout() kick_layout.setLabelAlignment(Qt.AlignRight) kick_layout.setFormAlignment(Qt.AlignHCenter) kick_layout.addRow('SP:', self.kick_sp_widget) kick_layout.addRow('RB:', self.kick_rb_label) kick_layout.addRow('Mon:', self.kick_mon_label) return kick_layout def _ctrlmode_layout(self): ctrlmode_layout = QHBoxLayout() self.ctrlmode_led = SiriusLedAlert(parent=self, init_channel=self._ctrlmode_pv) self.ctrlmode_label = PyDMLabel(parent=self, init_channel=self._ctrlmode_pv) ctrlmode_layout.addStretch() ctrlmode_layout.addWidget(self.ctrlmode_led) ctrlmode_layout.addWidget(self.ctrlmode_label) return ctrlmode_layout