Example #1
0
class TriggeredAcquisition(BaseWidget):
    def __init__(self, parent=None, prefix='', bpm=''):
        super().__init__(parent=parent, prefix=prefix, bpm=bpm)
        self.setupui()
        mode = SiriusConnectionSignal(self.get_pvname('ACQBPMMode-Sts'))
        mode.new_value_signal[int].connect(self.toggle_multi_single)
        self._chans.append(mode)

    def setupui(self):
        vbl = QGridLayout(self)
        lab = QLabel('<h2>' + self.bpm + ' Triggered Acquisitions</h2>')
        lab.setAlignment(Qt.AlignCenter)
        vbl.addWidget(lab, 0, 0, 1, 2)
        self.stack = QStackedLayout()
        multi_pass = MultiTurnData(parent=self,
                                   acq_type='ACQ',
                                   prefix=self.prefix,
                                   bpm=self.bpm)
        multi_pass.setObjectName('multi_pass')
        single_pass = SinglePassData(parent=self,
                                     prefix=self.prefix,
                                     bpm=self.bpm)
        single_pass.setObjectName('single_pass')

        self.stack.addWidget(multi_pass)
        self.stack.addWidget(single_pass)
        vbl.addLayout(self.stack, 1, 0)
        config = ACQTrigConfigs(parent=self,
                                prefix=self.prefix,
                                bpm=self.bpm,
                                data_prefix='ACQ')
        config.setObjectName('config')
        vbl.addWidget(config, 1, 1)

        self.setStyleSheet("""
            #multi_pass{
                min-width:50em;
                min-height:48em;}
            #single_pass{
                min-width:50em;
                min-height:48em;}
            #config{
                min-height:21em;}""")

    def toggle_multi_single(self, modeidx):
        self.stack.setCurrentIndex(modeidx)
Example #2
0
class MainApp(QWidget):
    LANDSCAPE = 0
    PORTRAIT = 1

    stop_signal = Signal()
    quality_changed = Signal(str)
    style_changed = Signal(object)
    last_frame_changed = Signal(object)

    def __init__(self):
        QWidget.__init__(self)

        self.styles = load_styles()
        self.image = StyledCapture(QImage(256, 256, QImage.Format_RGB888),
                                   '')  # placeholder
        self.freeze = None
        if isinstance(settings.CAPTURE_HANDLER, string_types):
            self.capture_handler = locate(settings.CAPTURE_HANDLER)
        else:
            self.capture_handler = settings.CAPTURE_HANDLER
        self.setup_ui()

        self.frame_grabber = FrameGrabber(settings.SIZES[0])
        self.frame_thread = QThread()
        # self.frame_grabber.image_signal.connect(self.display_frame)
        self.frame_grabber.last_frame_signal.connect(self.last_frame)
        self.frame_grabber.moveToThread(self.frame_thread)
        self.frame_thread.started.connect(self.frame_grabber.grab)
        self.stop_signal.connect(self.frame_grabber.stop_work)
        self.quality_changed.connect(self.frame_grabber.change_size)
        self.frame_thread.start()

        self.image_processor = ImageProcessor(self.styles[0])
        self.image_thread = QThread()
        self.image_processor.image_signal.connect(self.display_frame)
        self.image_processor.moveToThread(self.image_thread)
        self.image_thread.started.connect(self.image_processor.monitor_images)
        self.stop_signal.connect(self.image_processor.stop_work)
        self.style_changed.connect(self.image_processor.change_style)
        self.last_frame_changed.connect(self.image_processor.change_last_frame)
        self.image_thread.start()

    def closeEvent(self, event):
        self.stop_signal.emit()
        self.frame_thread.quit()
        self.image_thread.quit()
        self.frame_thread.wait()
        self.image_thread.wait()

    def setup_ui(self):
        """Initialize widgets."""
        def switch_style(i):
            view = self.landscape_view if self.view_mode == MainApp.LANDSCAPE else self.portrait_view
            self.style_changed.emit(self.styles[i])
            view.selected_style = self.styles[i]

        for i in range(min(len(self.styles), len(settings.STYLE_SHORTCUTS))):
            QShortcut(QKeySequence(settings.STYLE_SHORTCUTS[i]),
                      self,
                      lambda x=i: switch_style(x))

        self.landscape_view = LandscapeView(self.styles)
        self.landscape_view.style_changed.connect(self.style_button_clicked)
        self.landscape_view.toggle_fullscreen_signal.connect(
            self.toggle_fullscreen)
        self.landscape_view.quality_changed.connect(self.quality_choice)
        self.portrait_view = PortraitView(self.styles)
        self.portrait_view.style_changed.connect(self.style_button_clicked)
        self.portrait_view.toggle_fullscreen_signal.connect(
            self.toggle_fullscreen)
        self.portrait_view.quality_changed.connect(self.quality_choice)

        self.main_layout = QStackedLayout()
        self.main_layout.addWidget(self.landscape_view)
        self.main_layout.addWidget(self.portrait_view)
        self.setLayout(self.main_layout)

        self.view_mode = MainApp.LANDSCAPE

        self.setStyleSheet('background-color:black;'
                           'font-family: Arial;'
                           'font-style: normal;'
                           'font-size: 12pt;'
                           'font-weight: bold;'
                           'color:white;')
        self.setWindowTitle('Stylize')

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Escape and not settings.KIOSK:
            if self.windowState() & Qt.WindowFullScreen:
                self.showNormal()
        elif event.key() == Qt.Key_Enter or event.key() == Qt.Key_Return:
            self.image_capture()

    def last_frame(self, frame):
        self.last_frame_changed.emit(frame)

    def display_frame(self, image):
        self.image = image
        if not self.freeze:
            if self.view_mode == MainApp.LANDSCAPE:
                self.landscape_view.set_image(self.image.image)
            else:
                self.portrait_view.set_image(self.image.image)

    def resizeEvent(self, event):
        super(MainApp, self).resizeEvent(event)
        new_view_mode = MainApp.LANDSCAPE if self.width() >= self.height(
        ) else MainApp.PORTRAIT

        if self.view_mode != new_view_mode:
            old_view = self.portrait_view if new_view_mode == MainApp.LANDSCAPE else self.landscape_view
            new_view = self.landscape_view if new_view_mode == MainApp.LANDSCAPE else self.portrait_view

            new_view.quality = old_view.quality
            new_view.selected_style = old_view.selected_style

            self.view_mode = new_view_mode
            self.main_layout.setCurrentIndex(self.view_mode)

    def style_button_clicked(self, style):
        self.style_changed.emit(style)

    def toggle_fullscreen(self):
        if self.windowState() & Qt.WindowFullScreen:
            self.showNormal()
        else:
            self.showFullScreen()

    def quality_choice(self, quality):
        self.quality_changed.emit(quality)

    def image_capture(self):
        self.freeze = self.image.copy()  # prevent background update
        try:
            self.capture_handler(self, self.freeze)
        except Exception:
            msg = QMessageBox(self)
            msg.setIcon(QMessageBox.Critical)
            msg.setText('Error during capture.')
            msg.setWindowFlags(Qt.FramelessWindowHint | Qt.Popup)
            msg.exec_()

        self.freeze = None
