Source code for siriushla.as_ti_control.low_level_devices

"""."""
import logging as _log
import numpy as _np
from datetime import datetime as _datetime

from qtpy.QtCore import Qt, Slot
from qtpy.QtGui import QColor, QBrush
from qtpy.QtWidgets import QLabel, QPushButton, QGroupBox, QVBoxLayout, \
    QHBoxLayout, QGridLayout, QMenuBar, QSplitter, QTabWidget, QWidget, \
    QSizePolicy as QSzPol, QCheckBox, QFrame
import qtawesome as qta
from pydm.widgets import PyDMLineEdit, PyDMPushButton

from siriuspy.search import LLTimeSearch, HLTimeSearch
from siriuspy.namesys import SiriusPVName as _PVName
from siriuspy.timesys import csdev as _cstime
from siriuspy.epics import PV as _PV

from ..widgets import PyDMLed, PyDMStateButton, SiriusLedState, \
    SiriusEnumComboBox, SiriusLedAlert, SiriusLabel, \
    SiriusSpinbox, SiriusConnectionSignal, \
    SiriusPushButton, SiriusWaveformPlot
from ..widgets.windows import create_window_from_widget, SiriusDialog
from ..util import connect_window, get_appropriate_color

from .base import BaseList, BaseWidget
from .allowed_buckets import AllowedBucketsMatrix


