Esempio n. 1
0
    def __init__(self, parent=None, adv_mode=False):
        """Constructor."""
        super().__init__(parent)
        self.setWindowTitle('PS/PU Test')
        self.setObjectName('ASApp')
        cor = get_appropriate_color(section='AS')
        self.setWindowIcon(qta.icon('mdi.test-tube', color=cor))

        # auxiliar data for initializing SI Fam PS
        self._is_adv_mode = adv_mode
        self._si_fam_psnames = PSSearch.get_psnames(filters={
            'sec': 'SI',
            'sub': 'Fam',
            'dis': 'PS'
        })

        # auxiliary data for SI fast correctors
        self._si_fastcorrs = PSSearch.get_psnames(filters={
            'sec': 'SI',
            'dis': 'PS',
            'dev': 'FC.*'
        })

        self._needs_update_setup = False
        self._setup_ui()
        self._update_setup_timer = QTimer(self)
        self._update_setup_timer.timeout.connect(self._update_setup)
        self._update_setup_timer.setInterval(250)
        self._update_setup_timer.start()
Esempio n. 2
0
    def setupui(self):
        chs = PSSearch.get_psnames({'sec': 'BO', 'dev': 'CH'})
        cvs = PSSearch.get_psnames({'sec': 'BO', 'dev': 'CV'})
        quads = PSSearch.get_psnames({'sec': 'BO', 'dev': 'Q(F|D)'})
        sexts = PSSearch.get_psnames({'sec': 'BO', 'dev': 'S.*'})
        dips = PSSearch.get_psnames({'sec': 'BO', 'dev': 'B'})

        wid = QWidget(self)
        self.setCentralWidget(wid)
        chwid = GraphWidget(wid,
                            chs,
                            name='CHs',
                            delta=0.05,
                            idxini=25,
                            idxfin=606,
                            legend=False)
        cvwid = GraphWidget(wid,
                            cvs,
                            name='CVs',
                            delta=0.05,
                            idxini=25,
                            idxfin=606,
                            legend=False)
        dipwid = GraphWidget(wid,
                             dips,
                             name='Dipoles',
                             delta=0.0,
                             idxini=110,
                             idxfin=2440,
                             legend=True)
        quadwid = GraphWidget(wid,
                              quads,
                              name='Quadrupoles',
                              delta=0.0,
                              idxini=110,
                              idxfin=2440,
                              legend=True)
        sextwid = GraphWidget(wid,
                              sexts,
                              name='Sextupoles',
                              delta=0.0,
                              idxini=110,
                              idxfin=2440,
                              legend=True)

        wid.setLayout(QGridLayout())
        wid.layout().addWidget(chwid, 0, 0)
        wid.layout().addWidget(cvwid, 0, 1)
        wid.layout().addWidget(quadwid, 1, 0)
        wid.layout().addWidget(sextwid, 1, 1)
        wid.layout().addWidget(dipwid, 2, 0, 1, 2)
Esempio n. 3
0
 def _get_PSNames(self, pstype=None):
     psnames = list()
     if pstype == 'corrs':
         psnames = _PSSearch.get_psnames({'sec': 'BO', 'dev': 'C(V|H)'})
     elif pstype == 'quads':
         psnames = ['BO-Fam:PS-QF', 'BO-Fam:PS-QD']
     elif pstype == 'sexts':
         psnames = ['BO-Fam:PS-SF', 'BO-Fam:PS-SD']
     else:
         psnames = _PSSearch.get_psnames({'sec': 'BO', 'sub': 'Fam'})
         psnames.extend(_PSSearch.get_psnames({'sec': 'BO', 'dev': 'QS'}))
         psnames.extend(_PSSearch.get_psnames({'sec': 'BO', 'dev': 'CH'}))
         psnames.extend(_PSSearch.get_psnames({'sec': 'BO', 'dev': 'CV'}))
     return psnames
Esempio n. 4
0
 def _get_pu_tree_names(self):
     punames = PSSearch.get_psnames({
         'sec': '(TB|BO|TS|SI)',
         'dis': 'PU',
         'dev': '.*(Kckr|Sept).*'
     })
     return punames
def get_pvs(accelerator, pattern):
    """."""
    regexp = re.compile(pattern)
    if accelerator:
        psnames = PSSearch.get_psnames({'sec': accelerator})
    else:
        psnames = PSSearch.get_psnames()
    pvslist = []
    for psname in psnames:
        psdata = PSData(psname)
        dbase = psdata.propty_database
        for prop in dbase:
            pvname = psname + ':' + prop
            if regexp.match(pvname):
                pvslist.append(pvname)
    return pvslist
def get_all_psnames():
    """."""
    pss = PSSearch()
    # psn = pss.get_psnames() + li_psnames
    psn = pss.get_psnames()
    psnames = [SiriusPVName(psname) for psname in psn]
    return psnames
