Beispiel #1
0
    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)
Beispiel #2
0
    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
Beispiel #3
0
    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
Beispiel #4
0
    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
Beispiel #5
0
    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)
Beispiel #6
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)
Beispiel #7
0
 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)
Beispiel #8
0
    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)
Beispiel #10
0
    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
Beispiel #11
0
 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
Beispiel #12
0
    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
Beispiel #13
0
    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)
Beispiel #14
0
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)
Beispiel #15
0
    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)
Beispiel #16
0
    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)
Beispiel #17
0
    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
Beispiel #18
0
    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)
Beispiel #19
0
    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)
Beispiel #20
0
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)
Beispiel #21
0
    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
            }
        }]
Beispiel #23
0
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()))
Beispiel #24
0
    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
Beispiel #25
0
    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
Beispiel #26
0
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
Beispiel #27
0
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)
Beispiel #28
0
    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
Beispiel #29
0
 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)
Beispiel #30
0
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