# ###################### Event Generator ######################
[docs] class BucketListLineEdit(PyDMLineEdit):
[docs] def value_changed(self, value): super().value_changed(value) self.channeltype = _np.ndarray self.subtype = int
[docs] class BucketListLabel(SiriusLabel):
[docs] def value_changed(self, value): maxele = 20 if isinstance(value, _np.ndarray): zeros = _np.where(value == 0)[0] if zeros.size > 0: value = value[:zeros[0]] txt = '[ ' + ' '.join([str(i) for i in value[:maxele]]) txt += ' ...]' if value.size > maxele else ']' self.setText(txt) else: super().value_changed(value)
[docs] class EVG(BaseWidget): """Template for control of High Level Triggers.""" def __init__(self, parent=None, prefix='', device=''): """Initialize object.""" super().__init__(parent, prefix=prefix) self.device = _PVName(device or LLTimeSearch.get_evg_name()) self.setupui() self.setObjectName('ASApp')
[docs] def setupui(self): mylayout = QGridLayout(self) mylayout.setHorizontalSpacing(20) mylayout.setVerticalSpacing(20) mylayout.addWidget(self._setupmenus(), 0, 0, 1, 2) lab = QLabel('<h1>' + self.device.device_name + '</h1>', self) mylayout.addWidget(lab, 1, 0, 1, 2) mylayout.setAlignment(lab, Qt.AlignCenter) # status self.status_wid = QGroupBox('Status', self) mylayout.addWidget(self.status_wid, 2, 0) self._setup_status_wid() # configurations conftab = QTabWidget(self) conftab.setObjectName('ASTab') conftab.setSizePolicy(QSzPol.Preferred, QSzPol.Maximum) mylayout.addWidget(conftab, 2, 1) confwid = QWidget() conflay = QVBoxLayout(confwid) maintab = QTabWidget(self) maintab.setObjectName('ASTab') maintab.setStyleSheet(""" QTabWidget::pane{ border-left: 2px solid gray; border-bottom: 2px solid gray; border-right: 2px solid gray; }""") self.configs_wid = self._setup_configs_wid() maintab.addTab(self.configs_wid, 'Main') self.info_wid = self._setup_info_wid() maintab.addTab(self.info_wid, 'Fw && IOC') conflay.addWidget(maintab) self.bucketlist_wid = BucketList(self, self.device, self.prefix) conflay.addWidget(self.bucketlist_wid) conflay.setContentsMargins(0, 6, 0, 0) conftab.addTab(confwid, 'Configurations') # interlock map self.intlkmap_wid = self._setup_intlkmap_wid() conftab.addTab(self.intlkmap_wid, 'Interlock Map') # outtab splitter = QSplitter(Qt.Horizontal) splitter.setContentsMargins(0, 0, 0, 0) splitter.setHandleWidth(20) mylayout.addWidget(splitter, 3, 0, 1, 2) obj_names = [ self.device.substitute(propty=dev) for dev in sorted(_cstime.Const.EvtLL._fields) if 0 < int(dev[3:]) < 64] self.events_wid = EventList( name='Events', parent=self, prefix=self.prefix, obj_names=obj_names) splitter.addWidget(self.events_wid) obj_names = [self.device.substitute(propty=dev) for dev in sorted(_cstime.Const.ClkLL._fields)] self.clocks_wid = ClockList( name='Clocks', parent=self, prefix=self.prefix, obj_names=obj_names, has_search=True) splitter.addWidget(self.clocks_wid) splitter.setSizePolicy(QSzPol.Preferred, QSzPol.MinimumExpanding)
def _setupmenus(self): main_menu = QMenuBar() main_menu.setNativeMenuBar(False) try: fouts = LLTimeSearch.get_evg2fout_mapping() except KeyError: return main_menu menu = main_menu.addMenu('&Downlinks') for out, down in sorted(fouts.items()): action = menu.addAction(out + ' --> ' + down) icon = qta.icon('mdi.timer', color=get_appropriate_color('AS')) Win = create_window_from_widget(FOUT, title=down, icon=icon) connect_window(action, Win, None, device=down, prefix=self.prefix) return main_menu def _setup_configs_wid(self): configs_wid = QWidget() lay = QGridLayout(configs_wid) # general configs pvname = self.get_pvname(propty='DevEnbl-Sel') sp = PyDMStateButton(self, init_channel=pvname) pvname = self.get_pvname(propty='DevEnbl-Sts') rb = PyDMLed(self, init_channel=pvname) pg = self._create_prop_widget('Dev Enable', configs_wid, (sp, rb)) lay.addWidget(pg, 0, 0, alignment=Qt.AlignCenter) pvname = self.get_pvname(propty='UpdateEvt-Cmd') sp = PyDMPushButton(self, init_channel=pvname, 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;}') pvname = self.get_pvname(propty='EvtSyncStatus-Mon') rb = SiriusLedState(self, init_channel=pvname) rb.offColor = rb.Red pg = self._create_prop_widget('Update Evts', configs_wid, (sp, rb)) lay.addWidget(pg, 0, 1, alignment=Qt.AlignCenter) pvname = self.get_pvname(propty='ContinuousEvt-Sel') sp = PyDMStateButton(self, init_channel=pvname) pvname = self.get_pvname(propty='ContinuousEvt-Sts') rb = SiriusLedState(self, init_channel=pvname) pg = self._create_prop_widget('Continuous', configs_wid, (sp, rb)) lay.addWidget(pg, 0, 2, alignment=Qt.AlignCenter) pvname = self.get_pvname(propty='InjectionEvt-Sel') sp = PyDMStateButton(self, init_channel=pvname) pvname = self.get_pvname(propty='InjectionEvt-Sts') rb = SiriusLedState(self, init_channel=pvname) pg = self._create_prop_widget('Injection', configs_wid, (sp, rb)) lay.addWidget(pg, 0, 3, alignment=Qt.AlignCenter) pvname = self.get_pvname(propty='InjRate-SP') sp = SiriusSpinbox(self, init_channel=pvname) pvname = self.get_pvname(propty='InjRate-RB') rb = SiriusLabel(self, init_channel=pvname) pg = self._create_prop_widget('Pulse Rate [Hz]', configs_wid, (sp, rb)) lay.addWidget(pg, 0, 4, alignment=Qt.AlignCenter) # ac line configs pvname = self.get_pvname(propty='ACEnbl-Sel') sp = PyDMStateButton(self, init_channel=pvname) pvname = self.get_pvname(propty='ACEnbl-Sts') rb = SiriusLedState(self, init_channel=pvname) pg = self._create_prop_widget('AC Enable', configs_wid, (sp, rb)) lay.addWidget(pg, 1, 0, alignment=Qt.AlignCenter) pvname = self.get_pvname(propty='ACStatus-Mon') mon = SiriusLedState(self, init_channel=pvname) mon.offColor = rb.Red pg = self._create_prop_widget('AC Status', configs_wid, (mon,)) lay.addWidget(pg, 1, 1, alignment=Qt.AlignCenter) pvname = self.get_pvname(propty='ACSrc-Sel') sp = SiriusEnumComboBox(self, init_channel=pvname) pvname = self.get_pvname(propty='ACSrc-Sts') rb = SiriusLabel(self, init_channel=pvname) pg = self._create_prop_widget('AC Source', configs_wid, (sp, rb)) lay.addWidget(pg, 1, 2, alignment=Qt.AlignCenter) # rf configs pvname = self.get_pvname(propty='RFReset-Cmd') sp = PyDMPushButton(self, init_channel=pvname, pressValue=1) sp.setIcon(qta.icon('fa5s.sync')) sp.setToolTip('Reset RF Status') sp.setObjectName('but') sp.setStyleSheet( '#but{min-width:25px; max-width:25px; icon-size:20px;}') pvname = self.get_pvname(propty='RFStatus-Mon') rb = SiriusLedState(self, init_channel=pvname) rb.offColor = rb.Red pg = self._create_prop_widget('RF Status', configs_wid, (sp, rb)) lay.addWidget(pg, 1, 3, alignment=Qt.AlignCenter) pvname = self.get_pvname(propty='RFDiv-SP') sp = SiriusSpinbox(self, init_channel=pvname) pvname = self.get_pvname(propty='RFDiv-RB') rb = SiriusLabel(self, init_channel=pvname) pg = self._create_prop_widget('RF Divisor', configs_wid, (sp, rb)) lay.addWidget(pg, 1, 4, alignment=Qt.AlignCenter) return configs_wid def _setup_status_wid(self): status_layout = QGridLayout(self.status_wid) status_layout.setHorizontalSpacing(30) status_layout.setVerticalSpacing(5) pvname = self.get_pvname(propty='STATEMACHINE') rb1 = SiriusLabel(self.status_wid, init_channel=pvname) pvname = self.get_pvname(propty='DevStatus-Mon') rb2 = SiriusLabel(self.status_wid, init_channel=pvname) hlay = QHBoxLayout() hlay.addStretch() hlay.addWidget(rb1) hlay.addStretch() hlay.addWidget(rb2) hlay.addStretch() status_layout.addItem(hlay, 0, 0, 1, 3) status_layout.setAlignment(hlay, Qt.AlignCenter) hlay = QHBoxLayout() wid = QWidget(self.status_wid) wid.setLayout(QHBoxLayout()) wid.layout().setContentsMargins(0, 0, 0, 0) pvname = self.get_pvname(propty='TotalInjCount-Mon') pydmlab1 = SiriusLabel(self.status_wid, init_channel=pvname) pydmlab1.setStyleSheet('min-width:5em;') pydmlab1.setAlignment(Qt.AlignRight | Qt.AlignVCenter) pvname = self.get_pvname(propty='InjCount-Mon') pydmlab2 = SiriusLabel(self.status_wid, init_channel=pvname) pydmlab2.setAlignment(Qt.AlignCenter) lab1 = QLabel( '(', self.status_wid, alignment=Qt.AlignRight | Qt.AlignVCenter) lab2 = QLabel( ')', self.status_wid, alignment=Qt.AlignLeft | Qt.AlignVCenter) wid.layout().addStretch() wid.layout().addWidget(pydmlab1) wid.layout().addWidget(lab1) wid.layout().addWidget(pydmlab2) wid.layout().addWidget(lab2) wid.layout().addStretch() hlay.addWidget(self._create_prop_widget( '<b>Inj Count: All (Now)</b>', self.status_wid, (wid, ))) wid = QWidget(self.status_wid) wid.setLayout(QHBoxLayout()) wid.layout().setContentsMargins(0, 0, 0, 0) pvname = self.get_pvname(propty='SeqStatus-Mon') pydmlab1 = SiriusLabel(self.status_wid, init_channel=pvname) pydmlab1.setAlignment(Qt.AlignRight | Qt.AlignVCenter) pvname = self.get_pvname(propty='SeqCount-SP') pydmlab2 = SiriusLabel(self.status_wid, init_channel=pvname) lab1 = QLabel( '(', self.status_wid, alignment=Qt.AlignRight | Qt.AlignVCenter) lab2 = QLabel( ')', self.status_wid, alignment=Qt.AlignLeft | Qt.AlignVCenter) wid.layout().addStretch() wid.layout().addWidget(pydmlab1) wid.layout().addWidget(lab1) wid.layout().addWidget(pydmlab2) wid.layout().addWidget(lab2) wid.layout().addStretch() hlay.addWidget(self._create_prop_widget( '<b>Sequence: Table (Count)</b>', self.status_wid, (wid, ))) status_layout.addItem(hlay, 1, 0, 1, 3) lb = QLabel("<b>Alive</b>") pvname = self.get_pvname(propty='Alive-Mon') rb = SiriusLabel(self, init_channel=pvname) gb = self._create_small_group('', self.status_wid, (lb, rb)) status_layout.addWidget(gb, 2, 0) lb = QLabel("<b>Network</b>") pvname = self.get_pvname(propty='Network-Mon') rb = SiriusLedAlert(self, init_channel=pvname) on_c, off_c = rb.onColor, rb.offColor rb.offColor = on_c rb.onColor = off_c gb = self._create_small_group('', self.status_wid, (lb, rb)) status_layout.addWidget(gb, 2, 1) lb = QLabel("<b>RF Sts</b>") pvname = self.get_pvname(propty='RFStatus-Mon') rb = SiriusLedAlert(self, init_channel=pvname) on_c, off_c = rb.onColor, rb.offColor rb.offColor = on_c rb.onColor = off_c gb = self._create_small_group('', self.status_wid, (lb, rb)) status_layout.addWidget(gb, 2, 2) wids = list() try: conn = LLTimeSearch.get_connections_from_evg() conn = {int(dev.propty[-1]) for dev in conn if dev.dev == 'EVG'} except KeyError: conn = set() for i in range(8): pvname = self.get_pvname(propty='DownlinkStatus-Mon') if i in conn: rb = SiriusLedAlert(self, init_channel=pvname, bit=i) else: rb = SiriusLedState(self, init_channel=pvname, bit=i) rb.onColor = rb.DarkGreen rb.offColor = rb.LightGreen wids.append(rb) but = QPushButton(self) but.setToolTip('Open Down Connections Details') but.setIcon(qta.icon('fa5s.ellipsis-v')) but.setObjectName('but') but.setDefault(False) but.setAutoDefault(False) but.setStyleSheet( '#but{min-width:15px; max-width:15px;\ min-height:25px; max-height:25px;\ icon-size:20px;}') but.clicked.connect(self._open_downconn_dialog) wids.append(but) pvname = self.get_pvname(propty='RxLockedLtcRst-Cmd') pbt = SiriusPushButton( self, init_channel=pvname, pressValue=1, label='', icon=qta.icon('fa5s.sync')) wids.append(pbt) gb = self._create_small_group( 'Down Connection', self.status_wid, wids, align_ver=False) status_layout.addWidget(gb, 3, 0, 1, 3) def _setup_info_wid(self): info_wid = QWidget() lay = QGridLayout(info_wid) lb = QLabel("<b>IP</b>") pvname = self.get_pvname(propty='IPAddr-Mon') addr = SiriusLabel(self, init_channel=pvname) pvname = self.get_pvname(propty='IPPort-Mon') port = SiriusLabel(self, init_channel=pvname) gb = self._create_small_group('', info_wid, (lb, addr, port)) lay.addWidget(gb, 0, 0, alignment=Qt.AlignHCenter) lb = QLabel("<b>DevFun</b>") pvname = self.get_pvname(propty='DevFun-Sel') sp = SiriusEnumComboBox(self, init_channel=pvname) pvname = self.get_pvname(propty='DevFun-Sts') rb = SiriusLabel(self, init_channel=pvname) gb = self._create_small_group('', info_wid, (lb, sp, rb)) lay.addWidget(gb, 0, 1, alignment=Qt.AlignHCenter) lb = QLabel("<b>Device Status</b>") pvname = self.get_pvname(propty='DevStatus-Mon') rb = SiriusLabel(self, init_channel=pvname) gb = self._create_small_group('', info_wid, (lb, rb)) lay.addWidget(gb, 0, 2, alignment=Qt.AlignHCenter) lb = QLabel("<b>FPGA Clk</b>") pvname = self.get_pvname('FPGAClk-Cte') mon = SiriusLabel(self, init_channel=pvname) mon.showUnits = True mon.precisionFromPV = False mon.precision = 3 gb = self._create_small_group('', info_wid, (lb, mon)) lay.addWidget(gb, 0, 3, alignment=Qt.AlignCenter) lb = QLabel("<b>Download</b>") pvname = self.get_pvname('Download-Cmd') sp = SiriusPushButton( self, label='', icon=qta.icon('fa5s.download'), pressValue=1, releaseValue=0, init_channel=pvname) # ? gb = self._create_small_group('', info_wid, (lb, sp)) lay.addWidget(gb, 1, 0, alignment=Qt.AlignHCenter) lb = QLabel("<b>Save Settings</b>") pvname = self.get_pvname('Save-Cmd') sp = PyDMPushButton( self, label='Save', init_channel=pvname, pressValue=1) # ? gb = self._create_small_group('', info_wid, (lb, sp)) lay.addWidget(gb, 1, 1, alignment=Qt.AlignHCenter) lb = QLabel("<b>RF Ref.</b>") pvname = self.get_pvname('RFRef-Mon') mon = SiriusLabel(self, init_channel=pvname) mon.showUnits = True pvname = self.get_pvname('RFRef-Mon', field='INP') inp = PyDMLineEdit(self, init_channel=pvname) gb = self._create_small_group('', info_wid, (lb, mon, inp)) lay.addWidget(gb, 1, 2, alignment=Qt.AlignHCenter) lb = QLabel("<b>Fw.Version</b>") pvname = self.get_pvname(propty='FwVersion-Cte.SVAL') frmv = SiriusLabel(self, init_channel=pvname) gb = self._create_small_group('', info_wid, (lb, frmv)) gb.layout().setSpacing(3) lay.addWidget(gb, 1, 3, alignment=Qt.AlignHCenter) but = QPushButton(self) but.setToolTip('Open Timestamp Controls') but.setIcon(qta.icon('fa5s.ellipsis-v')) but.setObjectName('but') but.setStyleSheet( '#but{min-width:25px; max-width:25px;\ min-height:25px; max-height:25px;\ icon-size:20px;}') but.clicked.connect(self._open_tstamp_dialog) lay.addWidget(but, 0, 4, alignment=Qt.AlignTop) return info_wid def _setup_intlkmap_wid(self): wid = QGroupBox() lay = QGridLayout(wid) lay.setHorizontalSpacing(30) # controls pvname = self.get_pvname(propty='IntlkCtrlEnbl-Sel') sp = PyDMStateButton(self, init_channel=pvname) pvname = self.get_pvname(propty='IntlkCtrlEnbl-Sts') rb = PyDMLed(self, init_channel=pvname) gb = self._create_prop_widget('Intlk. Enable', wid, (sp, rb)) lay.addWidget(gb, 0, 0, alignment=Qt.AlignCenter) pvname = self.get_pvname(propty='IntlkCtrlRst-Cmd') sp = SiriusPushButton(self, init_channel=pvname, pressValue=1) sp.setIcon(qta.icon('fa5s.sync')) sp.setObjectName('bt') sp.setStyleSheet( '#bt{min-width:25px; max-width:25px; icon-size:20px;}') gb = self._create_prop_widget('Intlk. Reset', wid, (sp, )) lay.addWidget(gb, 1, 0, alignment=Qt.AlignCenter) pvname = self.get_pvname(propty='IntlkCtrlRepeat-Sel') sp = PyDMStateButton(self, init_channel=pvname) pvname = self.get_pvname(propty='IntlkCtrlRepeat-Sts') rb = PyDMLed(self, init_channel=pvname) gb = self._create_prop_widget('Intlk. Repeat', wid, (sp, rb)) lay.addWidget(gb, 2, 0, alignment=Qt.AlignCenter) pvname = self.get_pvname(propty='IntlkCtrlRepeatTime-SP') sp = PyDMLineEdit(self, init_channel=pvname) pvname = self.get_pvname(propty='IntlkCtrlRepeatTime-RB') rb = SiriusLabel(self, init_channel=pvname) gb = self._create_prop_widget('Intlk. Repeat Time', wid, (sp, rb)) lay.addWidget(gb, 3, 0, alignment=Qt.AlignCenter) # table # columns in lay_grid = QGridLayout() lay_grid.setHorizontalSpacing(6) lay_grid.setVerticalSpacing(4) for idx in range(7): idxstr = str(idx) hd = QLabel('Evt'+idxstr, self, alignment=Qt.AlignCenter) hd.setObjectName('hd') le = PyDMLineEdit(self, self.get_pvname('IntlkEvtIn'+idxstr+'-SP')) le.setObjectName('le') le.setAlignment(Qt.AlignCenter) lb = SiriusLabel(self, self.get_pvname('IntlkEvtIn'+idxstr+'-RB')) lb.setObjectName('lb') lb.setAlignment(Qt.AlignCenter) ld = SiriusLedState( self, self.get_pvname('IntlkEvtStatus-Mon'), bit=idx) lay_grid.addWidget(hd, 0, idx+2, alignment=Qt.AlignCenter) lay_grid.addWidget(le, 1, idx+2, alignment=Qt.AlignCenter) lay_grid.addWidget(lb, 2, idx+2, alignment=Qt.AlignCenter) lay_grid.addWidget(ld, 3, idx+2, alignment=Qt.AlignCenter) # column out hd = QLabel('EvtOut', self, alignment=Qt.AlignCenter) hd.setObjectName('hd') le = PyDMLineEdit(self, self.get_pvname('IntlkEvtOut-SP')) le.setObjectName('le') le.setAlignment(Qt.AlignCenter) lb = SiriusLabel(self, self.get_pvname('IntlkEvtOut-RB')) lb.setObjectName('lb') lb.setAlignment(Qt.AlignCenter) ld = SiriusLedState(self, self.get_pvname('IntlkEvtStatus-Mon'), bit=7) lay_grid.addWidget(hd, 0, 9, alignment=Qt.AlignCenter) lay_grid.addWidget(le, 1, 9, alignment=Qt.AlignCenter) lay_grid.addWidget(lb, 2, 9, alignment=Qt.AlignCenter) lay_grid.addWidget(ld, 3, 9, alignment=Qt.AlignCenter) evt, row, col, colini = 0, 4, 2, 2 for idx in range(28): biti = idx % 16 bith = hex(biti).split('x')[1].capitalize() bitg = '0to15' if idx < 16 else '16to27' pvsp = self.get_pvname('IntlkTbl'+bitg+'-Sel', field='B'+bith) sp = PyDMStateButton(self, pvsp) sp.setStyleSheet( 'PyDMStateButton{min-height: 0.98em; max-height: 0.98em;}') pvrb = pvsp.substitute(propty_suffix='Sts') rb = SiriusLedState(self, pvrb) rb.setStyleSheet( 'SiriusLedState{min-width: 0.98em; max-width: 0.98em;}') gb = self._create_small_group('', wid, (sp, rb), align_ver=False) gb.layout().setSpacing(3) gb.layout().setContentsMargins(3, 1, 3, 1) gb.setSizePolicy(QSzPol.Preferred, QSzPol.Maximum) lay_grid.addWidget(gb, row, col) col += 1 if idx in [6, 12, 17, 21, 24, 26, 27]: evtlb = QLabel('Evt'+str(evt), self, alignment=Qt.AlignRight) lay_grid.addWidget(evtlb, row, 0, alignment=Qt.AlignVCenter) line = QFrame(self) line.setFrameShape(QFrame.HLine) line.setFrameShadow(QFrame.Plain) lay_grid.addWidget(line, row, 1, 1, colini-1) evt += 1 row += 1 colini += 1 col = colini lay.addLayout(lay_grid, 0, 1, 4, 1) wid.setStyleSheet("#hd, #le, #lb{max-width: 3em;}") return wid def _create_prop_widget(self, name, parent, wids, align_ver=True): pwid = QWidget(parent) vbl = QVBoxLayout(pwid) lab = QLabel('<b>' + name + '</b>') lab.setAlignment(Qt.AlignCenter) vbl.addWidget(lab) hbl = QHBoxLayout() vbl.addItem(hbl) for wid in wids: wid.setParent(pwid) hbl.addWidget(wid) hbl.setAlignment(wid, Qt.AlignCenter) return pwid def _create_tstamp_dialog(self): dialog = SiriusDialog() dialog.setObjectName('ASApp') dialog.setWindowTitle(self.device + ' Timestamp Control') dialog.setWindowIcon(self.windowIcon()) lay = QVBoxLayout(dialog) gbox_tim = QGroupBox('Timestamp', self) lay.addWidget(gbox_tim) lb = QLabel('<b>Get UTC</b>') pvname = self.get_pvname('GetUTC-Cmd') sp = PyDMPushButton( self, label='Get UTC', init_channel=pvname, pressValue=1) # ? gb_getutc = self._create_small_group('', gbox_tim, (lb, sp)) lb = QLabel("<b>Mismatch</b>") pvname = self.get_pvname(propty='UTCMismatch-Mon') rb = SiriusLedAlert(self, init_channel=pvname) gb_utcmis = self._create_small_group('', gbox_tim, (lb, rb)) lb = QLabel("<b>UTC Source</b>") pvname = self.get_pvname(propty='UTCRefSrc-Sel') sp = SiriusEnumComboBox(self, init_channel=pvname) gb_utcsrc = self._create_small_group('', gbox_tim, (lb, sp)) lb = QLabel("<b>PPS Source</b>") pvname = self.get_pvname(propty='TimestampSrc-Sel') sp = SiriusEnumComboBox(self, init_channel=pvname) pvname = self.get_pvname(propty='TimestampSrc-Sts') rb = SiriusLabel(self, init_channel=pvname) gb_ppssrc = self._create_small_group('', gbox_tim, (lb, sp, rb)) lb = QLabel("<b>UTC</b>") pvname = self.get_pvname(propty='UTC-SP') sp = PyDMLineEdit(self, init_channel=pvname) pvname = self.get_pvname(propty='UTC-RB') rb = SiriusLabel(self, init_channel=pvname) rb.showUnits = True gb_utc = self._create_small_group('', gbox_tim, (lb, sp, rb)) lb = QLabel('<b>Subsec</b>') mon = SiriusLabel(self, self.get_pvname('SubSecond-Mon')) mon.showUnits = True gb_subsec = self._create_small_group('', gbox_tim, (lb, mon)) lb = QLabel('<b>Control Room UTC</b>') mon = SiriusLabel(self, self.get_pvname('CtrlRoomUTC')) mon.showUnits = True gb_ctrlutc = self._create_small_group('', gbox_tim, (lb, mon)) lay_tim = QGridLayout(gbox_tim) lay_tim.setHorizontalSpacing(30) lay_tim.addWidget(gb_getutc, 0, 0) lay_tim.addWidget(gb_utcmis, 0, 1) lay_tim.addWidget(gb_utcsrc, 0, 2) lay_tim.addWidget(gb_ppssrc, 0, 3) lay_tim.addWidget(gb_utc, 1, 0) lay_tim.addWidget(gb_subsec, 1, 1) lay_tim.addWidget(gb_ctrlutc, 1, 2) # Timestamp Log enable gbox_enbl = QGroupBox('Timestamp Log Enable', self) lay.addWidget(gbox_enbl) lay_enbl = QGridLayout(gbox_enbl) lay_enbl.setHorizontalSpacing(15) for bit in range(8): bitname = 'Out' if bit == 7 else f'In{bit}' lb = QLabel(f'Evt{bitname}', self, alignment=Qt.AlignCenter) pvsp = self.get_pvname('IntlkLogEnbl-SP', field=f'B{bit}') sp = PyDMStateButton(self, pvsp) sp.setStyleSheet( 'PyDMStateButton{min-height: 0.98em; max-height: 0.98em;}') pvrb = pvsp.substitute(propty_suffix='RB') rb = SiriusLedState(self, pvrb) rb.setStyleSheet( 'SiriusLedState{min-width: 0.98em; max-width: 0.98em;}') gb = self._create_small_group( '', gbox_enbl, (lb, sp, rb), align_ver=True) gb.layout().setSpacing(3) gb.layout().setContentsMargins(3, 1, 3, 1) gb.setSizePolicy(QSzPol.Preferred, QSzPol.Maximum) lay_enbl.addWidget(gb, 0, bit) # Timestamp Log gbox_log = QGroupBox('Timestamp Log', self) lay.addWidget(gbox_log) ld_logstp = QLabel('<b>Stop Log</b>', self) self.sb_logstp = PyDMStateButton(self, self.get_pvname('stoplog')) self.led_logstp = SiriusLedState(self, self.get_pvname('STOPLOGRBV')) gb_logstp = self._create_small_group( '', gbox_log, (ld_logstp, self.sb_logstp, self.led_logstp)) ld_logrst = QLabel('<b>Reset Log</b>', self) self.sb_logrst = PyDMStateButton(self, self.get_pvname('rstlog')) self.led_logrst = SiriusLedState(self, self.get_pvname('RSTLOGRBV')) gb_logrst = self._create_small_group( '', gbox_log, (ld_logrst, self.sb_logrst, self.led_logrst)) ld_logpul = QLabel('<b>Pull</b>', self) self.bt_logpul = SiriusPushButton( parent=self, init_channel=self.get_pvname('pull'), pressValue=1, releaseValue=0) # ? self.bt_logpul.setIcon(qta.icon('fa5s.arrow-down')) self.bt_logpul.setObjectName('bt') self.bt_logpul.setStyleSheet( '#bt{min-width:25px; max-width:25px; icon-size:20px;}') gb_logpul = self._create_small_group( '', gbox_log, (ld_logpul, self.bt_logpul)) ld_logcnt = QLabel('<b>Log Count</b>', self, alignment=Qt.AlignCenter) self.lb_logcnt = SiriusLabel(self, self.get_pvname('LOGCOUNT')) self.lb_logcnt.showUnits = True self.lb_logcnt.setAlignment(Qt.AlignCenter) ld_logful = QLabel('Full', self) self.led_logful = SiriusLedState(self, self.get_pvname('FULL')) ld_logemp = QLabel('Empty', self) self.led_logemp = SiriusLedState(self, self.get_pvname('EMPTY')) fr_logcnt = QFrame(gbox_log) fr_logcnt.setStyleSheet('.QFrame{border: 1px solid gray;}') lay_logcnt = QGridLayout(fr_logcnt) lay_logcnt.setAlignment(Qt.AlignCenter) lay_logcnt.setContentsMargins(0, 0, 0, 0) lay_logcnt.addWidget(ld_logcnt, 0, 0, 1, 4) lay_logcnt.addWidget(self.lb_logcnt, 1, 0, 1, 4) lay_logcnt.addWidget(ld_logful, 2, 0, alignment=Qt.AlignRight) lay_logcnt.addWidget(self.led_logful, 2, 1, alignment=Qt.AlignTop) lay_logcnt.addWidget(ld_logemp, 2, 2, alignment=Qt.AlignRight) lay_logcnt.addWidget(self.led_logemp, 2, 3, alignment=Qt.AlignTop) ld_logevt = QLabel('<b>Event</b>', self) self.lb_logevt = SiriusLabel(self, self.get_pvname('LOGEVENT')) gb_logevt = self._create_small_group( '', gbox_log, (ld_logevt, self.lb_logevt)) ld_logutc = QLabel('<b>Log UTC</b>', self) self.lb_logutc = SiriusLabel(self, self.get_pvname('LOGUTC')) self.lb_logutc.showUnits = True gb_logutc = self._create_small_group( '', gbox_log, (ld_logutc, self.lb_logutc)) ld_logsub = QLabel('<b>Log Subsec</b>', self) self.lb_logsub = SiriusLabel(self, self.get_pvname('LOGSUBSEC')) self.lb_logsub.showUnits = True gb_logsub = self._create_small_group( '', gbox_log, (ld_logsub, self.lb_logsub)) lay_log = QGridLayout(gbox_log) lay_log.addWidget(gb_logstp, 0, 0, alignment=Qt.AlignTop) lay_log.addWidget(gb_logrst, 0, 1, alignment=Qt.AlignTop) lay_log.addWidget(gb_logpul, 0, 2, alignment=Qt.AlignTop) lay_log.addWidget(gb_logevt, 1, 0, alignment=Qt.AlignTop) lay_log.addWidget(gb_logutc, 1, 1, alignment=Qt.AlignTop) lay_log.addWidget(gb_logsub, 1, 2, alignment=Qt.AlignTop) lay_log.addWidget(fr_logcnt, 0, 3, 2, 1, alignment=Qt.AlignCenter) # Timestamp Log Buffer gbox_buf = QGroupBox('Timestamp Log Buffer', self) lay.addWidget(gbox_buf) ld_bufcnt = QLabel('<b>Log Count</b>', self) self.lb_bufcnt = SiriusLabel(self, self.get_pvname('LOGSOFTCNT')) self.lb_bufcnt.showUnits = True gb_bufcnt = self._create_small_group( '', gbox_buf, (ld_bufcnt, self.lb_bufcnt)) ld_bufrst = QLabel('<b>Reset</b>', self) self.bt_bufrst = SiriusPushButton( parent=self, init_channel=self.get_pvname('rstSoftBuff'), pressValue=1, releaseValue=0) # ? self.bt_bufrst.setIcon(qta.icon('fa5s.sync')) self.bt_bufrst.setObjectName('bt') self.bt_bufrst.setStyleSheet( '#bt{min-width:25px; max-width:25px; icon-size:20px;}') gb_bufrst = self._create_small_group( '', gbox_buf, (ld_bufrst, self.bt_bufrst)) ld_bufutc = QLabel('<b>UTC buffer</b>', self) fmt = "%d/%m/%y %H:%M:%S" func = _np.vectorize( lambda tstp: _datetime.fromtimestamp(tstp).strftime(fmt) if tstp != 0 else 0 ) # from timestamp to datetime format self.tb_bufutc = self._create_logbuffer_table( prop='UTCbuffer', transform=func ) gb_bufutc = self._create_small_group( '', gbox_buf, (ld_bufutc, self.tb_bufutc)) ld_bufsub = QLabel('<b>Subsec buffer</b>', self) rffreq = _PV("RF-Gen:GeneralFreq-RB").value func = lambda vec: _np.round(vec * 4 / rffreq, decimals=10) # from EVG clock to seconds self.tb_bufsub = self._create_logbuffer_table( prop='SUBSECbuffer', transform=func) gb_bufsub = self._create_small_group( '', gbox_buf, (ld_bufsub, self.tb_bufsub)) ld_bufevt = QLabel('<b>Event buffer</b>', self) self.tb_bufevt = self._create_logbuffer_table('EVENTbuffer') gb_bufevt = self._create_small_group( '', gbox_buf, (ld_bufevt, self.tb_bufevt)) lay_logbuf = QGridLayout(gbox_buf) lay_logbuf.addWidget(gb_bufcnt, 0, 0, 1, 3) lay_logbuf.addWidget(gb_bufrst, 0, 3, 1, 3) lay_logbuf.addWidget(gb_bufutc, 1, 0, 1, 2) lay_logbuf.addWidget(gb_bufsub, 1, 2, 1, 2) lay_logbuf.addWidget(gb_bufevt, 1, 4, 1, 2) return dialog def _open_tstamp_dialog(self): if not hasattr(self, 'tstamp_wind'): self.tstamp_wind = self._create_tstamp_dialog() self.tstamp_wind.show() else: self.tstamp_wind.showNormal() def _create_downconn_dialog(self): dialog = SiriusDialog() dialog.setObjectName('ASApp') dialog.setWindowTitle(self.device + ' Down Connections') dialog.setWindowIcon(self.windowIcon()) lay = QVBoxLayout(dialog) obj_names = [ self.device.substitute(idx=self.device.idx+'_'+str(i)) for i in range(8)] downconn_wid = EVGFOUTOUTList( name='Down Connections', parent=self, prefix=self.prefix, obj_names=obj_names) lay.addWidget(downconn_wid) return dialog def _open_downconn_dialog(self): if not hasattr(self, 'downconn_wind'): self.downconn_wind = self._create_downconn_dialog() self.downconn_wind.show() else: self.downconn_wind.showNormal()
[docs] class BucketListGraph(BaseWidget): """Bucket List Graph.""" def __init__(self, parent=None, device='', prefix=''): if not device: device = LLTimeSearch.get_evg_name() super().__init__(parent, device, prefix) self._setupUi() def _setupUi(self): # Graph self.graph = SiriusWaveformPlot(self) self.graph.setBackgroundColor(QColor(255, 255, 255)) self.graph.maxRedrawRate = 2 self.graph.mouseEnabledX = True self.graph.setShowXGrid(True) self.graph.setShowYGrid(True) self.graph.setAutoRangeX(False) self.graph.setMinYRange(-0.1) self.graph.setMaxYRange(1.1) self.graph.setAxisColor(QColor(0, 0, 0)) self.graph.setLabel('left', 'Buckets', color='gray') self.graph.setObjectName('graph') self.graph.setStyleSheet('#graph{min-height: 5em;}') self.graph.setSizePolicy(QSzPol.Expanding, QSzPol.Expanding) self._curves = dict() self.graph.addChannel( y_channel='FAKE:SP', name='SP', color='red', lineWidth=2) self._curves['SP'] = self.graph.curveAtIndex(0) self._curves['SP'].setFillLevel(0) self._curves['SP'].setBrush(QBrush(QColor('red'))) self.graph.addChannel( y_channel='FAKE:RB', name='RB', color='blue', lineWidth=2) self._curves['RB'] = self.graph.curveAtIndex(1) self._curves['RB'].setFillLevel(0) self._curves['RB'].setBrush(QBrush(QColor('blue'))) self.graph.addChannel( y_channel='FAKE:Mon', name='Mon', color='green', lineWidth=2) self._curves['Mon'] = self.graph.curveAtIndex(2) self._curves['Mon'].setFillLevel(0) self._curves['Mon'].setBrush(QBrush(QColor('green'))) # Show self.show_sp = QCheckBox('SP') self.show_sp.setChecked(True) self.show_sp.setStyleSheet('color: red;') self.show_sp.stateChanged.connect(self._curves['SP'].setVisible) self.show_rb = QCheckBox('RB') self.show_rb.setChecked(True) self.show_rb.setStyleSheet('color: blue;') self.show_rb.stateChanged.connect(self._curves['RB'].setVisible) self.show_mn = QCheckBox('Mon') self.show_mn.setChecked(True) self.show_mn.setStyleSheet('color: green;') self.show_mn.stateChanged.connect(self._curves['Mon'].setVisible) wid_show = QWidget() lay_show = QVBoxLayout(wid_show) lay_show.setContentsMargins(0, 0, 0, 0) lay_show.addWidget(self.show_sp) lay_show.addWidget(self.show_rb) lay_show.addWidget(self.show_mn) lay = QHBoxLayout(self) lay.setContentsMargins(0, 0, 0, 0) lay.addWidget(self.graph) lay.addWidget(wid_show) self._ch_sp = SiriusConnectionSignal( self.get_pvname(propty='BucketList-SP')) self._ch_sp.new_value_signal[_np.ndarray].connect(self._update_curves) self._ch_sp.new_value_signal[int].connect(self._update_curves) self._ch_rb = SiriusConnectionSignal( self.get_pvname(propty='BucketList-RB')) self._ch_rb.new_value_signal[_np.ndarray].connect(self._update_curves) self._ch_rb.new_value_signal[int].connect(self._update_curves) self._ch_mn = SiriusConnectionSignal( self.get_pvname(propty='BucketList-Mon')) self._ch_mn.new_value_signal[_np.ndarray].connect(self._update_curves) self._ch_mn.new_value_signal[int].connect(self._update_curves) @Slot(int) @Slot(_np.ndarray) def _update_curves(self, new_array): new_array = _np.asarray(new_array) for k in self._curves: if self.sender().address.endswith(k): curve = self._curves[k] break org_bunch = _np.arange(1, 864) - 0.5 org_curve = _np.zeros(864) # trying to catch bug observed where new_array # had strange values greater than 864 try: org_curve[new_array-1] = 1 except IndexError: _log.warning( 'IndexError: Received array for ' f'{self.sender().address} with values out of [1, 864]') _log.warning(f'IndexError: new_array: {new_array}') new_bunch = _np.linspace(1, 864, 10000) - 0.5 new_bunch_indices = _np.searchsorted( _np.nextafter(org_bunch, -_np.inf), new_bunch, side='left') new_bunch_indices = new_bunch_indices.clip( 1, len(org_bunch)).astype(_np.int_) new_curve = org_curve[new_bunch_indices-1] curve.receiveXWaveform(new_bunch) curve.receiveYWaveform(new_curve)
[docs] class BucketList(BaseWidget): def __init__(self, parent=None, device='', prefix='', min_size=25, show_graph=False): if not device: device = LLTimeSearch.get_evg_name() super().__init__(parent, device, prefix) self.setObjectName('ASApp') self._min_size = min_size self._show_graph = show_graph self.setupui()
[docs] def setupui(self): self.setLayout(QHBoxLayout(self)) wid = QGroupBox('Bucket List', self) self.layout().addWidget(wid) self.layout().setContentsMargins(0, 0, 0, 0) lay = QGridLayout(wid) tm = 'min-width:{0:d}em; max-height:1.15em;' pvname = self.get_pvname("BucketList-SP") sp = BucketListLineEdit(wid, init_channel=pvname) self.bucket_ledit = sp sp.setStyleSheet(tm.format(self._min_size-1)) sp.setSizePolicy(QSzPol.MinimumExpanding, QSzPol.Maximum) lab = QLabel('SP : ', wid) lab.setSizePolicy(QSzPol.Maximum, QSzPol.Maximum) pushbtn = QPushButton(wid) pushbtn.setObjectName('but') pushbtn.setStyleSheet( '#but{min-width:25px; max-width:25px; icon-size:20px;}') pushbtn.setIcon(qta.icon('mdi.basket-fill')) self._wid_fill = self._setup_bucket_list_fill() pushbtn.clicked.connect(self._wid_fill.open) lay_sp = QHBoxLayout() lay_sp.addWidget(lab) lay_sp.addWidget(sp) lay_sp.addWidget(pushbtn) pvname = self.get_pvname("BucketList-RB") rb = BucketListLabel(wid, init_channel=pvname) rb.setStyleSheet(tm.format(self._min_size)) rb.setSizePolicy(QSzPol.MinimumExpanding, QSzPol.Maximum) lab = QLabel('RB : ', wid) lab.setSizePolicy(QSzPol.Maximum, QSzPol.Maximum) lay_rb = QHBoxLayout() lay_rb.addWidget(lab) lay_rb.addWidget(rb) pvname = self.get_pvname("BucketList-Mon") mn = BucketListLabel(wid, init_channel=pvname) mn.setStyleSheet(tm.format(self._min_size)) mn.setSizePolicy(QSzPol.MinimumExpanding, QSzPol.Maximum) lab = QLabel('Mon: ', wid) lab.setSizePolicy(QSzPol.Maximum, QSzPol.Maximum) lay_mn = QHBoxLayout() lay_mn.addWidget(lab) lay_mn.addWidget(mn) vlay = QVBoxLayout() vlay.setSpacing(1) vlay.addLayout(lay_sp) vlay.addLayout(lay_rb) vlay.addLayout(lay_mn) lay.addLayout(vlay, 0, 0) pvname = self.get_pvname("BucketListSyncStatus-Mon") rb = PyDMLed(wid, init_channel=pvname) rb.setOffColor(rb.Red) rb.setOnColor(rb.LightGreen) lab = QLabel('Sync', wid) lab.setStyleSheet("min-width:4em; max-height:1.15em;") lab.setAlignment(Qt.AlignCenter) vlay = QVBoxLayout() vlay.setSpacing(1) vlay.addWidget(lab) vlay.addWidget(rb) lay.addLayout(vlay, 0, 1) rb = SiriusLabel( wid, init_channel=self.get_pvname("BucketListLen-Mon")) rb.setStyleSheet("min-width:4em; max-height:1.15em;") rb.setAlignment(Qt.AlignCenter) lab = QLabel('Size', wid) lab.setStyleSheet("min-width:4em; max-height:1.15em;") lab.setAlignment(Qt.AlignCenter) vlay = QVBoxLayout() vlay.setSpacing(1) vlay.addWidget(lab) vlay.addWidget(rb) lay.addLayout(vlay, 0, 2) pvname = self.get_pvname("RepeatBucketList-SP") sp = SiriusSpinbox(wid, init_channel=pvname) pvname = self.get_pvname("RepeatBucketList-RB") rb = SiriusLabel(wid, init_channel=pvname) rb.setStyleSheet("min-width:4em; max-height:1.15em;") lab = QLabel('Repeat', wid, alignment=Qt.AlignCenter) hlay = QHBoxLayout() hlay.setSpacing(1) hlay.addWidget(sp) hlay.addWidget(rb) vlay = QVBoxLayout() vlay.setSpacing(1) vlay.addWidget(lab) vlay.addLayout(hlay) lay.addLayout(vlay, 0, 3) if self._show_graph: graph = BucketListGraph(self, self.device, self.prefix) lay.addWidget(graph, 1, 0, 1, 4)
def _setup_bucket_list_fill(self): inj_prefix = _PVName('AS-Glob:AP-InjCtrl').substitute( prefix=self.prefix) wid = SiriusDialog(self) wid.setFocus(True) wid.setFocusPolicy(Qt.StrongFocus) wid.setObjectName('ASApp') window = create_window_from_widget( AllowedBucketsMatrix, title='Allowed Buckets to Inject', withscroll=True, ) self._pb_allowed_buckets = QPushButton('', wid) self._pb_allowed_buckets.setObjectName('btn') self._pb_allowed_buckets.setIcon(qta.icon('fa5s.tasks')) self._pb_allowed_buckets.setToolTip( 'Open window to select BPMs and correctors' ) self._pb_allowed_buckets.setStyleSheet( '#btn{min-width:3.3em; max-width:3.3em;\ min-height:1.8em; max-height:1.8em; icon-size:25px;}' ) connect_window( self._pb_allowed_buckets, window, None, device=inj_prefix ) self._sb_start = SiriusSpinbox( wid, inj_prefix.substitute(propty='BucketListStart-SP')) self._sb_start.setAlignment(Qt.AlignCenter) self._sb_start.setStyleSheet('max-width:5em;') self._lb_start = SiriusLabel( wid, inj_prefix.substitute(propty='BucketListStart-RB')) self._sb_stop = SiriusSpinbox( wid, inj_prefix.substitute(propty='BucketListStop-SP')) self._sb_stop.setAlignment(Qt.AlignCenter) self._sb_stop.setStyleSheet('max-width:5em;') self._lb_stop = SiriusLabel( wid, inj_prefix.substitute(propty='BucketListStop-RB')) self._sb_step = SiriusSpinbox( wid, inj_prefix.substitute(propty='BucketListStep-SP')) self._sb_step.setAlignment(Qt.AlignCenter) self._sb_step.setStyleSheet('max-width:5em;') self._lb_step = SiriusLabel( wid, inj_prefix.substitute(propty='BucketListStep-RB')) self._pb_ok = QPushButton('Ok', wid) self._pb_ok.clicked.connect(self._sb_start.send_value) self._pb_ok.clicked.connect(wid.accept) self._pb_cancel = QPushButton('Cancel', wid) self._pb_cancel.setDefault(True) self._pb_cancel.clicked.connect(wid.reject) lay_pbrow = QHBoxLayout() lay_pbrow.setContentsMargins(0, 0, 0, 0) lay_pbrow.addWidget(self._pb_cancel) lay_pbrow.addWidget(self._pb_ok) lay = QGridLayout(wid) lay.addWidget(QLabel('Allowed Buckets:', wid), 0, 0) lay.addWidget( self._pb_allowed_buckets, 0, 1, 1, 2, alignment=Qt.AlignCenter ) lay.addWidget(QLabel('Start:', wid), 1, 0) lay.addWidget(self._sb_start, 1, 1) lay.addWidget(self._lb_start, 1, 2) lay.addWidget(QLabel('Stop:', wid), 2, 0) lay.addWidget(self._sb_stop, 2, 1) lay.addWidget(self._lb_stop, 2, 2) lay.addWidget(QLabel('Step:', wid), 3, 0) lay.addWidget(self._sb_step, 3, 1) lay.addWidget(self._lb_step, 3, 2) lay.addLayout(lay_pbrow, 4, 0, 1, 3) return wid
[docs] class EventList(BaseList): """Template for control of Events.""" _MIN_WIDs = { 'ext_trig': 4, 'mode': 6.6, 'delay_type': 4.2, 'delay': 5.2, 'delayraw': 5.2, 'description': 9.7, 'code': 3.2, 'name': 4.8, } _LABELS = { 'ext_trig': 'Trig.', 'mode': 'Mode', 'description': 'Description', 'delay_type': 'Type', 'delay': 'Delay [us]', 'delayraw': 'Raw Delay', 'code': 'Code', 'name': 'Name'} _ALL_PROPS = ( 'ext_trig', 'name', 'mode', 'delay_type', 'delay', 'delayraw', 'description', 'code') def __init__(self, **kwargs): kwargs['props2search'] = set( ('name', 'mode', 'delay_type')) super().__init__(**kwargs) self.setObjectName('ASApp') def _createObjs(self, device, prop): sp = rb = None if prop == 'ext_trig': pvname = device.substitute(propty=device.propty+'ExtTrig-Cmd') sp = QWidget(self) but = PyDMPushButton(sp, init_channel=pvname, pressValue=1) but.setIcon(qta.icon('fa5s.step-forward')) but.setObjectName('but') but.setStyleSheet( '#but{min-width:40px; min-height:30px; icon-size:20px;}') but.setToolTip('Run event asynchronously') hbl = QHBoxLayout(sp) hbl.addWidget(but) elif prop == 'name': sp = QLabel(device.propty, self, alignment=Qt.AlignCenter) elif prop == 'mode': pvname = device.substitute(propty=device.propty+'Mode-Sel') sp = SiriusEnumComboBox(self, init_channel=pvname) pvname = device.substitute(propty=device.propty+'Mode-Sts') rb = SiriusLabel(self, init_channel=pvname) elif prop == 'delay_type': pvname = device.substitute(propty=device.propty+'DelayType-Sel') sp = SiriusEnumComboBox(self, init_channel=pvname) pvname = device.substitute(propty=device.propty+'DelayType-Sts') rb = SiriusLabel(self, init_channel=pvname) elif prop == 'delay': pvname = device.substitute(propty=device.propty+'Delay-SP') sp = SiriusSpinbox(self, init_channel=pvname) pvname = device.substitute(propty=device.propty+'Delay-RB') rb = SiriusLabel(self, init_channel=pvname) elif prop == 'delayraw': pvname = device.substitute(propty=device.propty+'DelayRaw-SP') sp = SiriusSpinbox(self, init_channel=pvname) pvname = device.substitute(propty=device.propty+'DelayRaw-RB') rb = SiriusLabel(self, init_channel=pvname) elif prop == 'description': pvname = device.substitute(propty=device.propty+'Desc-SP') sp = PyDMLineEdit(self, init_channel=pvname) pvname = device.substitute(propty=device.propty+'Desc-RB') rb = SiriusLabel(self, init_channel=pvname) elif prop == 'code': pvname = device.substitute(propty=device.propty+'Code-Mon') sp = SiriusLabel(self, init_channel=pvname) sp.setAlignment(Qt.AlignCenter) if rb is None: return (sp, ) return (sp, rb)
[docs] class ClockList(BaseList): """Template for control of Low Level Clocks.""" _MIN_WIDs = { 'name': 3.8, 'frequency': 4.8, 'mux_div': 6, 'mux_enbl': 4.8, } _LABELS = { 'name': 'Name', 'frequency': 'Freq. [Hz]', 'mux_div': 'Mux Divisor', 'mux_enbl': 'Enabled', } _ALL_PROPS = ('name', 'mux_enbl', 'frequency', 'mux_div') def __init__(self, name=None, parent=None, prefix='', props=set(), obj_names=list(), has_search=False): """Initialize object.""" super().__init__( name=name, parent=parent, prefix=prefix, props=props, obj_names=obj_names, has_search=has_search, props2search={'name', 'mux_enbl'}) self.setObjectName('ASApp') def _createObjs(self, device, prop): if prop == 'frequency': pvname = device.substitute(propty=device.propty+'Freq-SP') sp = SiriusSpinbox(self, init_channel=pvname) sp.limitsFromChannel = False sp.setMinimum(1) sp.setMaximum(2**31 - 1) pvname = device.substitute(propty=device.propty+'Freq-RB') rb = SiriusLabel(self, init_channel=pvname) elif prop == 'name': rb = QLabel(device.propty, self) rb.setAlignment(Qt.AlignCenter) return (rb, ) elif prop == 'mux_enbl': pvname = device.substitute(propty=device.propty+'MuxEnbl-Sel') sp = PyDMStateButton(self, init_channel=pvname) pvname = device.substitute(propty=device.propty+'MuxEnbl-Sts') rb = PyDMLed(self, init_channel=pvname) elif prop == 'mux_div': pvname = device.substitute(propty=device.propty+'MuxDiv-SP') sp = SiriusSpinbox(self, init_channel=pvname) pvname = device.substitute(propty=device.propty+'MuxDiv-RB') rb = SiriusLabel(self, init_channel=pvname) return sp, rb
# ###################### Event Distributors ######################
[docs] class FOUT(BaseWidget): """Template for control of High Level Triggers.""" def __init__(self, parent=None, device='', prefix=''): """Initialize object.""" super().__init__(parent, device, prefix) self._setupUi() self.setObjectName('ASApp') def _setupUi(self): self.my_layout = QGridLayout(self) self.my_layout.setHorizontalSpacing(20) self.my_layout.setVerticalSpacing(15) self.my_layout.addWidget(self._setupmenus(), 0, 0) lab = QLabel('<h1>' + self.device.device_name + '</h1>', self) self.my_layout.addWidget(lab, 1, 0) self.my_layout.setAlignment(lab, Qt.AlignCenter) stattab = QTabWidget(self) stattab.setObjectName('ASTab') stattab.setStyleSheet(""" QTabWidget::pane{ border-left: 2px solid gray; border-bottom: 2px solid gray; border-right: 2px solid gray; }""") self.status_wid = self._setup_status_wid() stattab.addTab(self.status_wid, 'Status') self.info_wid = self._setup_info_wid() stattab.addTab(self.info_wid, 'Fw && IOC') self.my_layout.addWidget(stattab, 2, 0) stattab.setSizePolicy(QSzPol.Preferred, QSzPol.Maximum) def _setupmenus(self): main_menu = QMenuBar() main_menu.setNativeMenuBar(False) icon = qta.icon('mdi.timer', color=get_appropriate_color('AS')) try: mapping = LLTimeSearch.get_fout2trigsrc_mapping() downs = mapping[self.device.device_name] downs = sorted([(ou, dwn) for ou, dwn in downs.items()]) menu = main_menu.addMenu('&Downlinks') except KeyError: downs = list() for out, dwn in downs: dev, down = dwn.dev, dwn.device_name devt = EVR if dev == 'EVR' else EVE if dev == 'EVE' else AFC action = menu.addAction(out + ' --> ' + down) Win = create_window_from_widget(devt, title=down, icon=icon) connect_window(action, Win, None, device=down, prefix=self.prefix) try: link = list(LLTimeSearch.In2OutMap[self.device.dev])[0] evg = LLTimeSearch.get_evg_channel( self.device.device_name.substitute(propty=link)) except KeyError: return main_menu menu = main_menu.addMenu('&Uplink') action = menu.addAction(evg) Win = create_window_from_widget(EVG, title=evg.device_name, icon=icon) connect_window( action, Win, None, device=evg.device_name, prefix=self.prefix) return main_menu def _setup_status_wid(self): status_wid = QWidget(self) status_lay = QGridLayout(status_wid) status_lay.setHorizontalSpacing(30) status_lay.setVerticalSpacing(30) pvname = self.get_pvname(propty='DevEnbl-Sel') sp = PyDMStateButton(self, init_channel=pvname) pvname = self.get_pvname(propty='DevEnbl-Sts') rb = PyDMLed(self, init_channel=pvname) gb = self._create_small_group( 'Enabled', status_wid, (sp, rb), align_ver=False) status_lay.addWidget(gb, 0, 0) lb = QLabel("<b>Alive</b>") rb = SiriusLabel( self, init_channel=self.get_pvname(propty='Alive-Mon')) gb = self._create_small_group('', status_wid, (lb, rb)) status_lay.addWidget(gb, 0, 1) lb = QLabel("<b>Network</b>") pvname = self.get_pvname(propty='Network-Mon') rb = SiriusLedAlert(self, init_channel=pvname) on_c, off_c = rb.onColor, rb.offColor rb.offColor = on_c rb.onColor = off_c gb = self._create_small_group('', status_wid, (lb, rb)) status_lay.addWidget(gb, 0, 2) lb = QLabel("<b>UP Link</b>") pvname = self.get_pvname(propty='LinkStatus-Mon') rb = SiriusLedAlert(self, init_channel=pvname) on_c, off_c = rb.onColor, rb.offColor rb.offColor = on_c rb.onColor = off_c gb = self._create_small_group('', status_wid, (lb, rb)) status_lay.addWidget(gb, 0, 3) wids = list() try: mapping = LLTimeSearch.get_fout2trigsrc_mapping() conn = mapping[self.device.device_name] conn = {int(dev[-1]) for dev in conn} except KeyError: conn = set() for i in range(8): pvname = self.get_pvname(propty='DownlinkStatus-Mon') if i in conn: rb = SiriusLedAlert(self, init_channel=pvname, bit=i) else: rb = SiriusLedState(self, init_channel=pvname, bit=i) rb.onColor = rb.DarkGreen rb.offColor = rb.LightGreen wids.append(rb) but = QPushButton(self) but.setToolTip('Open Down Connections Details') but.setIcon(qta.icon('fa5s.ellipsis-v')) but.setObjectName('but') but.setDefault(False) but.setAutoDefault(False) but.setStyleSheet( '#but{min-width:15px; max-width:15px;\ min-height:25px; max-height:25px;\ icon-size:20px;}') but.clicked.connect(self._open_downconn_dialog) wids.append(but) pvname = self.get_pvname(propty='RxLockedLtcRst-Cmd') pbt = SiriusPushButton( self, init_channel=pvname, pressValue=1, label='', icon=qta.icon('fa5s.sync')) wids.append(pbt) gb = self._create_small_group( 'Down Connection', status_wid, wids, align_ver=False) gb.layout().setContentsMargins(6, 6, 0, 6) status_lay.addWidget(gb, 1, 0, 1, 4) return status_wid def _setup_info_wid(self): info_wid = QWidget(self) info_lay = QGridLayout(info_wid) info_lay.setHorizontalSpacing(30) lb = QLabel("<b>IP</b>") pvname = self.get_pvname(propty='IPAddr-Mon') addr = SiriusLabel(self, init_channel=pvname) pvname = self.get_pvname(propty='IPPort-Mon') port = SiriusLabel(self, init_channel=pvname) gb = self._create_small_group('', info_wid, (lb, addr, port)) info_lay.addWidget(gb, 0, 0, alignment=Qt.AlignTop) lb = QLabel("<b>DevFun</b>") pvname = self.get_pvname(propty='DevFun-Sts') rb = SiriusLabel(self, init_channel=pvname) gb = self._create_small_group('', info_wid, (lb, rb)) info_lay.addWidget(gb, 0, 1, alignment=Qt.AlignTop) lb = QLabel("<b>Device Status</b>") pvname = self.get_pvname(propty='DevStatus-Mon') rb = SiriusLabel(self, init_channel=pvname) gb = self._create_small_group('', info_wid, (lb, rb)) info_lay.addWidget(gb, 0, 2, alignment=Qt.AlignTop) lb = QLabel("<b>Download</b>") pvname = self.get_pvname('Download-Cmd') sp = SiriusPushButton( self, label='', icon=qta.icon('fa5s.download'), pressValue=1, releaseValue=0, init_channel=pvname) # ? gb = self._create_small_group('', info_wid, (lb, sp)) info_lay.addWidget(gb, 1, 0, alignment=Qt.AlignTop) lb = QLabel("<b>Save Settings</b>") pvname = self.get_pvname('Save-Cmd') sp = PyDMPushButton( self, label='Save', init_channel=pvname, pressValue=1) # ? gb = self._create_small_group('', info_wid, (lb, sp)) info_lay.addWidget(gb, 1, 1, alignment=Qt.AlignTop) lb = QLabel("<b>Fw.Version</b>") pvname = self.get_pvname(propty='FwVersion-Cte.SVAL') frmv = SiriusLabel(self, init_channel=pvname) gb = self._create_small_group('', info_wid, (lb, frmv)) gb.layout().setSpacing(3) info_lay.addWidget(gb, 1, 2, alignment=Qt.AlignTop) return info_wid def _create_downconn_dialog(self): dialog = SiriusDialog() dialog.setObjectName('ASApp') dialog.setWindowTitle(self.device + ' Down Connections') dialog.setWindowIcon(self.windowIcon()) lay = QVBoxLayout(dialog) obj_names = [ self.device.substitute(idx=self.device.idx+'_'+str(i)) for i in range(8)] downconn_wid = EVGFOUTOUTList( name='Down Connections', parent=self, prefix=self.prefix, obj_names=obj_names) lay.addWidget(downconn_wid) return dialog def _open_downconn_dialog(self): if not hasattr(self, 'downconn_wind'): self.downconn_wind = self._create_downconn_dialog() self.downconn_wind.show() else: self.downconn_wind.showNormal()
# ###################### Event Receivers ######################
[docs] class AFC(BaseWidget): """Template for control of High Level Triggers.""" def __init__(self, parent=None, device='', prefix=''): """Initialize object.""" super().__init__(parent, device, prefix) self._setupUi() self.setObjectName('ASApp') def _setupUi(self): self.my_layout = QGridLayout(self) self.my_layout.setHorizontalSpacing(20) self.my_layout.setVerticalSpacing(20) # menu self.my_layout.addWidget(self._setupmenus(), 0, 0) # title lab = QLabel('<h1>' + self.device.device_name + '</h1>', self) self.my_layout.addWidget(lab, 1, 0) self.my_layout.setAlignment(lab, Qt.AlignCenter) # status stattab = QTabWidget(self) stattab.setObjectName('ASTab') stattab.setStyleSheet(""" QTabWidget::pane{ border-left: 2px solid gray; border-bottom: 2px solid gray; border-right: 2px solid gray; }""") self.status_wid = self._setup_status_wid() stattab.addTab(self.status_wid, 'Status') self.info_wid = self._setup_info_wid() stattab.addTab(self.info_wid, 'Fw && IOC') self.my_layout.addWidget(stattab, 2, 0) stattab.setSizePolicy(QSzPol.Preferred, QSzPol.Maximum) # frequency feedback self.freqff_wid = QGroupBox('Frequency feedback', self) freqtab = QTabWidget(self) freqtab.setObjectName('ASTab') afcfrefb_wid = self._setup_freqfb_wid('AFC') freqtab.addTab(afcfrefb_wid, 'AFC') rtmfreqfb_wid = self._setup_freqfb_wid('RTM') freqtab.addTab(rtmfreqfb_wid, 'RTM') freqff_lay = QVBoxLayout(self.freqff_wid) freqff_lay.setContentsMargins(0, 6, 0, 0) freqff_lay.addWidget(freqtab) self.my_layout.addWidget(self.freqff_wid, 3, 0) self.freqff_wid.setSizePolicy(QSzPol.Preferred, QSzPol.Maximum) # output tabs outtab = QTabWidget(self) outtab.setObjectName('ASTab') self.my_layout.addWidget(outtab, 4, 0) props = { 'name', 'state', 'event', 'source', 'width', 'polarity', 'pulses', 'delay', 'evtcnt', 'evtcntrst', 'hl_trigger'} set_ = LLTimeSearch.In2OutMap['AMCFPGAEVR']['SFP8'] obj_names = sorted([out for out in set_ if out.startswith('FMC')]) obj_names = [self.device.substitute(propty_name=o) for o in obj_names] self.fmcs_wid = AFCOUTList( name='', parent=self, props=props, prefix=self.prefix, obj_names=obj_names) self.fmcs_wid.setObjectName('fmcs_wid') outtab.addTab(self.fmcs_wid, 'FMC Outputs') obj_names = sorted([out for out in set_ if out.startswith('CRT')]) obj_names = [self.device.substitute(propty_name=o) for o in obj_names] self.crts_wid = AFCOUTList( name='', parent=self, props=props, prefix=self.prefix, obj_names=obj_names) self.crts_wid.setObjectName('crts_wid') outtab.addTab(self.crts_wid, 'CRT Outputs') def _setupmenus(self): main_menu = QMenuBar() main_menu.setNativeMenuBar(False) try: fout = LLTimeSearch.get_fout_channel( self.device.substitute(propty='CRT0')) except KeyError: return main_menu menu = main_menu.addMenu('&Uplink') action = menu.addAction(fout) icon = qta.icon('mdi.timer', color=get_appropriate_color('AS')) Win = create_window_from_widget( FOUT, title=fout.device_name, icon=icon) connect_window( action, Win, None, device=fout.device_name, prefix=self.prefix) return main_menu def _setup_status_wid(self): status_wid = QWidget(self) status_lay = QGridLayout(status_wid) status_lay.setHorizontalSpacing(30) pvname = self.get_pvname('DevEnbl-Sel') sp = PyDMStateButton(self, init_channel=pvname) pvname = self.get_pvname('DevEnbl-Sts') rb = PyDMLed(self, init_channel=pvname) gb = self._create_small_group( 'Enabled', status_wid, (sp, rb), align_ver=False) status_lay.addWidget(gb, 0, 0) lb = QLabel("<b>Alive</b>") pvname = self.get_pvname('Alive-Mon') rb = SiriusLabel(self, init_channel=pvname) gb = self._create_small_group('', status_wid, (lb, rb)) status_lay.addWidget(gb, 0, 1) for i, locktype in enumerate(['', 'Ltc']): lb = QLabel( '<b>Locked' + (' Latch' if locktype else '') + '</b>') widlbl = QWidget() hbxlbl = QHBoxLayout(widlbl) hbxlbl.setSpacing(10) hbxlbl.setContentsMargins(0, 0, 0, 0) hbxlbl.setAlignment(Qt.AlignLeft) widctl = QWidget() hbxctl = QHBoxLayout(widctl) hbxctl.setSpacing(1) hbxctl.setContentsMargins(0, 0, 0, 0) for dev in ['AFC', 'RTM', 'GT0']: pvname = self.get_pvname(f'{dev}ClkLocked{locktype}-Mon') rb = SiriusLedAlert(self, init_channel=pvname) rb.offColor, rb.onColor = rb.onColor, rb.offColor hbxctl.addWidget(rb) hbxlbl.addWidget(QLabel(dev, self)) if locktype == 'Ltc': rst = SiriusPushButton( self, label='', icon=qta.icon('fa5s.sync'), pressValue=1, init_channel=self.get_pvname('ClkLockedLtcRst-Cmd')) hbxctl.addWidget(rst) hbxlbl.addWidget(QLabel(' ', self)) gb = self._create_small_group('', status_wid, (lb, widctl, widlbl)) status_lay.addWidget(gb, 0, 2+i) lb = QLabel("<b>UP Link</b>") pvname = self.get_pvname('LinkStatus-Mon') rb = SiriusLedAlert(self, init_channel=pvname) rb.offColor, rb.onColor = rb.onColor, rb.offColor gb = self._create_small_group('', status_wid, (lb, rb)) status_lay.addWidget(gb, 0, 4) return status_wid def _setup_info_wid(self): info_wid = QWidget(self) info_lay = QGridLayout(info_wid) info_lay.setHorizontalSpacing(30) lb = QLabel("<b>FPGA Clk</b>") pvname = self.get_pvname('FPGAClk-Cte') mon = SiriusLabel(self, init_channel=pvname) mon.showUnits = True mon.precisionFromPV = False mon.precision = 3 pvname = self.get_pvname('FPGAClk-Cte', field='DOL') dol = PyDMLineEdit(self, init_channel=pvname) omsl = SiriusPushButton( self, label='', icon=qta.icon('fa5s.sync'), pressValue=1, init_channel=self.get_pvname('FPGAClk-Cte', field='OMSL')) proc = QWidget() hlproc = QHBoxLayout(proc) hlproc.setContentsMargins(0, 0, 0, 0) hlproc.addWidget(dol) hlproc.addWidget(omsl) gb = self._create_small_group('', info_wid, (lb, mon, proc)) info_lay.addWidget(gb, 0, 0) return info_wid def _setup_freqfb_wid(self, subdev): gbox = QWidget(self) # Controls ld_phskp = QLabel('<b>Phase KP</b>', self, alignment=Qt.AlignCenter) sb_phskp = SiriusSpinbox( self, self.get_pvname(propty=subdev+'PhasePropGain-SP')) sb_phskp.limitsFromChannel = False sb_phskp.setMinimum(-2**31) sb_phskp.setMaximum(2**31-1) lb_phskp = SiriusLabel( self, self.get_pvname(propty=subdev+'PhasePropGain-RB')) ld_phski = QLabel('<b>Phase KI</b>', self, alignment=Qt.AlignCenter) sb_phski = SiriusSpinbox( self, self.get_pvname(propty=subdev+'PhaseIntgGain-SP')) sb_phski.limitsFromChannel = False sb_phski.setMinimum(-2**31) sb_phski.setMaximum(2**31-1) lb_phski = SiriusLabel( self, self.get_pvname(propty=subdev+'PhaseIntgGain-RB')) ld_frqkp = QLabel('<b>Freq. KP</b>', self, alignment=Qt.AlignCenter) sb_frqkp = SiriusSpinbox( self, self.get_pvname(propty=subdev+'FreqPropGain-SP')) sb_frqkp.limitsFromChannel = False sb_frqkp.setMinimum(-2**31) sb_frqkp.setMaximum(2**31-1) lb_frqkp = SiriusLabel( self, self.get_pvname(propty=subdev+'FreqPropGain-RB')) ld_frqki = QLabel('<b>Freq. KI</b>', self, alignment=Qt.AlignCenter) sb_frqki = SiriusSpinbox( self, self.get_pvname(propty=subdev+'FreqIntgGain-SP')) sb_frqki.limitsFromChannel = False sb_frqki.setMinimum(-2**31) sb_frqki.setMaximum(2**31-1) lb_frqki = SiriusLabel( self, self.get_pvname(propty=subdev+'FreqIntgGain-RB')) ld_phnvg = QLabel('<b>Phs.Navg</b>', self, alignment=Qt.AlignCenter) sb_phnvg = SiriusSpinbox( self, self.get_pvname(propty=subdev+'PhaseNavg-SP')) sb_phnvg.limitsFromChannel = False sb_phnvg.setMinimum(-2**31) sb_phnvg.setMaximum(2**31-1) lb_phnvg = SiriusLabel( self, self.get_pvname(propty=subdev+'PhaseNavg-RB')) ld_phdiv = QLabel( '<b>Phs.Div 2<sup>n</sup></b>', self, alignment=Qt.AlignCenter) sb_phdiv = SiriusSpinbox( self, self.get_pvname(propty=subdev+'PhaseDiv-SP')) sb_phdiv.limitsFromChannel = False sb_phdiv.setMinimum(-2**31) sb_phdiv.setMaximum(2**31-1) lb_phdiv = SiriusLabel( self, self.get_pvname(propty=subdev+'PhaseDiv-RB')) ld_rfrlo = QLabel('<b>RFreqLo</b>', self, alignment=Qt.AlignCenter) lb_rfrlo = SiriusLabel( self, self.get_pvname(propty=subdev+'RFreqLo-Mon')) lb_rfrlo.displayFormat = SiriusLabel.DisplayFormat.Hex ld_rfrhi = QLabel('<b>RFreqHi</b>', self, alignment=Qt.AlignCenter) lb_rfrhi = SiriusLabel( self, self.get_pvname(propty=subdev+'RFreqHi-Mon')) lb_rfrhi.displayFormat = SiriusLabel.DisplayFormat.Hex ld_n1 = QLabel('<b>N1</b>', self, alignment=Qt.AlignCenter) ld_n1.setObjectName('n1') lb_n1 = SiriusLabel( self, self.get_pvname(propty=subdev+'N1-Mon')) lb_n1.setObjectName('n1') lb_n1.displayFormat = SiriusLabel.DisplayFormat.Hex ld_hsdiv = QLabel('<b>HSDiv</b>', self, alignment=Qt.AlignCenter) lb_hsdiv = SiriusLabel( self, self.get_pvname(propty=subdev+'HSDiv-Mon')) # Equation ld_fpgaclk = QLabel('(FPGA Clk) x ', self, alignment=Qt.AlignRight) ld_fpgaclk.setObjectName('fpgaclk') ld_fraqdiv = QLabel('------ = ', self, alignment=Qt.AlignCenter) lb_freqmult = PyDMLineEdit( self, self.get_pvname(propty=subdev+'FreqMult-Cte')) lb_freqmult.setObjectName('frac') lb_freqdiv = PyDMLineEdit( self, self.get_pvname(propty=subdev+'FreqDiv-Cte')) lb_freqdiv.setObjectName('frac') ld_freqdsc = QLabel('<b>Frequency</b>', self, alignment=Qt.AlignCenter) ld_freqdsc.setObjectName('freq') ld_freqsp = PyDMLineEdit( self, self.get_pvname(propty=subdev+'Freq-SP')) ld_freqsp.setObjectName('freq') ld_freqrb = SiriusLabel( self, self.get_pvname(propty=subdev+'Freq-RB'), keep_unit=True) ld_freqrb.setObjectName('freq') ld_freqrb.showUnits = True pb_clkrst = SiriusPushButton( self, init_channel=self.get_pvname(propty='RTMClkRst-Cmd'), pressValue=1, label='', icon=qta.icon('fa5s.sync')) pb_clkrst.setDefault(False) pb_clkrst.setAutoDefault(False) pb_clkrst.setObjectName('pb') pb_clkrst.setStyleSheet( '#pb{min-width:25px; max-width:25px;\ min-height:25px; max-height:25px;\ icon-size:20px;}') lay_sett1 = QGridLayout() lay_sett1.setHorizontalSpacing(30) lay_sett1.setVerticalSpacing(6) lay_sett1.addWidget(ld_phskp, 0, 0) lay_sett1.addWidget(sb_phskp, 1, 0, alignment=Qt.AlignCenter) lay_sett1.addWidget(lb_phskp, 2, 0) lay_sett1.addWidget(ld_phski, 0, 1) lay_sett1.addWidget(sb_phski, 1, 1, alignment=Qt.AlignCenter) lay_sett1.addWidget(lb_phski, 2, 1) lay_sett1.addWidget(ld_frqkp, 0, 2) lay_sett1.addWidget(sb_frqkp, 1, 2, alignment=Qt.AlignCenter) lay_sett1.addWidget(lb_frqkp, 2, 2) lay_sett1.addWidget(ld_frqki, 0, 3) lay_sett1.addWidget(sb_frqki, 1, 3, alignment=Qt.AlignCenter) lay_sett1.addWidget(lb_frqki, 2, 3) lay_sett1.addWidget(ld_phnvg, 0, 4) lay_sett1.addWidget(sb_phnvg, 1, 4, alignment=Qt.AlignCenter) lay_sett1.addWidget(lb_phnvg, 2, 4) lay_sett1.addWidget(ld_phdiv, 0, 5) lay_sett1.addWidget(sb_phdiv, 1, 5, alignment=Qt.AlignCenter) lay_sett1.addWidget(lb_phdiv, 2, 5) lay_sett2 = QGridLayout() lay_sett2.setHorizontalSpacing(30) lay_sett2.addWidget(ld_rfrlo, 0, 0) lay_sett2.addWidget(lb_rfrlo, 1, 0) lay_sett2.addWidget(ld_rfrhi, 0, 1) lay_sett2.addWidget(lb_rfrhi, 1, 1) lay_sett2.addWidget(ld_n1, 0, 2) lay_sett2.addWidget(lb_n1, 1, 2) lay_sett2.addWidget(ld_hsdiv, 0, 3) lay_sett2.addWidget(lb_hsdiv, 1, 3) lay_eq = QGridLayout() lay_eq.setHorizontalSpacing(12) lay_eq.setVerticalSpacing(6) lay_eq.addWidget(ld_fpgaclk, 1, 0) lay_eq.addWidget(lb_freqmult, 0, 1) lay_eq.addWidget(ld_fraqdiv, 1, 1) lay_eq.addWidget(lb_freqdiv, 2, 1) lay_eq.addWidget(ld_freqdsc, 0, 2) lay_eq.addWidget(ld_freqsp, 1, 2) lay_eq.addWidget(ld_freqrb, 2, 2) lay_eq.addWidget(pb_clkrst, 1, 3) lay = QGridLayout(gbox) lay.setHorizontalSpacing(30) lay.setVerticalSpacing(15) lay.addLayout(lay_sett1, 0, 0, 1, 2, alignment=Qt.AlignLeft) lay.addLayout(lay_sett2, 1, 0, alignment=Qt.AlignLeft) lay.addLayout(lay_eq, 1, 1, alignment=Qt.AlignRight) gbox.setStyleSheet(""" .SiriusSpinbox{max-width: 4.5em;} QComboBox, #n1 {max-width: 2.7em;} #frac {max-width: 1.5em;} #freq, #fpgaclk {max-width: 6.5em;} SiriusLabel{qproperty-alignment: AlignCenter;} """) return gbox
class _EVR_EVE(BaseWidget): """Template for control of High Level Triggers.""" def __init__(self, parent=None, device='', prefix=''): """Initialize object.""" super().__init__(parent, device, prefix) self.device_type = _PVName(device).dev self.setupUi() self.setObjectName('ASApp') def setupUi(self): self.my_layout = QGridLayout(self) self.my_layout.setHorizontalSpacing(20) self.my_layout.setVerticalSpacing(20) self.my_layout.addWidget(self.setupmenus(), 0, 0) lab = QLabel('<h1>' + self.device.device_name + '</h1>', self) self.my_layout.addWidget(lab, 1, 0) self.my_layout.setAlignment(lab, Qt.AlignCenter) # status stattab = QTabWidget(self) stattab.setObjectName('ASTab') stattab.setStyleSheet(""" QTabWidget::pane{ border-left: 2px solid gray; border-bottom: 2px solid gray; border-right: 2px solid gray; }""") self.status_wid = self._setup_status_wid() stattab.addTab(self.status_wid, 'Status') self.info_wid = self._setup_info_wid() stattab.addTab(self.info_wid, 'Fw && IOC') self.my_layout.addWidget(stattab, 2, 0) stattab.setSizePolicy(QSzPol.Preferred, QSzPol.Maximum) # outputs splitter = QSplitter(Qt.Horizontal) splitter.setContentsMargins(0, 0, 0, 0) splitter.setHandleWidth(20) self.my_layout.addWidget(splitter, 3, 0) props = { 'name', 'state', 'event', 'widthraw', 'polarity', 'pulses', 'delayraw', 'evtcnt', 'evtcntrst', 'hl_trigger'} obj_names = ['OTP{0:02d}'.format(i) for i in range(24)] obj_names = [self.device.substitute(propty=o) for o in obj_names] self.otps_wid = EVREVEOTPList( name='Internal Trigger (OTP)', parent=self, prefix=self.prefix, props=props, obj_names=obj_names) self.otps_wid.setObjectName('otps_wid') splitter.addWidget(self.otps_wid) props = { 'name', 'source', 'trigger', 'rf_delayraw', 'rf_delay_type', 'fine_delayraw', 'hl_trigger'} obj_names = ['OUT{0:d}'.format(i) for i in range(8)] obj_names = [self.device.substitute(propty=o) for o in obj_names] self.outs_wid = EVREVEOUTList( name='OUT', parent=self, prefix=self.prefix, props=props, obj_names=obj_names) self.outs_wid.setObjectName('outs_wid') splitter.addWidget(self.outs_wid) splitter.setSizePolicy(QSzPol.Preferred, QSzPol.MinimumExpanding) def setupmenus(self): main_menu = QMenuBar() main_menu.setNativeMenuBar(False) try: fout = LLTimeSearch.get_fout_channel( self.device.substitute(propty='OTP0')) except KeyError: return main_menu menu = main_menu.addMenu('&Uplink') action = menu.addAction(fout) icon = qta.icon('mdi.timer', color=get_appropriate_color('AS')) Win = create_window_from_widget( FOUT, title=fout.device_name, icon=icon) connect_window( action, Win, None, device=fout.device_name, prefix=self.prefix) return main_menu def _setup_status_wid(self): status_wid = QWidget(self) status_lay = QGridLayout(status_wid) status_lay.setVerticalSpacing(30) pvname = self.get_pvname('DevEnbl-Sel') sp = PyDMStateButton(self, init_channel=pvname) pvname = self.get_pvname('DevEnbl-Sts') rb = PyDMLed(self, init_channel=pvname) gb = self._create_small_group( 'Enabled', status_wid, (sp, rb), align_ver=False) status_lay.addWidget(gb, 0, 0) lb = QLabel("<b>Alive</b>") pvname = self.get_pvname('Alive-Mon') rb = SiriusLabel(self, init_channel=pvname) gb = self._create_small_group('', status_wid, (lb, rb)) status_lay.addWidget(gb, 0, 1) lb = QLabel("<b>Network</b>") pvname = self.get_pvname('Network-Mon') rb = SiriusLedAlert(self, init_channel=pvname) rb.offColor, rb.onColor = rb.onColor, rb.offColor gb = self._create_small_group('', status_wid, (lb, rb)) status_lay.addWidget(gb, 0, 2) lb = QLabel("<b>UP Link</b>") pvname = self.get_pvname('LinkStatus-Mon') rb = SiriusLedAlert(self, init_channel=pvname) on_c, off_c = rb.onColor, rb.offColor rb.offColor = on_c rb.onColor = off_c gb = self._create_small_group('', status_wid, (lb, rb)) status_lay.addWidget(gb, 0, 3) lb = QLabel("<b>Interlock Status</b>") pvname = self.get_pvname('IntlkStatus-Mon') rb = SiriusLedAlert(self, init_channel=pvname) gb = self._create_small_group('', status_wid, (lb, rb)) status_lay.addWidget(gb, 0, 4) lb = QLabel("<b>Interlock Enabled</b>") pvname = self.get_pvname('IntlkEnbl-Mon') rb = SiriusLedState(self, init_channel=pvname) gb = self._create_small_group('', status_wid, (lb, rb)) status_lay.addWidget(gb, 0, 5) if self.device_type == 'EVR': wids = list() try: conn = LLTimeSearch.get_connections_from_evg() conn = { dev.propty for dev in conn if dev.device_name == self.device.device_name} conn = {int(p[-1]) for p in conn if p.startswith('OUT')} except KeyError: conn = set() for i in range(8): pvname = self.get_pvname('Los-Mon') if i in conn: rb = SiriusLedAlert(self, init_channel=pvname, bit=i) else: rb = SiriusLedState(self, init_channel=pvname, bit=i) rb.onColor = rb.DarkGreen rb.offColor = rb.LightGreen wids.append(rb) gb = self._create_small_group( 'Down Connection', status_wid, wids, align_ver=False) else: sp = SiriusEnumComboBox( self, init_channel=self.get_pvname('RFOut-Sel')) rb = SiriusLabel(self, init_channel=self.get_pvname('RFOut-Sts')) gb = self._create_small_group('RF Output', status_wid, (sp, rb)) status_lay.addWidget(gb, 0, 6) but = QPushButton(self) but.setToolTip('Open Timestamp, Log and\nDigital Input Controls') but.setIcon(qta.icon('fa5s.ellipsis-v')) but.setDefault(False) but.setAutoDefault(False) but.setObjectName('but') but.setStyleSheet( '#but{min-width:25px; max-width:25px;\ min-height:25px; max-height:25px;\ icon-size:20px;}') but.clicked.connect(self._open_detail_dialog) status_lay.addWidget(but, 0, 7, alignment=Qt.AlignTop) return status_wid def _setup_info_wid(self): info_wid = QWidget(self) info_lay = QGridLayout(info_wid) info_lay.setHorizontalSpacing(15) lb = QLabel("<b>IP</b>") pvname = self.get_pvname(propty='IPAddr-Mon') addr = SiriusLabel(self, init_channel=pvname) pvname = self.get_pvname(propty='IPPort-Mon') port = SiriusLabel(self, init_channel=pvname) gb = self._create_small_group('', info_wid, (lb, addr, port)) info_lay.addWidget(gb, 0, 0, alignment=Qt.AlignTop) lb = QLabel("<b>DevFun</b>") pvname = self.get_pvname(propty='DevFun-Sel') sp = SiriusEnumComboBox(self, init_channel=pvname) pvname = self.get_pvname(propty='DevFun-Sts') rb = SiriusLabel(self, init_channel=pvname) gb = self._create_small_group('', info_wid, (lb, sp, rb)) info_lay.addWidget(gb, 0, 1, alignment=Qt.AlignTop) lb = QLabel("<b>Device Status</b>") pvname = self.get_pvname(propty='DevStatus-Mon') rb = SiriusLabel(self, init_channel=pvname) gb = self._create_small_group('', info_wid, (lb, rb)) info_lay.addWidget(gb, 0, 2, alignment=Qt.AlignTop) lb = QLabel("<b>Download</b>") pvname = self.get_pvname('Download-Cmd') sp = SiriusPushButton( self, label='', icon=qta.icon('fa5s.download'), pressValue=1, releaseValue=0, init_channel=pvname) # ? gb = self._create_small_group('', info_wid, (lb, sp)) info_lay.addWidget(gb, 0, 3, alignment=Qt.AlignTop) lb = QLabel("<b>Save Settings</b>") pvname = self.get_pvname('Save-Cmd') sp = PyDMPushButton( self, label='Save', init_channel=pvname, pressValue=1) gb = self._create_small_group('', info_wid, (lb, sp)) info_lay.addWidget(gb, 0, 4, alignment=Qt.AlignTop) # if self.device_type == 'EVE': lb = QLabel("<b>Clk Mode</b>") pvname = self.get_pvname(propty='ClkMode-RB') rb = SiriusLabel(self, init_channel=pvname) gb = self._create_small_group('', info_wid, (lb, rb)) info_lay.addWidget(gb, 0, 5, alignment=Qt.AlignTop) lb = QLabel("<b>FPGA Clk</b>") pvname = self.get_pvname('FPGAClk-Cte') mon = SiriusLabel(self, init_channel=pvname) mon.showUnits = True pvname = self.get_pvname('FPGAClk-Cte', field='INP') inp = PyDMLineEdit(self, init_channel=pvname) gb = self._create_small_group('', info_wid, (lb, mon, inp)) info_lay.addWidget(gb, 0, 6, alignment=Qt.AlignTop) lb = QLabel("<b>Fw.Version</b>") pvname = self.get_pvname(propty='FwVersion-Cte.SVAL') frmv = SiriusLabel(self, init_channel=pvname) gb = self._create_small_group('', info_wid, (lb, frmv)) gb.layout().setSpacing(3) info_lay.addWidget(gb, 0, 7, alignment=Qt.AlignTop) return info_wid def _create_detail_dialog(self): dialog = SiriusDialog() dialog.setObjectName('ASApp') dialog.setWindowTitle(self.device + ' Timestamp and Log Control') dialog.setWindowIcon(self.windowIcon()) # Timestamp gbox_tim = QGroupBox('Timestamp', self) ld_timsrc = QLabel('<b>Source</b>', self) self.ec_timsrc = SiriusEnumComboBox( self, self.get_pvname('TimestampSrc-Sel')) self.lb_timsrc = SiriusLabel(self, self.get_pvname('TimestampSrc-Sts')) gb_timsrc = self._create_small_group( '', gbox_tim, (ld_timsrc, self.ec_timsrc, self.lb_timsrc)) fr_tim = QFrame() fr_tim.setStyleSheet('.QFrame{border: 1px solid gray;}') ld_timutc = QLabel('<b>UTC</b>', self) self.lb_timutc = SiriusLabel(self, self.get_pvname('UTC-RB')) self.lb_timutc.showUnits = True ld_timsub = QLabel('<b>Subsec</b>') self.lb_timsub = SiriusLabel(self, self.get_pvname('SubSecond-Mon')) self.lb_timsub.showUnits = True lay_tim = QGridLayout(fr_tim) lay_tim.setAlignment(Qt.AlignVCenter) lay_tim.setContentsMargins(0, 0, 0, 0) lay_tim.addWidget(ld_timutc, 0, 0, alignment=Qt.AlignCenter) lay_tim.addWidget(self.lb_timutc, 1, 0, alignment=Qt.AlignCenter) lay_tim.addWidget(ld_timsub, 0, 1, alignment=Qt.AlignCenter) lay_tim.addWidget(self.lb_timsub, 1, 1, alignment=Qt.AlignCenter) lay_tstamp = QGridLayout(gbox_tim) lay_tstamp.addWidget(gb_timsrc, 0, 0) lay_tstamp.addWidget(fr_tim, 0, 1) # Timestamp Log gbox_log = QGroupBox('Timestamp Log', self) ld_logstp = QLabel('<b>Stop Log</b>', self) self.sb_logstp = PyDMStateButton(self, self.get_pvname('stoplog')) self.led_logstp = SiriusLedState(self, self.get_pvname('STOPLOGRBV')) gb_logstp = self._create_small_group( '', gbox_log, (ld_logstp, self.sb_logstp, self.led_logstp)) ld_logrst = QLabel('<b>Reset Log</b>', self) self.sb_logrst = PyDMStateButton(self, self.get_pvname('rstlog')) self.led_logrst = SiriusLedState(self, self.get_pvname('RSTLOGRBV')) gb_logrst = self._create_small_group( '', gbox_log, (ld_logrst, self.sb_logrst, self.led_logrst)) ld_logpul = QLabel('<b>Pull</b>', self) self.bt_logpul = SiriusPushButton( parent=self, init_channel=self.get_pvname('pull'), pressValue=1, releaseValue=0) # ? self.bt_logpul.setIcon(qta.icon('fa5s.arrow-down')) self.bt_logpul.setObjectName('bt') self.bt_logpul.setStyleSheet( '#bt{min-width:25px; max-width:25px; icon-size:20px;}') gb_logpul = self._create_small_group( '', gbox_log, (ld_logpul, self.bt_logpul)) ld_logcnt = QLabel('<b>Log Count</b>', self, alignment=Qt.AlignCenter) self.lb_logcnt = SiriusLabel(self, self.get_pvname('LOGCOUNT')) self.lb_logcnt.showUnits = True self.lb_logcnt.setAlignment(Qt.AlignCenter) ld_logful = QLabel('Full', self) self.led_logful = SiriusLedState(self, self.get_pvname('FULL')) ld_logemp = QLabel('Empty', self) self.led_logemp = SiriusLedState(self, self.get_pvname('EMPTY')) fr_logcnt = QFrame(gbox_log) fr_logcnt.setStyleSheet('.QFrame{border: 1px solid gray;}') lay_logcnt = QGridLayout(fr_logcnt) lay_logcnt.setAlignment(Qt.AlignCenter) lay_logcnt.setContentsMargins(0, 0, 0, 0) lay_logcnt.addWidget(ld_logcnt, 0, 0, 1, 4) lay_logcnt.addWidget(self.lb_logcnt, 1, 0, 1, 4) lay_logcnt.addWidget(ld_logful, 2, 0, alignment=Qt.AlignRight) lay_logcnt.addWidget(self.led_logful, 2, 1, alignment=Qt.AlignTop) lay_logcnt.addWidget(ld_logemp, 2, 2, alignment=Qt.AlignRight) lay_logcnt.addWidget(self.led_logemp, 2, 3, alignment=Qt.AlignTop) ld_logevt = QLabel('<b>Event</b>', self) self.lb_logevt = SiriusLabel(self, self.get_pvname('LOGEVENT')) gb_logevt = self._create_small_group( '', gbox_log, (ld_logevt, self.lb_logevt)) ld_logutc = QLabel('<b>Log UTC</b>', self) self.lb_logutc = SiriusLabel(self, self.get_pvname('LOGUTC')) self.lb_logutc.showUnits = True gb_logutc = self._create_small_group( '', gbox_log, (ld_logutc, self.lb_logutc)) ld_logsub = QLabel('<b>Log Subsec</b>', self) self.lb_logsub = SiriusLabel(self, self.get_pvname('LOGSUBSEC')) self.lb_logsub.showUnits = True gb_logsub = self._create_small_group( '', gbox_log, (ld_logsub, self.lb_logsub)) lay_log = QGridLayout(gbox_log) lay_log.addWidget(gb_logstp, 0, 0, alignment=Qt.AlignTop) lay_log.addWidget(gb_logrst, 0, 1, alignment=Qt.AlignTop) lay_log.addWidget(gb_logpul, 0, 2, alignment=Qt.AlignTop) lay_log.addWidget(gb_logevt, 1, 0, alignment=Qt.AlignTop) lay_log.addWidget(gb_logutc, 1, 1, alignment=Qt.AlignTop) lay_log.addWidget(gb_logsub, 1, 2, alignment=Qt.AlignTop) lay_log.addWidget(fr_logcnt, 0, 3, 2, 1, alignment=Qt.AlignCenter) # Timestamp Log Buffer gbox_buf = QGroupBox('Timestamp Log Buffer', self) ld_bufcnt = QLabel('<b>Log Count</b>', self) self.lb_bufcnt = SiriusLabel(self, self.get_pvname('LOGSOFTCNT')) self.lb_bufcnt.showUnits = True gb_bufcnt = self._create_small_group( '', gbox_buf, (ld_bufcnt, self.lb_bufcnt)) ld_bufrst = QLabel('<b>Reset</b>', self) self.bt_bufrst = SiriusPushButton( parent=self, init_channel=self.get_pvname('rstSoftBuff'), pressValue=1, releaseValue=0) # ? self.bt_bufrst.setIcon(qta.icon('fa5s.sync')) self.bt_bufrst.setObjectName('bt') self.bt_bufrst.setStyleSheet( '#bt{min-width:25px; max-width:25px; icon-size:20px;}') gb_bufrst = self._create_small_group( '', gbox_buf, (ld_bufrst, self.bt_bufrst)) ld_bufutc = QLabel('<b>UTC buffer</b>', self) self.tb_bufutc = self._create_logbuffer_table('UTCbuffer') gb_bufutc = self._create_small_group( '', gbox_buf, (ld_bufutc, self.tb_bufutc)) ld_bufsub = QLabel('<b>Subsec buffer</b>', self) self.tb_bufsub = self._create_logbuffer_table('SUBSECbuffer') gb_bufsub = self._create_small_group( '', gbox_buf, (ld_bufsub, self.tb_bufsub)) ld_bufevt = QLabel('<b>Event buffer</b>', self) self.tb_bufevt = self._create_logbuffer_table('EVENTbuffer') gb_bufevt = self._create_small_group( '', gbox_buf, (ld_bufevt, self.tb_bufevt)) lay_logbuf = QGridLayout(gbox_buf) lay_logbuf.addWidget(gb_bufcnt, 0, 0, 1, 3) lay_logbuf.addWidget(gb_bufrst, 0, 3, 1, 3) lay_logbuf.addWidget(gb_bufutc, 1, 0, 1, 2) lay_logbuf.addWidget(gb_bufsub, 1, 2, 1, 2) lay_logbuf.addWidget(gb_bufevt, 1, 4, 1, 2) wid_timlog = QWidget() lay_timlog = QVBoxLayout(wid_timlog) lay_timlog.addWidget(gbox_tim) lay_timlog.addWidget(gbox_log) lay_timlog.addWidget(gbox_buf) # Digital Inputs obj_names = [ self.device.substitute(propty=f'DIN{i:d}') for i in range(3)] props = set(EVREVEDIList._ALL_PROPS) props.discard('device') self.dis_wid = EVREVEDIList( name='', parent=self, prefix=self.prefix, obj_names=obj_names, props=props) self.dis_wid.setObjectName('dis_wid') # tab and layout tab = QTabWidget() tab.setObjectName('ASTab') tab.addTab(wid_timlog, 'Timestamp && Log') tab.addTab(self.dis_wid, 'Digital Inputs (DI)') lay = QVBoxLayout(dialog) lay.addWidget(tab) return dialog def _open_detail_dialog(self): if not hasattr(self, 'detail_wind'): self.detail_wind = self._create_detail_dialog() self.detail_wind.show() else: self.detail_wind.showNormal()
[docs] class EVR(_EVR_EVE): def __init__(self, parent=None, device='', prefix=''): if 'EVR' not in device: raise ValueError('device has to be an EVR') super().__init__(parent, device, prefix)
[docs] class EVE(_EVR_EVE): def __init__(self, parent=None, device='', prefix=''): if 'EVE' not in device: raise ValueError('device has to be an EVE') super().__init__(parent, device, prefix)
# ###################### EVG & FOUT OUT ######################
[docs] class EVGFOUTOUTList(BaseList): """Template for control of Timing devices Internal Triggers.""" _MIN_WIDs = { 'name': 3, 'connected': 8, 'tripdelay': 4.8, 'position': 4.8, 'outdelay': 4.8, 'rxlocked': 4.8, 'rxlockedltc': 8, 'downlinksts': 6, 'rxenbl': 4, 'connection': 12, } _LABELS = { 'name': 'Name', 'connected': 'Connected', 'tripdelay': 'TripDelay', 'position': 'Position', 'outdelay': 'OutDelay', 'rxlocked': 'RX Locked', 'rxlockedltc': 'RX Locked Lacth', 'downlinksts': 'Downlink', 'rxenbl': 'RX Enbl', 'connection': 'Connection', } _ALL_PROPS = ('name', 'connected', 'tripdelay', 'position', 'outdelay', 'rxlocked', 'rxlockedltc', 'downlinksts', 'rxenbl', 'connection') def __init__(self, **kwargs): srch = set(('name', 'connection')) kwargs['props2search'] = srch super().__init__(**kwargs) def _get_connections(self, device): if not hasattr(self, 'conn_idcs'): try: if device.dev == 'EVG': conn_names = LLTimeSearch.get_evg2fout_mapping() else: conn_map = LLTimeSearch.get_fout2trigsrc_mapping() conn_names = conn_map[device.device_name] conn_idcs = [int(dev[-1]) for dev in conn_names] except KeyError: conn_idcs, conn_names = list(), list() self.conn_idcs, self.conn_names = conn_idcs, conn_names return self.conn_idcs, self.conn_names def _createObjs(self, device, prop): idx_orig = device.idx.split('_')[0] idx = int(device.idx[-1]) device = device.substitute(idx=idx_orig) conn_idcs, conn_names = self._get_connections(device) sp = rb = None if prop == 'name': sp = QLabel('OUT'+str(idx), self) sp.setAlignment(Qt.AlignCenter) elif prop == 'connected': pvname = device.substitute(propty='Los-Mon') if idx in conn_idcs: sp = SiriusLedAlert(self, init_channel=pvname, bit=idx) else: sp = SiriusLedState(self, init_channel=pvname, bit=idx) sp.onColor = sp.DarkGreen sp.offColor = sp.LightGreen elif prop == 'tripdelay': pvname = device.substitute(propty='OUT'+str(idx)+'TripDelay-Mon') sp = SiriusLabel(self, pvname) sp.setAlignment(Qt.AlignCenter) elif prop == 'position': pvname = device.substitute(propty='OUT'+str(idx)+'FramePos-Mon') sp = SiriusLabel(self, pvname) sp.setAlignment(Qt.AlignCenter) elif prop == 'rxlocked': pvname = device.substitute(propty='RxLocked-Mon') sp = SiriusLedState(self, init_channel=pvname, bit=idx) elif prop == 'rxlockedltc': pvname = device.substitute(propty='RxLockedLtc-Mon') sp = SiriusLedState(self, init_channel=pvname, bit=idx) elif prop == 'downlinksts': pvname = device.substitute(propty='DownlinkStatus-Mon') if idx in conn_idcs: sp = SiriusLedAlert(self, init_channel=pvname, bit=idx) else: sp = SiriusLedState(self, init_channel=pvname, bit=idx) sp.onColor = sp.DarkGreen sp.offColor = sp.LightGreen elif prop == 'outdelay': pvname = device.substitute(propty='OUT'+str(idx)+'Delay-SP') sp = SiriusSpinbox(self, pvname) sp.limitsFromChannel = False sp.setMinimum(0) sp.setMaximum(2**31 - 1) pvname = device.substitute(propty='OUT'+str(idx)+'Delay-RB') rb = SiriusLabel(self, pvname) rb.setAlignment(Qt.AlignCenter) elif prop == 'rxenbl': pvname = device.substitute(propty='RxEnbl-SP', field='B'+str(idx)) sp = PyDMStateButton(self, pvname) pvname = device.substitute(propty='RxEnbl-RB') rb = SiriusLedState(self, init_channel=pvname, bit=idx) elif prop == 'connection': txtn = '' if idx in conn_idcs: out = _PVName(conn_names['OUT'+str(idx)]) if device.dev == 'EVG': link = list(LLTimeSearch.In2OutMap['Fout'])[0] else: link = list(LLTimeSearch.In2OutMap[out.dev])[0] txtn = out+'\n'+link sp = QLabel(txtn, self, alignment=Qt.AlignCenter) if rb is None: return (sp, ) return sp, rb
# ###################### Triggers ######################
[docs] class LLTriggerList(BaseList): """Template for control of High Level Triggers.""" _MIN_WIDs = { 'name': 4.5, 'device': 14, 'state': 5.8, 'event': 4.8, 'widthraw': 4.8, 'width': 4.8, 'polarity': 5, 'pulses': 4.8, 'delayraw': 4.8, 'delay': 4.8, 'log': 3.2, 'source': 6.5, 'trigger': 4, 'rf_delayraw': 4.8, 'rf_delay': 6.5, 'fine_delayraw': 4.8, 'fine_delay': 6.5, 'rf_delay_type': 6.5, 'hl_trigger': 10, 'dir': 4.5, 'evtcnt': 5, 'evtcntrst': 4, } _LABELS = { 'name': 'Name', 'device': 'Device', 'state': 'State', 'event': 'Event', 'widthraw': 'Width', 'width': 'Width [us]', 'polarity': 'Polarity', 'pulses': 'Nr Pulses', 'delayraw': 'Delay', 'delay': 'Delay [us]', 'log': 'Log', 'source': 'Source', 'trigger': 'Trigger', 'rf_delayraw': 'RF Delay', 'rf_delay': 'RF Delay [ns]', 'fine_delayraw': 'Fine Delay', 'fine_delay': 'Fine Delay [ps]', 'rf_delay_type': 'RF Delay Type', 'hl_trigger': 'HL Trigger', 'dir': 'Direction', 'evtcnt': 'Evt. Cnt.', 'evtcntrst': 'Rst. Cnt.', } _ALL_PROPS = ( 'device', 'name', 'state', 'event', 'widthraw', 'width', 'polarity', 'pulses', 'delayraw', 'delay', 'log', 'source', 'trigger', 'rf_delayraw', 'rf_delay', 'rf_delay_type', 'fine_delayraw', 'fine_delay', 'hl_trigger', 'dir', 'evtcnt', 'evtcntrst') def __init__(self, **kwargs): srch = set(('device', 'name', 'polarity', 'source', 'dir')) kwargs['props2search'] = srch super().__init__(**kwargs) def _createObjs(self, device, prop): intlb = LLTimeSearch.get_channel_internal_trigger_pvname(device) outlb = LLTimeSearch.get_channel_output_port_pvname(device) sp = rb = None if prop == 'device': devt = outlb.dev if devt == 'EVR': devt = EVR elif devt == 'EVE': devt = EVE else: devt = AFC sp = QPushButton(outlb.device_name, self) sp.setAutoDefault(False) sp.setDefault(False) icon = qta.icon('mdi.timer', color=get_appropriate_color('AS')) Win = create_window_from_widget( devt, title=outlb.device_name, icon=icon) connect_window( sp, Win, None, device=outlb.device_name, prefix=self.prefix) elif prop == 'name': sp = QLabel(outlb.propty, self) sp.setAlignment(Qt.AlignCenter) elif prop == 'hl_trigger': trig = HLTimeSearch.get_hl_from_ll_triggers(device) sp = QLabel(trig, self) sp.setAlignment(Qt.AlignCenter) elif prop == 'state': pvname = intlb.substitute(propty=intlb.propty+'State-Sel') sp = PyDMStateButton(self, init_channel=pvname) pvname = intlb.substitute(propty=intlb.propty+'State-Sts') rb = PyDMLed(self, init_channel=pvname) elif prop == 'event': pvname = intlb.substitute(propty=intlb.propty+'Evt-SP') sp = SiriusSpinbox(self, init_channel=pvname) sp.limitsFromChannel = False sp.setMinimum(0) sp.setMaximum(255) pvname = intlb.substitute(propty=intlb.propty+'Evt-RB') rb = SiriusLabel(self, init_channel=pvname) rb.setAlignment(Qt.AlignCenter) elif prop == 'widthraw': pvname = intlb.substitute(propty=intlb.propty+'WidthRaw-SP') sp = SiriusSpinbox(self, init_channel=pvname) sp.limitsFromChannel = False sp.setMinimum(1) sp.setMaximum(2**31 - 1) pvname = intlb.substitute(propty=intlb.propty+'WidthRaw-RB') rb = SiriusLabel(self, init_channel=pvname) rb.setAlignment(Qt.AlignCenter) elif prop == 'width': pvname = intlb.substitute(propty=intlb.propty+'Width-SP') sp = SiriusSpinbox(self, init_channel=pvname) pvname = intlb.substitute(propty=intlb.propty+'Width-RB') rb = SiriusLabel(self, init_channel=pvname) rb.setAlignment(Qt.AlignCenter) elif prop == 'polarity': pvname = intlb.substitute(propty=intlb.propty+'Polarity-Sel') sp = SiriusEnumComboBox(self, init_channel=pvname) pvname = intlb.substitute(propty=intlb.propty+'Polarity-Sts') rb = SiriusLabel(self, init_channel=pvname) rb.setAlignment(Qt.AlignCenter) elif prop == 'pulses': pvname = intlb.substitute(propty=intlb.propty+'NrPulses-SP') sp = SiriusSpinbox(self, init_channel=pvname) sp.limitsFromChannel = False sp.setMinimum(1) sp.setMaximum(2**31 - 1) pvname = intlb.substitute(propty=intlb.propty+'NrPulses-RB') rb = SiriusLabel(self, init_channel=pvname) rb.setAlignment(Qt.AlignCenter) elif prop == 'delayraw': pvname = intlb.substitute(propty=intlb.propty+'DelayRaw-SP') sp = SiriusSpinbox(self, init_channel=pvname) sp.limitsFromChannel = False sp.setMinimum(0) sp.setMaximum(2**31 - 1) pvname = intlb.substitute(propty=intlb.propty+'DelayRaw-RB') rb = SiriusLabel(self, init_channel=pvname) rb.setAlignment(Qt.AlignCenter) elif prop == 'delay': pvname = intlb.substitute(propty=intlb.propty+'Delay-SP') sp = SiriusSpinbox(self, init_channel=pvname) pvname = intlb.substitute(propty=intlb.propty+'Delay-RB') rb = SiriusLabel(self, init_channel=pvname) rb.setAlignment(Qt.AlignCenter) elif prop == 'log': pvname = intlb.substitute(propty=intlb.propty+'Log-Sel') sp = PyDMStateButton(self, init_channel=pvname) pvname = intlb.substitute(propty=intlb.propty+'Log-Sts') rb = PyDMLed(self, init_channel=pvname) elif prop == 'source': pvname = outlb.substitute(propty=outlb.propty+'Src-Sel') sp = SiriusEnumComboBox(self, init_channel=pvname) pvname = outlb.substitute(propty=outlb.propty+'Src-Sts') rb = SiriusLabel(self, init_channel=pvname) rb.setAlignment(Qt.AlignCenter) elif prop == 'trigger': pvname = outlb.substitute(propty=outlb.propty+'SrcTrig-SP') sp = SiriusSpinbox(self, init_channel=pvname) pvname = outlb.substitute(propty=outlb.propty+'SrcTrig-RB') rb = SiriusLabel(self, init_channel=pvname) rb.setAlignment(Qt.AlignCenter) elif prop == 'rf_delayraw': pvname = outlb.substitute(propty=outlb.propty+'RFDelayRaw-SP') sp = SiriusSpinbox(self, init_channel=pvname) pvname = outlb.substitute(propty=outlb.propty+'RFDelayRaw-RB') rb = SiriusLabel(self, init_channel=pvname) rb.setAlignment(Qt.AlignCenter) elif prop == 'rf_delay': pvname = outlb.substitute(propty=outlb.propty+'RFDelay-SP') sp = SiriusSpinbox(self, init_channel=pvname) pvname = outlb.substitute(propty=outlb.propty+'RFDelay-RB') rb = SiriusLabel(self, init_channel=pvname) rb.setAlignment(Qt.AlignCenter) elif prop == 'rf_delay_type': pvname = outlb.substitute(propty=outlb.propty+'RFDelayType-Sel') sp = SiriusEnumComboBox(self, init_channel=pvname) pvname = outlb.substitute(propty=outlb.propty+'RFDelayType-Sts') rb = SiriusLabel(self, init_channel=pvname) rb.setAlignment(Qt.AlignCenter) elif prop == 'fine_delayraw': pvname = outlb.substitute(propty=outlb.propty+'FineDelayRaw-SP') sp = SiriusSpinbox(self, init_channel=pvname) pvname = outlb.substitute(propty=outlb.propty+'FineDelayRaw-RB') rb = SiriusLabel(self, init_channel=pvname) rb.setAlignment(Qt.AlignCenter) elif prop == 'fine_delay': pvname = outlb.substitute(propty=outlb.propty+'FineDelay-SP') sp = SiriusSpinbox(self, init_channel=pvname) pvname = outlb.substitute(propty=outlb.propty+'FineDelay-RB') rb = SiriusLabel(self, init_channel=pvname) rb.setAlignment(Qt.AlignCenter) elif prop == 'dir': pvname = intlb.substitute(propty=intlb.propty+'Dir-Sel') sp = SiriusEnumComboBox(self, init_channel=pvname) pvname = intlb.substitute(propty=intlb.propty+'Dir-Sts') rb = SiriusLabel(self, init_channel=pvname) rb.setAlignment(Qt.AlignCenter) elif prop == 'evtcnt': pvname = intlb.substitute(propty=intlb.propty+'EvtCnt-Mon') sp = SiriusLabel(self, init_channel=pvname) sp.setAlignment(Qt.AlignCenter) elif prop == 'evtcntrst': pvname = intlb.substitute(propty=intlb.propty+'EvtCntRst-Cmd') sp = PyDMPushButton( self, icon=qta.icon('fa5s.sync'), label='', init_channel=pvname, pressValue=1) sp.setObjectName('rst') sp.setStyleSheet( '#rst{min-width:25px; max-width:25px; icon-size:20px;}') if rb is None: return (sp, ) return sp, rb
[docs] class EVREVEOTPList(LLTriggerList): """Template for control of Timing devices Internal Triggers.""" _ALL_PROPS = ( 'name', 'state', 'event', 'widthraw', 'width', 'polarity', 'pulses', 'delayraw', 'delay', 'evtcnt', 'evtcntrst', 'log', 'hl_trigger')
[docs] class EVREVEOUTList(LLTriggerList): """Template for control of Timing Devices Output Channels.""" _ALL_PROPS = ( 'name', 'source', 'trigger', 'rf_delayraw', 'rf_delay', 'rf_delay_type', 'fine_delayraw', 'fine_delay', 'hl_trigger')
[docs] class AFCOUTList(LLTriggerList): """Template for control of Timing devices Internal Triggers.""" _ALL_PROPS = ( 'name', 'state', 'event', 'source', 'widthraw', 'width', 'polarity', 'pulses', 'delayraw', 'delay', 'dir', 'evtcnt', 'evtcntrst', 'log', 'hl_trigger')
# ###################### Digital Inputs ######################
[docs] class EVREVEDIList(BaseList): """Template for control of Timing devices Internal Triggers.""" _MIN_WIDs = { 'name': 3, 'device': 14, 'state': 5.8, 'polarity': 5, 'event': 4.8, 'log': 3.2, } _LABELS = { 'name': 'Name', 'device': 'Device', 'state': 'State', 'polarity': 'Polarity', 'event': 'Event', 'log': 'Log', } _ALL_PROPS = ('device', 'name', 'state', 'polarity', 'event', 'log') def __init__(self, **kwargs): srch = {'name', 'polarity'} kwargs['props2search'] = srch super().__init__(**kwargs) def _createObjs(self, device, prop): di_idx = device.propty[3:] device = device.substitute(propty='') sp = rb = None if prop == 'device': devt = device.dev if devt == 'EVR': devt = EVR elif devt == 'EVE': devt = EVE sp = QPushButton(device.device_name, self) sp.setAutoDefault(False) sp.setDefault(False) icon = qta.icon('mdi.timer', color=get_appropriate_color('AS')) Win = create_window_from_widget( devt, title=device.device_name, icon=icon) connect_window( sp, Win, None, device=device.device_name, prefix=self.prefix) elif prop == 'name': sp = QLabel('DIN'+di_idx, self) sp.setAlignment(Qt.AlignCenter) elif prop == 'state': pvname = device.substitute(propty='DIN'+di_idx+'State-Sel') sp = PyDMStateButton(self, init_channel=pvname) pvname = device.substitute(propty='DIN'+di_idx+'State-Sts') rb = PyDMLed(self, init_channel=pvname) elif prop == 'polarity': pvname = device.substitute(propty='DIN'+di_idx+'Polarity-Sel') sp = SiriusEnumComboBox(self, init_channel=pvname) pvname = device.substitute(propty='DIN'+di_idx+'Polarity-Sts') rb = SiriusLabel(self, init_channel=pvname) rb.setAlignment(Qt.AlignCenter) elif prop == 'event': pvname = device.substitute(propty='DIN'+di_idx+'Evt-SP') sp = SiriusSpinbox(self, init_channel=pvname) sp.limitsFromChannel = False sp.setMinimum(0) sp.setMaximum(255) pvname = device.substitute(propty='DIN'+di_idx+'Evt-RB') rb = SiriusLabel(self, init_channel=pvname) rb.setAlignment(Qt.AlignCenter) elif prop == 'log': pvname = device.substitute(propty='DIN'+di_idx+'Log-Sel') sp = PyDMStateButton(self, init_channel=pvname) pvname = device.substitute(propty='DIN'+di_idx+'Log-Sts') rb = PyDMLed(self, init_channel=pvname) if rb is None: return (sp, ) return sp, rb