Esempio n. 7
0
def _create_objects(section):
    """."""
    dipnames = DIPNAMES[section]
    psnames = _PSSearch.get_psnames({'sec': section})
    kckrs = [
        _SiriusPVName('BO-01D:PU-InjKckr'),
        _SiriusPVName('BO-48D:PU-EjeKckr'),
        _SiriusPVName('SI-01SA:PU-InjDpKckr'),
        _SiriusPVName('SI-01SA:PU-InjNLKckr')
    ]
    # Add Kickers to TLs:
    if section == 'TS':
        psnames.extend(kckrs[1:])
        psnames = sorted(psnames)
    elif section == 'TB':
        psnames.append(kckrs[0])
        psnames = sorted(psnames)
    else:
        psnames = sorted(set(psnames) - set(kckrs))

    magnets = []
    dipoles = []
    for psname in psnames:
        if psname.dev.startswith('FC'):
            continue
        mfunc = _PSSearch.conv_psname_2_magfunc(psname)
        if mfunc == 'dipole':
            dipoles.append({'psname': psname, 'mafunc': mfunc})
            continue
        magnets.append({'psname': psname, 'mafunc': mfunc})
    return dipoles, magnets
Esempio n. 8
0
    def _make_sec_widget(self, sec):
        widget = QWidget(self)
        lay = QVBoxLayout(widget)

        if sec in {'TB', 'BO', 'TS', 'SI'}:
            devices = PSSearch.get_psnames({'sec': sec, 'dis': 'PU'})
        elif sec == 'InjBO':
            devices = PSSearch.get_psnames({
                'sec': '(TB|BO)',
                'dis': 'PU',
                'dev': 'Inj'
            })
        elif sec == 'EjeBO':
            devices = PSSearch.get_psnames({
                'sec': '(BO|TS)',
                'dis': 'PU',
                'dev': 'Eje'
            })
        elif sec == 'InjSI':
            devices = PSSearch.get_psnames({
                'sec': '(TS|SI)',
                'dis': 'PU',
                'dev': 'Inj'
            })
        elif sec == 'PingSI':
            devices = PSSearch.get_psnames({
                'sec': 'SI',
                'dis': 'PU',
                'dev': 'Ping'
            })

        visible_props = sort_propties([
            'detail', 'state', 'reset', 'intlk', 'setpoint', 'monitor',
            'pulse', 'strength_sp', 'strength_mon'
        ])

        lay.addWidget(SummaryHeader(devices[0], visible_props, self))
        for device in devices:
            ma_widget = SummaryWidget(device, visible_props, self)
            lay.addWidget(ma_widget)
            self.pu_widgets_dict[device] = ma_widget

        lay.addStretch()
        return widget
def get_pvs_bo():
    """."""
    psnames = PSSearch.get_psnames()
    pvs = dict()
    for psname in psnames:
        if psname[:2] in ('TB', 'TS', 'SI') and \
                'FCH' not in psname and \
                'FCV' not in psname and \
                'PU' not in psname:
            print(psname)
            pvs[psname] = epics.PV(psname + ':WfmUpdateAuto-Sel')
    return pvs
Esempio n. 10
0
 def __init__(self, parent=None, prefix=_vaca_prefix, filters=''):
     super().__init__(parent)
     self.setWindowTitle('Power Supplies Graph Monitor')
     self._prefix = prefix
     self._filters = filters
     if not filters:
         self.setObjectName('ASApp')
         filters = {'sec': 'SI', 'dis': 'PS', 'dev': 'CH'}
     else:
         self.setObjectName(filters['sec']+'App')
     self._psnames = _PSSearch.get_psnames(filters)
     self._magfunc = _PSSearch.conv_psname_2_magfunc(self._psnames[0])
     self._pstype = _PSSearch.conv_psname_2_pstype(self._psnames[0])
     self._setupUi()
Esempio n. 11
0
    def _setupUi(self):
        self.kicks = dict()
        for dev in ['CV', 'CH']:
            names = PSSearch.get_psnames({'sec': 'BO', 'dev': dev})
            corr2kicks = {n: self.strengths_dict[n] for n in names}
            self.kicks[dev] = _np.array([corr2kicks[n] for n in names])

        label_ch = QLabel('<h3>Horizontal</h3>',
                          self,
                          alignment=Qt.AlignCenter)
        self.graph_ch = _GraphKicks(parent=self,
                                    xdata=_np.array(self.consts.ch_pos),
                                    ydata=self.kicks['CH'],
                                    tooltip_names=self.consts.ch_nicknames,
                                    c0=self.consts.circum,
                                    color='blue')

        label_cv = QLabel('<h3>Vertical</h3>', self, alignment=Qt.AlignCenter)
        self.graph_cv = _GraphKicks(parent=self,
                                    xdata=_np.array(self.consts.cv_pos),
                                    ydata=self.kicks['CV'],
                                    tooltip_names=self.consts.cv_nicknames,
                                    c0=self.consts.circum,
                                    color='red')

        lb_stats = QLabel('<h4>Statistics: </h4>',
                          self,
                          alignment=Qt.AlignCenter)
        self.lb_statsdata = QLabel('X: {:7.3f} ± {:7.3f} urad\n'
                                   'Y: {:7.3f} ± {:7.3f} urad'.format(
                                       _np.mean(self.kicks['CH']),
                                       _np.std(self.kicks['CH']),
                                       _np.mean(self.kicks['CV']),
                                       _np.std(self.kicks['CV'])),
                                   self,
                                   alignment=Qt.AlignCenter)

        lay = QVBoxLayout(self)
        lay.setSpacing(10)
        lay.addWidget(
            QLabel('<h3>' + str(self.time) + '</h3>',
                   self,
                   alignment=Qt.AlignCenter))
        lay.addWidget(label_ch)
        lay.addWidget(self.graph_ch)
        lay.addWidget(label_cv)
        lay.addWidget(self.graph_cv)
        lay.addWidget(lb_stats)
        lay.addWidget(self.lb_statsdata)