Example #3
0
class PSDiag(SiriusMainWindow):
    """Power Supply Diagnostic."""

    def __init__(self, parent=None, prefix=VACA_PREFIX):
        """Init."""
        super().__init__(parent)
        self._prefix = prefix
        self.setWindowTitle('PS Diagnostics')
        self.setObjectName('ASApp')
        cor = _get_appropriate_color(section='AS')
        self.setWindowIcon(qta.icon('mdi.stethoscope', color=cor))
        self._setupUi()
        self._initialized = False

    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 _arrange_table(self):
        text = self.sender().text()
        if '↟' in text:
            self._visible_table.scrollToTop()
        elif '↡' in text:
            self._visible_table.scrollToBottom()

    def _filter_table(self, text=''):
        # identify first user interaction
        if isinstance(self.sender(), (QLineEdit, QLed)):
            self._initialized = True
        # ignore initializing
        if not self._initialized:
            return
        # set led's filter
        if isinstance(self.sender(), QLed):
            self.blockSignals(True)
            self._search_psname.setText(text)
            self.blockSignals(False)

        # get search filters
        pats = list()
        date_txt = self._search_date.text()
        time_txt = self._search_time.text()
        logtype_txt = self._search_type.text()
        psname_txt = self._search_psname.text()
        property_txt = self._search_property.text()
        value_txt = self._search_value.text()
        try:
            if date_txt:
                pats.append([_re.compile(date_txt, _re.I), 0])
            if time_txt:
                pats.append([_re.compile(time_txt, _re.I), 1])
            if logtype_txt:
                pats.append([_re.compile(logtype_txt, _re.I), 2])
            if psname_txt:
                pats.append([_re.compile(psname_txt, _re.I), 3])
            if property_txt:
                pats.append([_re.compile(property_txt, _re.I), 4])
            if value_txt:
                pats.append([_re.compile(value_txt, _re.I), 5])
        except Exception:
            return

        m = self._visible_table.model()
        for row in range(m.rowCount()):
            for pat, col in pats:
                if not pat.search(m.data(m.index(row, col))):
                    self._visible_table.setRowHidden(
                        row, self._visible_table.rootIndex(), True)
                    break
            else:
                self._visible_table.setRowHidden(
                    row, self._visible_table.rootIndex(), False)

    def _toggle_table(self, i, toggle):
        if not toggle:
            return

        self._tables_stack.setCurrentIndex(i)
        if i == 0:
            self._log.updated.disconnect(self._filter_table)
            self._status.updated.connect(self._filter_table)
            self._visible_table = self._status
        else:
            self._status.updated.disconnect(self._filter_table)
            self._log.updated.connect(self._filter_table)
            self._visible_table = self._log
        self._filter_table()