Esempio n. 12
0
 def test_get_psnames(self):
     """Test get_psnames."""
     # without filters
     psnames = PSSearch.get_psnames()
     self.assertIsInstance(psnames, (list, tuple))
     for psname in TestPSSearch.sample:
         self.assertIn(psname, psnames)
     # check sorted
     sorted_psnames = sorted(psnames)
     self.assertEqual(psnames, sorted_psnames)
     # with filters
     psnames = PSSearch.get_psnames({'dis': 'PU'})
     self.assertEqual(len(psnames), 12)
     for name in psnames:
         self.assertIn('PU', name)
     psnames = PSSearch.get_psnames({'sub': '0.M1'})
     self.assertEqual(len(psnames), 69)
     # exceptions
     self.assertRaises(TypeError, PSSearch.get_psnames, filters=23)
     self.assertRaises(TypeError, PSSearch.get_psnames, filters=23.4)
     self.assertRaises(TypeError, PSSearch.get_psnames, filters=[
         0,
     ])
     self.assertRaises(TypeError, PSSearch.get_psnames, filters=(0.0, ))
Esempio n. 13
0
    def __init__(self, subsection=None, orientation=0, parent=None):
        """Class constructor.

        Parameters:
        psname_list - a list of power supplies, will be filtered based on
                      patterns defined in the subclass;
        orientation - how the different groups(defined in subclasses) will be
                      laid out.
        """
        super(BasePSControlWidget, self).__init__(parent)
        self._orientation = orientation
        self._subsection = subsection
        self._dev_list = PSSearch.get_psnames(self._getFilter(subsection))
        dev0 = PVName(self._dev_list[0])
        if dev0.sec == 'LI':
            if dev0.dev == 'Slnd':
                idcs = [int(PVName(dev).idx) for dev in self._dev_list]
                self._dev_list = [
                    x for _, x in sorted(zip(idcs, self._dev_list))
                ]
            if 'Q' in dev0.dev:
                all_props = dict()
                for dev in self._dev_list:
                    all_props.update(get_prop2label(dev))
                self.all_props = sort_propties(all_props)
            else:
                self.all_props = get_prop2label(self._dev_list[0])
        else:
            self.all_props = get_prop2label(self._dev_list[0])

        self.visible_props = self._getVisibleProps()
        if 'trim' in self.all_props:
            self.visible_props.append('trim')
        self.visible_props = sort_propties(self.visible_props)

        # Data used to filter the widgets
        self.ps_widgets_dict = dict()
        self.containers_dict = dict()
        self.filtered_widgets = set()  # Set with key of visible widgets

        # Setup the UI
        self.groups = self._getGroups()
        self._setup_ui()
        self._create_actions()
        self._enable_actions()
        if len(self.groups) in [1, 3]:
            self.setObjectName('cw')
            self.setStyleSheet('#cw{min-height: 40em;}')
Esempio n. 14
0
    def _update_setup(self):
        if not self._needs_update_setup:
            return
        self._needs_update_setup = False

        # update leds
        psnames = self.pwrsupplies_tree.checked_items()
        ti_ch = [
            PVName(name).substitute(prefix=VACA_PREFIX)
            for name in self._timing.get_pvnames_by_psnames(psnames)
        ]
        self.ticonn_led.set_channels(ti_ch)

        ps_ch = list()
        for name in psnames:
            ps_ch.append(
                PVName(name).substitute(prefix=VACA_PREFIX,
                                        propty='PwrState-Sts'))
        self.psconn_led.set_channels(ps_ch)

        # update buttons and self._prepared dict if not in advanced mode
        if not self._is_adv_mode:
            has_si = False
            for psn in PSSearch.get_psnames({'sec': 'SI', 'dis': 'PS'}):
                if psn not in self.pwrsupplies_tree._item_map:
                    continue
                item = self.pwrsupplies_tree._item_map[psn]
                has_si |= item.checkState(0) != 0

            if not has_si:
                self.cycle_bt.setText('8. Cycle')
                self.restore_timing_bt.setText(
                    '9. Restore Timing Initial State')
                self.cycle_trims_bt.setVisible(False)
                self.cycle_trims_lb.setVisible(False)
                self._prepared['trims'] = True
            else:
                self.cycle_bt.setText('9. Cycle')
                self.restore_timing_bt.setText(
                    '10. Restore Timing Initial State')
                self.cycle_trims_bt.setVisible(True)
                self.cycle_trims_lb.setVisible(True)
                self._prepared['trims'] = False

        self._handle_stslabels_content()
        self._handle_buttons_enabled(True)
Esempio n. 15
0
    def _set_psnames(self):
        sec = self.cb_sec.currentText()
        if sec == 'SI':
            sub = self.cb_sub.currentText()
            sub = sub if sub != 'All' else '.*'
        else:
            sub = '.*'
        dev = self.cb_dev[sec].currentText()

        self._psnames = _PSSearch.get_psnames(
            {'sec': sec, 'sub': '(?!Fam)'+sub, 'dis': 'PS', 'dev': dev})

        if self._psnames and self.sender() == self.cb_dev[sec]:
            self.magfunc = _PSSearch.conv_psname_2_magfunc(self._psnames[0])
            self.pytype = _PSSearch.conv_psname_2_pstype(self._psnames[0])
            self.matype_changed.emit(self.magfunc, self.pytype)

        self.psnames_changed.emit(self._psnames)
Esempio n. 16
0
    def _handle_checked_items_changed(self, item):
        psname = PVName(item.data(0, Qt.DisplayRole))
        if not _re.match('.*-.*:.*-.*', psname):
            return

        if not self._is_adv_mode and psname.sec == 'SI' and \
                not psname.dev.startswith('FC'):
            psname2check = Filter.process_filters(self._psnames,
                                                  filters={
                                                      'sec': 'SI',
                                                      'dev': '(?!FC)'
                                                  })
            psname2check.remove(psname)
            state2set = item.checkState(0)
            self.pwrsupplies_tree.tree.blockSignals(True)
            for psn in psname2check:
                item2check = self.pwrsupplies_tree._item_map[psn]
                if item2check.checkState(0) != state2set:
                    item2check.setData(0, Qt.CheckStateRole, state2set)
            self.pwrsupplies_tree.tree.blockSignals(False)
        else:
            if (psname.sec in ['BO', 'SI'] and psname.dev in ['B', 'B1B2']):
                psname2check = PSSearch.get_psnames({
                    'sec': psname.sec,
                    'dev': 'B.*'
                })
                psname2check.remove(psname)
                item2check = self.pwrsupplies_tree._item_map[psname2check[0]]

                state2set = item.checkState(0)
                state2change = item2check.checkState(0)
                if state2change != state2set:
                    self.pwrsupplies_tree.tree.blockSignals(True)
                    item2check.setData(0, Qt.CheckStateRole, state2set)
                    self.pwrsupplies_tree.tree.blockSignals(False)

        self._prepared.update(self._prepared_init_vals)
        self._needs_update_setup = True
Esempio n. 17
0
 def _get_ps_tree_names(self):
     # add LI, TB, BO, TS
     psnames = PSSearch.get_psnames({'sec': '(LI|TB|BO|TS)', 'dis': 'PS'})
     # add SI Fams
     psnames.extend(
         PSSearch.get_psnames({
             'sec': 'SI',
             'sub': 'Fam',
             'dis': 'PS',
             'dev': '(B.*|Q.*|S.*)'
         }))
     # add SI Corrs
     psnames.extend(
         PSSearch.get_psnames({
             'sec': 'SI',
             'sub': '[0-2][0-9].*',
             'dis': 'PS',
             'dev': '(CH|CV)'
         }))
     # add SI QTrims
     psnames.extend(
         PSSearch.get_psnames({
             'sec': 'SI',
             'sub': '[0-2][0-9].*',
             'dis': 'PS',
             'dev': '(QD.*|QF.*|Q[1-4])'
         }))
     # add SI QSkews
     psnames.extend(
         PSSearch.get_psnames({
             'sec': 'SI',
             'dis': 'PS',
             'dev': 'QS'
         }))
     # add SI Fast Corrs
     psnames.extend(
         PSSearch.get_psnames({
             'sec': 'SI',
             'dis': 'PS',
             'dev': 'FC.*'
         }))
     return psnames
Esempio n. 18
0
        def _set_ps_menu(self, sec):
            scr = 'sirius-hla-' + sec + '-ps-control.py'
            psmenu = LEVEL2M('PS', self)
            psmenu.setObjectName(sec.upper() + 'App')

            if sec == 'it':
                lens = QAction('Lens', psmenu)
                self.connect_newprocess(lens, [scr, '--device', 'lens'])
                psmenu.addAction(lens)
                return psmenu

            all_dev = QAction('All' + ('' if sec != 'si' else ' Families'),
                              psmenu)
            self.connect_newprocess(all_dev, scr)
            psmenu.addAction(all_dev)

            # dips
            if sec != 'li':
                dip = QAction('Dipoles', psmenu)
                self.connect_newprocess(dip, [scr, '--device', 'dipole'])
                psmenu.addAction(dip)
            else:
                spect = QAction('Spectrometer', psmenu)
                self.connect_newprocess(spect,
                                        [scr, '--device', 'spectrometer'])
                psmenu.addAction(spect)

            # quads
            quad = QAction('Quadrupoles', psmenu)
            self.connect_newprocess(quad, [scr, '--device', 'quadrupole'])
            psmenu.addAction(quad)

            # sext
            if sec in {'bo', 'si'}:
                sext = QAction('Sextupoles', psmenu)
                self.connect_newprocess(sext, [scr, '--device', 'sextupole'])
                psmenu.addAction(sext)

            ps_indiv = {
                'Correctors': {
                    'device': 'corrector-slow',
                    'graphs': {
                        'All': 'C(H|V)',
                        'CH': 'CH',
                        'CV': 'CV'
                    },
                },
                'Trims': {
                    'device': 'trim-quadrupole',
                    'graphs': {
                        'All': 'Q(F|D|[1-4]).*',
                        'QF': 'QF.*',
                        'QD': 'QD.*',
                        'Q1,Q2,Q3&&Q4': 'Q[1-4].*'
                    },
                },
                'Skew Quadrupoles': {
                    'device': 'skew-quadrupole',
                    'graphs': {
                        'All': 'QS'
                    },
                },
                'Fast Correctors': {
                    'device': 'corrector-fast',
                    'graphs': {
                        'All': 'FC(H|V)',
                        'FCH': 'FCH',
                        'FCV': 'FCV'
                    },
                },
            }
            if sec != 'li':
                for pstype, data in ps_indiv.items():
                    type_menu = psmenu.addMenu(pstype)
                    type_menu.setObjectName(sec.upper() + 'App')

                    if sec == 'si':
                        all_menu = type_menu.addMenu('All')
                        all_menu.setObjectName(sec.upper() + 'App')
                    elif pstype == 'Correctors':
                        all_menu = type_menu

                    # list
                    all_lst_act = QAction('List', all_menu)
                    self.connect_newprocess(all_lst_act,
                                            [scr, '--device', data['device']])
                    all_menu.addAction(all_lst_act)

                    # graphs
                    if len(data['graphs']) > 1:
                        all_gph_menu = all_menu.addMenu('Graph')
                        all_gph_menu.setObjectName(sec.upper() + 'App')
                        for label, filt in data['graphs'].items():
                            act = QAction(label, all_gph_menu)
                            self.connect_newprocess(act, [
                                'sirius-hla-as-ps-graphmon.py', '--section',
                                sec.upper(), '--device', filt
                            ])
                            all_gph_menu.addAction(act)
                    else:
                        all_gph_act = QAction('Graph', all_menu)
                        self.connect_newprocess(all_gph_act, [
                            'sirius-hla-as-ps-graphmon.py', '--section',
                            sec.upper(), '--device', data['graphs']['All']
                        ])
                        all_menu.addAction(all_gph_act)

                    if sec != 'si':
                        break

                    # subsectors
                    sec_menu = type_menu.addMenu('Subsectors')
                    sec_menu.setObjectName('SIApp')
                    for i in range(20):
                        act = sec_menu.addAction('SI-{:02d}'.format(i + 1))
                        self.connect_newprocess(act, [
                            scr, '--device', data['device'], '--subsection',
                            '{:02d}.*'.format(i + 1)
                        ])

                    # trims fams
                    if pstype != 'Trims':
                        continue

                    fam_all_menu = type_menu.addMenu('Families')
                    fam_all_menu.setObjectName('SIApp')
                    fams = PSSearch.get_psnames({
                        'sec': 'SI',
                        'sub': 'Fam',
                        'dev': 'Q(D|F|[1-4]).*'
                    })
                    for fam in fams:
                        fam = SiriusPVName(fam)
                        fam_menu = fam_all_menu.addMenu(fam.dev)
                        fam_menu.setObjectName('SIApp')
                        act1 = QAction('List', fam_menu)
                        self.connect_newprocess(
                            act1, [scr, '--device', fam, '-istrim'])
                        fam_menu.addAction(act1)
                        act2 = QAction('Graph', fam_menu)
                        self.connect_newprocess(act2, [
                            'sirius-hla-as-ps-graphmon.py', '--section', 'SI',
                            '--device', fam.dev
                        ])
                        fam_menu.addAction(act2)
            else:
                corrs = QAction('Correctors', psmenu)
                self.connect_newprocess(corrs,
                                        [scr, '--device', 'corrector-slow'])
                psmenu.addAction(corrs)
                lens = QAction('Lens', psmenu)
                self.connect_newprocess(lens, [scr, '--device', 'lens'])
                psmenu.addAction(lens)
                slnd = QAction('Solenoids', psmenu)
                self.connect_newprocess(slnd, [scr, '--device', 'solenoid'])
                psmenu.addAction(slnd)

            if sec == 'bo':
                skew = QAction('Skew Quadrupoles', psmenu)
                self.connect_newprocess(skew,
                                        [scr, '--device', 'skew-quadrupole'])
                psmenu.addAction(skew)

                wfmerr = QAction('Waveform Error', psmenu)
                self.connect_newprocess(wfmerr, 'sirius-hla-bo-ps-wfmerror.py')
                psmenu.addAction(wfmerr)

            return psmenu
Esempio n. 19
0
    def _setupUi(self):
        # Leds Panel
        cw = QWidget(self)
        panel = QWidget(cw)
        panel_lay = QGridLayout()
        panel_lay.setVerticalSpacing(0)
        panel_lay.setHorizontalSpacing(5)
        panel.setLayout(panel_lay)

        # # Leds Header
        for i, lab in enumerate([
                '', 'PS\nConn?', 'Power\nState', 'Interlock',
                'OpMode\nSlowRef?', 'Current\nDiff']):
            label = QLabel(lab, panel, alignment=Qt.AlignCenter)
            label.setStyleSheet('min-width:3.4em; max-width:3.4em;')
            panel_lay.addWidget(label, 0, i)

        # # Leds panel
        _on = _PSConst.PwrStateSts.On
        _slowref = _PSConst.States.SlowRef
        _rmpwfm = _PSConst.States.RmpWfm
        i = 2
        for sec in ['LI', 'TB', 'BO', 'TS', 'SI']:
            seclabel = QLabel('<h3>'+sec+'</h3>', panel)
            panel_lay.addWidget(seclabel, i, 0)
            i += 1
            if sec == 'LI':
                for label, filt in lips2filters.items():
                    ps_label = QLabel(
                        label, panel,
                        alignment=Qt.AlignRight | Qt.AlignVCenter)
                    psnames = PSSearch.get_psnames(filters=filt)
                    ps_c2v = dict()
                    ilk_c2v = dict()
                    conn_chs = list()
                    for name in psnames:
                        pvn = _PVName(name).substitute(prefix=self._prefix)
                        conn_chs.append(pvn.substitute(propty='PwrState-Sts'))
                        ps_c2v[pvn.substitute(propty='PwrState-Sts')] = 1
                        ilk_c2v[pvn.substitute(propty='StatusIntlk-Mon')] = \
                            {'value': _PS_LI_INTLK, 'comp': 'lt'}

                    f = 'LI-.*:PS-'+filt['dev']
                    conn_led = MyLedMultiConnection(
                        filters=f, parent=panel, channels=conn_chs)
                    ps_led = MyLedMultiChannel(
                        filters=f, parent=panel, channels2values=ps_c2v)
                    if 'Spect' in filt['dev']:
                        intlk_led = LISpectIntlkLed(panel, filters=f)
                    else:
                        intlk_led = MyLedMultiChannel(
                            filters=f, parent=panel,
                            channels2values=ilk_c2v)

                    suf = sec+filt['dev'].strip('.*')+'_led'
                    conn_led.setObjectName('conn' + suf)
                    ps_led.setObjectName('ps' + suf)
                    intlk_led.setObjectName('intlk' + suf)

                    panel_lay.addWidget(ps_label, i, 0)
                    panel_lay.addWidget(conn_led, i, 1)
                    panel_lay.addWidget(ps_led, i, 2)
                    panel_lay.addWidget(intlk_led, i, 3)
                    i += 1
            else:
                l2f = sips2filters if sec == 'SI' else asps2filters
                for label, filt in l2f.items():
                    filt['sec'] = sec
                    psnames = PSSearch.get_psnames(filters=filt)
                    if not psnames:
                        continue
                    psconn_chs = list()
                    ps_c2v = dict()
                    ilk_c2v = dict()
                    opm_c2v = dict()
                    df_c2v = dict()
                    for name in psnames:
                        pvn = _PVName(name).substitute(prefix=self._prefix)
                        ps_c2v[pvn.substitute(propty='PwrState-Sts')] = _on
                        if name.dis == 'PS':
                            psconn_chs.append(
                                pvn.substitute(propty='Version-Cte'))
                            ilk_c2v[pvn.substitute(propty='IntlkSoft-Mon')] = 0
                            ilk_c2v[pvn.substitute(propty='IntlkHard-Mon')] = 0
                            opm_pvn = pvn.substitute(propty='OpMode-Sts')
                            if sec == 'BO':
                                opm_c2v[opm_pvn] = {
                                    'value': [_slowref, _rmpwfm], 'comp': 'in'}
                            else:
                                opm_c2v[opm_pvn] = _slowref
                            df_c2v[pvn.substitute(propty='DiagStatus-Mon')] = \
                                {'value': 0, 'bit': 5}
                        elif name.dis == 'PU':
                            psconn_chs.append(
                                pvn.substitute(propty='PwrState-Sts'))
                            intlkcount = 7 if 'Sept' in name.dev else 8
                            for idx in range(1, intlkcount+1):
                                ppty = 'Intlk'+str(idx)+'-Mon'
                                pvn = pvn.substitute(propty=ppty)
                                ilk_c2v[pvn] = 1

                    f = sec+'-'+filt['sub']+':'+psnames[0].dis+'-'+filt['dev']
                    ps_label = QLabel(
                        label, panel,
                        alignment=Qt.AlignRight | Qt.AlignVCenter)
                    psconn_led = MyLedMultiConnection(
                        filters=f, parent=panel, channels=psconn_chs)
                    ps_led = MyLedMultiChannel(
                        filters=f, parent=panel, channels2values=ps_c2v)
                    intlk_led = MyLedMultiChannel(
                        filters=f, parent=panel, channels2values=ilk_c2v)

                    suf = sec+filt['dev'].strip('.*')+'_led'
                    psconn_led.setObjectName('psconn' + suf)
                    ps_led.setObjectName('ps' + suf)
                    intlk_led.setObjectName('intlk' + suf)

                    panel_lay.addWidget(ps_label, i, 0)
                    panel_lay.addWidget(psconn_led, i, 1)
                    panel_lay.addWidget(ps_led, i, 2)
                    panel_lay.addWidget(intlk_led, i, 3)

                    if psnames[0].dis == 'PS':
                        opm_led = MyLedMultiChannel(
                            filters=f, parent=panel,
                            channels2values=opm_c2v)
                        opm_led.setOnColor(PyDMLed.LightGreen)
                        opm_led.setOffColor(PyDMLed.Yellow)
                        diff_led = MyLedMultiChannel(
                            filters=f, parent=panel,
                            channels2values=df_c2v)

                        opm_led.setObjectName('opm' + suf)
                        diff_led.setObjectName('diff' + suf)

                        panel_lay.addWidget(opm_led, i, 4)
                        panel_lay.addWidget(diff_led, i, 5)

                    i += 1
            panel_lay.addItem(QSpacerItem(1, 10, QSzPlcy.Ignored,
                              QSzPlcy.MinimumExpanding), i, 0)
            i += 1

        # Current State and Log Tables
        table_label2px = {
            'Date': 110,
            'Time': 85,
            'Type': 70,
            'PS Name': 145,
            'Property': 85,
            'Value': 120}

        channels = list()
        for ps in PSSearch.get_psnames(filters={'dis': 'PS'}):
            channels.append(_PVName(ps).substitute(
                prefix=self._prefix, propty='DiagCurrentDiff-Mon'))
            channels.append(_PVName(ps).substitute(
                prefix=self._prefix, propty='OpMode-Sts'))
        self._status = LogTable(cw, channels, table_label2px, is_status=True)
        self._status.setObjectName('status_table')
        self._status.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self._status.updated.connect(self._filter_table)
        self._log = LogTable(cw, channels, table_label2px)
        self._log.setObjectName('log_table')
        self._log.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
        self._tables_stack = QStackedLayout()
        self._tables_stack.addWidget(self._status)
        self._tables_stack.addWidget(self._log)

        self._rb_status = QRadioButton('Status', self)
        self._rb_status.setObjectName('rb_status')
        self._rb_status.setChecked(True)
        self._visible_table = self._status
        self._rb_status.toggled.connect(_partial(self._toggle_table, 0))
        self._rb_log = QRadioButton('Log', self)
        self._rb_log.setObjectName('rb_log')
        self._rb_log.toggled.connect(_partial(self._toggle_table, 1))

        for name, width in table_label2px.items():
            attr = '_search_'+name.replace(' ', '').lower()
            setattr(self, attr, QLineEdit())
            le = getattr(self, attr)
            le.setObjectName(name)
            le.setPlaceholderText(name + '...')
            le.editingFinished.connect(self._filter_table)
            width = str(width-1)
            if name == 'Value':
                le.setStyleSheet(
                    '#'+name+'{min-width:'+width+'px;}')
                le.setSizePolicy(QSzPlcy.Expanding, QSzPlcy.Maximum)
            else:
                le.setStyleSheet(
                    '#'+name+'{min-width:'+width+'px; max-width:'+width+'px;}')
                le.setSizePolicy(QSzPlcy.Maximum, QSzPlcy.Maximum)

        self._scrollup_pb = QPushButton('↟', cw)
        self._scrollup_pb.setObjectName('scrollup_pb')
        self._scrollup_pb.clicked.connect(self._arrange_table)

        self._scrolldown_pb = QPushButton('↡', cw)
        self._scrolldown_pb.setObjectName('scrolldown_pb')
        self._scrolldown_pb.clicked.connect(self._arrange_table)

        tables_lay = QGridLayout()
        tables_lay.setVerticalSpacing(2)
        tables_lay.setHorizontalSpacing(0)
        tables_lay.addWidget(self._search_date, 0, 0)
        tables_lay.addWidget(self._search_time, 0, 1)
        tables_lay.addWidget(self._search_type, 0, 2)
        tables_lay.addWidget(self._search_psname, 0, 3)
        tables_lay.addWidget(self._search_property, 0, 4)
        tables_lay.addWidget(self._search_value, 0, 5)
        tables_lay.addWidget(self._scrollup_pb, 0, 6, alignment=Qt.AlignRight)
        tables_lay.addLayout(self._tables_stack, 1, 0, 1, 7)
        tables_lay.addWidget(self._rb_status, 2, 0, alignment=Qt.AlignLeft)
        tables_lay.addWidget(self._rb_log, 2, 1, alignment=Qt.AlignLeft)
        tables_lay.addWidget(self._scrolldown_pb, 2, 6,
                             alignment=Qt.AlignRight)
        tables = QWidget(cw)
        tables.setObjectName('tables')
        tables.setLayout(tables_lay)

        # Connect signals
        for led in self.findChildren(QLed):
            led.shape = PyDMLed.ShapeMap.Round
            led.filterlog.connect(self._filter_table)
            led.warning.connect(self._log.add_log_slot)
            led.warning.connect(self._status.add_log_slot)
            led.normal.connect(self._status.remove_log_slot)

        # Layout
        window_title = QLabel('<h2>Power Supplies Diagnostics</h2>', cw,
                              alignment=Qt.AlignCenter)
        layout = QGridLayout()
        layout.setVerticalSpacing(20)
        layout.setHorizontalSpacing(5)
        layout.addWidget(window_title, 0, 0, 1, 2)
        layout.addWidget(panel, 1, 0)
        layout.addWidget(tables, 1, 1)

        cw.setStyleSheet("""
            #scrollup_pb, #scrolldown_pb{
                max-height: 1em;
                max-width: 0.7em;
                color: #464646;
            }
            QLineEdit{
                max-height: 1em;
            }
            #status_table, #log_table{
                border: 1px solid #bebebe;
            }
            #tables{
                min-width: 700px;
            }
            #rb_status, #rb_log{
                min-width: 5em;
                max-width: 5em;
                max-height: 1em;
            }""")
        cw.setLayout(layout)
        self.setCentralWidget(cw)
def select_psnames(psgroup):
    """."""
    # select only PS
    allps = []
    for ps in PSSearch.get_psnames():
        if ':PS-' in ps:
            allps.append(ps)
    psnames = []
    if psgroup.lower() == 'all':
        psnames += allps
    elif psgroup in allps:
        psnames.append(psgroup)
    elif psgroup.lower() == 'tb-dipole' or psgroup.lower() == 'tb-dipoles':
        for ps in allps:
            if 'TB-Fam' in ps and 'PS-B' in ps:
                psnames.append(ps)
    elif psgroup.lower() == 'tb-correctors':
        for ps in allps:
            if 'TB' in ps and ('PS-CH' in ps or 'PS-CV' in ps):
                psnames.append(ps)
    elif psgroup.lower() == 'tb-quadrupoles':
        for ps in allps:
            if 'TB' in ps and ('PS-QF' in ps or 'PS-QD' in ps):
                psnames.append(ps)
    elif psgroup.lower() == 'tb':
        for ps in allps:
            if ps.startswith('TB-'):
                psnames.append(ps)
    elif psgroup.lower() == 'bo-dipoles':
        for ps in allps:
            if 'BO-Fam' in ps and 'PS-B' in ps:
                psnames.append(ps)
    elif psgroup.lower() == 'bo-quadrupoles':
        for ps in allps:
            if 'BO-' in ps and \
               ('PS-QF' in ps or 'PS-QD' in ps or 'PS-QS' in ps):
                psnames.append(ps)
    elif psgroup.lower() == 'bo-sextupoles':
        for ps in allps:
            if 'BO-Fam' in ps and ('PS-SF' in ps or 'PS-SD' in ps):
                psnames.append(ps)
    elif psgroup.lower() == 'bo-correctors':
        for ps in allps:
            if 'BO-' in ps and \
               ('PS-CH' in ps or 'PS-CV' in ps or 'PS-QS' in ps):
                psnames.append(ps)
    elif psgroup.lower() == 'bo':
        for ps in allps:
            if ps.startswith('BO-'):
                psnames.append(ps)
    elif psgroup.lower() in ('li-dipole', 'li-spectrometer'):
        for ps in allps:
            if ps.startswith('LI-01:PS-Spect'):
                psnames.append(ps)
    elif psgroup.lower() in ('li-quadrupoles', ):
        for ps in allps:
            if ':PS-QD' in ps or ':PS-QF' in ps:
                psnames.append(ps)
    elif psgroup.lower() in ('li-magnetic-lenses', ):
        for ps in allps:
            if ':PS-Lens' in ps:
                psnames.append(ps)
    elif psgroup.lower() in ('li-correctors', ):
        for ps in allps:
            if ':PS-CH' in ps or ':PS-CV':
                psnames.append(ps)
    elif psgroup.lower() in ('li-solenoids', ):
        for ps in allps:
            if ':PS-Slnd' in ps:
                psnames.append(ps)
    elif psgroup.lower() == 'li':
        for ps in allps:
            if ps.startswith('LI-01:'):
                psnames.append(ps)
    return psnames
    for ps in pss:
        print('    {}'.format(ps))
    amais = pss - trigs[trig]
    for name in amais:
        print('    a mais: {}'.format(name))
    amenos = trigs[trig] - pss
    for name in amenos:
        print('    a menos: {}'.format(name))


if __name__ == '__main__':

    pss = PSSearch.get_psnames({
        'sec': 'BO',
        'dis': 'PS',
        'sub': '[0-9]{2}.*',
    })
    pss.extend(
        PSSearch.get_psnames({
            'sec': 'SI',
            'dis': 'PS',
            'sub': '[0-9]{2}.*',
            'dev': '[QC]'
        }))

    trigs = dict()
    for i, ps in enumerate(pss):
        chan = ps.substitute(propty_name='BCKPLN')
        trig = LLTimeSearch.get_trigger_name(chan)
        if trig in trigs: