Source code for siriushla.as_ps_control.detail_widget.PSDetailWidget

"""PS Detail Widget."""

import re
from datetime import datetime as _datetime
from functools import partial as _part
import numpy as _np

from qtpy.QtCore import Qt
from qtpy.QtWidgets import QWidget, QGroupBox, QPushButton, QLabel, \
    QGridLayout, QVBoxLayout, QHBoxLayout, QFormLayout, QTabWidget, \
    QSizePolicy as QSzPlcy, QCheckBox, QHeaderView, QAbstractItemView, \
    QScrollArea, QFrame, QComboBox
from qtpy.QtGui import QColor

import qtawesome as qta

from pydm.widgets import PyDMEnumComboBox, PyDMPushButton, PyDMLineEdit
from pydm.widgets.display_format import parse_value_for_display

from siriuspy.util import get_strength_label
from siriuspy.namesys import SiriusPVName
from siriuspy.envars import VACA_PREFIX
from siriuspy.search import PSSearch
from siriuspy.pwrsupply.csdev import get_ps_propty_database, get_ps_modules, \
    DEF_WFMSIZE_FBP, DEF_WFMSIZE_OTHERS, PS_LI_INTLK_THRS as _PS_LI_INTLK, \
    ETypes as _PSet, get_ps_scopesourcemap
from siriuspy.devices import PowerSupply

from ... import util
from ...widgets import PyDMStateButton, PyDMSpinboxScrollbar, SiriusTimePlot, \
    SiriusConnectionSignal, SiriusLedState, SiriusLedAlert, SiriusLabel, \
    PyDMLedMultiChannel, SiriusDialog, SiriusWaveformTable, SiriusSpinbox, \
    SiriusHexaSpinbox, SiriusWaveformPlot, PyDMLed, SiriusStringComboBox, \
    PyDMLinEditScrollbar
from .InterlockWindow import InterlockWindow, LIInterlockWindow
from .custom_widgets import LISpectIntlkLed


class _BaseDetailWidget(QWidget):
    """Widget with some common layouts."""

    StyleSheet = """
        #opmode_sp_cbox{
            min-width: 7em;
            max-width: 7em;
        }
        #opmode_rb_label,
        #psstatus_mon{
            min-width: 7em;
            max-width: 7em;
            qproperty-alignment: AlignCenter;
        }
        #ctrlloop_label,
        #ctrlmode_label {
            min-width: 4em;
            max-width: 4em;
            qproperty-alignment: AlignCenter;
        }
        #pwrstate_label {
            min-width: 2em;
            max-width: 2em;
        }
        #current > SiriusLabel,
        #metric > SiriusLabel {
            min-width: 7em;
            max-width: 7em;
            qproperty-alignment: AlignCenter;
        }
        QLed,
        SiriusLedAlert,
        SiriusLedState {
            min-width: 1.5em;
            max-width: 1.5em;
            min-height: 1.5em;
            max-height: 1.5em;
        }
        PyDMStateButton {
            min-width: 2.5em;
            max-width: 2.5em;
            min-height: 1.5em;
            max-height: 1.5em;
        }
        #auxmeaslabel {
            min-width: 7.5em;
            qproperty-alignment: AlignCenter;
        }
    """

    def __init__(self, psname, parent=None):
        """Class constructor."""
        super(_BaseDetailWidget, self).__init__(parent)
        self._prefix = VACA_PREFIX
        self._psname = SiriusPVName(psname)

        try:
            self._metric = get_strength_label(
                PSSearch.conv_psname_2_magfunc(self._psname))
        except (ValueError, KeyError):
            self._metric = ''

        self._prefixed_psname = self._psname.substitute(prefix=self._prefix)

        self.setObjectName(parent.objectName())

        self.setFocus(True)
        self.setFocusPolicy(Qt.StrongFocus)
        self.setSizePolicy(QSzPlcy.Maximum, QSzPlcy.Maximum)

    @staticmethod
    def conv_time_string(value):
        time_str = _datetime.fromtimestamp(value).strftime('%Y-%m-%d %H:%M:%S')
        time_str += '.{:03d}'.format(int(1e3*(value % 1)))
        return time_str

    def _powerStateLayout(self):
        self.state_button = PyDMStateButton(
            parent=self, init_channel=self._prefixed_psname + ":PwrState-Sel")
        self.pwrstate_led = SiriusLedState(
            parent=self, init_channel=self._prefixed_psname + ":PwrState-Sts")
        self.pwrstate_label = SiriusLabel(
            parent=self, init_channel=self._prefixed_psname + ":PwrState-Sts")
        self.pwrstate_label.setObjectName("pwrstate_label")

        layout = QGridLayout()
        layout.setAlignment(Qt.AlignCenter)
        layout.setHorizontalSpacing(4)
        layout.addWidget(self.state_button, 0, 0, 1, 2, Qt.AlignHCenter)
        layout.addWidget(self.pwrstate_led, 1, 0, Qt.AlignRight)
        layout.addWidget(self.pwrstate_label, 1, 1, Qt.AlignLeft)
        return layout

    def _currentLayout(self, prec=None, has_refmon=True):
        current_sp_label = QLabel("Setpoint")
        current_rb_label = QLabel("Readback")
        current_mon_label = QLabel("Mon")

        self.current_sp_wid = PyDMSpinboxScrollbar(
            self, self._prefixed_psname + ":Current-SP")
        self.current_rb_val = SiriusLabel(
            self, self._prefixed_psname+":Current-RB", keep_unit=True)
        self.current_rb_val.showUnits = True
        self.current_mon_val = SiriusLabel(
            self, self._prefixed_psname+":Current-Mon", keep_unit=True)
        self.current_mon_val.showUnits = True

        if has_refmon:
            current_ref_label = QLabel("Ref Mon")
            self.current_ref_val = SiriusLabel(
                self, self._prefixed_psname+":CurrentRef-Mon", keep_unit=True)
            self.current_ref_val.showUnits = True

        if prec is not None:
            self.current_sp_wid.spinbox.precisionFromPV = False
            self.current_sp_wid.spinbox.precision = prec
            self.current_rb_val.precisionFromPV = False
            self.current_rb_val.precision = prec
            self.current_mon_val.precisionFromPV = False
            self.current_mon_val.precision = prec
            if has_refmon:
                self.current_ref_val.precisionFromPV = False
                self.current_ref_val.precision = prec
        else:
            self.current_rb_val.precisionFromPV = True
            self.current_mon_val.precisionFromPV = True
            if has_refmon:
                self.current_ref_val.precisionFromPV = True

        layout = QGridLayout()
        layout.addWidget(current_sp_label, 0, 0, Qt.AlignRight)
        layout.addWidget(self.current_sp_wid, 0, 1)
        layout.addWidget(current_rb_label, 1, 0, Qt.AlignRight)
        layout.addWidget(self.current_rb_val, 1, 1)
        if has_refmon:
            layout.addWidget(current_ref_label, 2, 0, Qt.AlignRight)
            layout.addWidget(self.current_ref_val, 2, 1)
            layout.addWidget(current_mon_label, 3, 0, Qt.AlignRight)
            layout.addWidget(self.current_mon_val, 3, 1)
        else:
            layout.addWidget(current_mon_label, 2, 0, Qt.AlignRight)
            layout.addWidget(self.current_mon_val, 2, 1)
        layout.setColumnStretch(2, 1)
        return layout

    def _metricLayout(self, prec=None, has_refmon=True):
        metric_sp_ch = self._prefixed_psname+":"+self._metric+"-SP"
        metric_rb_ch = self._prefixed_psname+":"+self._metric+"-RB"
        metric_mon_ch = self._prefixed_psname+":"+self._metric+"-Mon"

        metric_sp_label = QLabel("Setpoint")
        metric_rb_label = QLabel("Readback")
        metric_mon_label = QLabel("Mon")

        self.metric_sp_wid = PyDMSpinboxScrollbar(self, metric_sp_ch)
        self.metric_rb_val = SiriusLabel(
            parent=self, init_channel=metric_rb_ch, keep_unit=True)
        self.metric_rb_val.showUnits = True
        self.metric_mon_val = SiriusLabel(
            parent=self, init_channel=metric_mon_ch, keep_unit=True)
        self.metric_mon_val.showUnits = True

        if has_refmon:
            metric_ref_ch = self._prefixed_psname+":"+self._metric+"Ref-Mon"
            metric_ref_label = QLabel("Ref Mon")
            self.metric_ref_val = SiriusLabel(
                parent=self, init_channel=metric_ref_ch, keep_unit=True)
            self.metric_ref_val.showUnits = True

        if prec is not None:
            self.metric_sp_wid.spinbox.precisionFromPV = False
            self.metric_sp_wid.spinbox.precision = prec
            self.metric_rb_val.precisionFromPV = False
            self.metric_rb_val.precision = prec
            self.metric_mon_val.precisionFromPV = False
            self.metric_mon_val.precision = prec
            if has_refmon:
                self.metric_ref_val.precisionFromPV = False
                self.metric_ref_val.precision = prec
        else:
            self.metric_rb_val.precFromPV = True
            self.metric_mon_val.precFromPV = True
            if has_refmon:
                self.metric_ref_val.precFromPV = True

        layout = QGridLayout()
        layout.addWidget(metric_sp_label, 0, 0, Qt.AlignRight)
        layout.addWidget(self.metric_sp_wid, 0, 1)
        layout.addWidget(metric_rb_label, 1, 0, Qt.AlignRight)
        layout.addWidget(self.metric_rb_val, 1, 1)
        if has_refmon:
            layout.addWidget(metric_ref_label, 2, 0, Qt.AlignRight)
            layout.addWidget(self.metric_ref_val, 2, 1)
            layout.addWidget(metric_mon_label, 3, 0, Qt.AlignRight)
            layout.addWidget(self.metric_mon_val, 3, 1)
        else:
            layout.addWidget(metric_mon_label, 2, 0, Qt.AlignRight)
            layout.addWidget(self.metric_mon_val, 2, 1)
        layout.setColumnStretch(3, 1)
        return layout


[docs] class PSDetailWidget(_BaseDetailWidget): """Widget with control interface for a given magnet.""" AuxDev2ModDict = { 'BO-Fam:PS-B-1': {'A': '1', 'B': '2'}, 'BO-Fam:PS-B-1a': {'A': '3', 'B': '4'}, 'BO-Fam:PS-B-1b': {'A': '5', 'B': '6'}, 'BO-Fam:PS-B-1c': {'A': '7', 'B': '8'}, 'BO-Fam:PS-B-2': {'A': '1', 'B': '2'}, 'BO-Fam:PS-B-2a': {'A': '3', 'B': '4'}, 'BO-Fam:PS-B-2b': {'A': '5', 'B': '6'}, 'BO-Fam:PS-B-2c': {'A': '7', 'B': '8'}, } BasicParams = [ 'Version-Cte', 'Properties-Cte', 'Reset-Cmd', 'Abort-Cmd', 'WfmUpdate-Cmd', 'TimestampBoot-Cte', 'TimestampUpdate-Mon', 'PwrState-Sel', 'PwrState-Sts', 'OpMode-Sel', 'OpMode-Sts', 'CtrlMode-Mon', 'CtrlLoop-Sel', 'CtrlLoop-Sts', 'Current-SP', 'Current-RB', 'CurrentRef-Mon', 'Current-Mon', 'CycleEnbl-Mon', 'CycleIndex-Mon', 'CycleType-Sel', 'CycleType-Sts', 'CycleNrCycles-SP', 'CycleNrCycles-RB', 'CycleFreq-SP', 'CycleFreq-RB', 'CycleAmpl-SP', 'CycleAmpl-RB', 'CycleOffset-SP', 'CycleOffset-RB', 'CycleAuxParam-SP', 'CycleAuxParam-RB', 'WfmIndex-Mon', 'WfmSyncPulseCount-Mon', 'WfmUpdateAuto-Sel', 'WfmUpdateAuto-Sts', 'IDFFMode-Sel', 'IDFFMode-Sts', 'PRUCtrlQueueSize-Mon', 'SyncPulse-Cmd', 'Wfm-SP', 'Wfm-RB', 'WfmRef-Mon', 'Wfm-Mon', 'Voltage-SP', 'Voltage-RB', 'VoltageRef-Mon', 'Voltage-Mon', 'CapacitorBankVoltage-SP', 'CapacitorBankVoltage-RB', 'CapacitorBankVoltageRef-Mon', 'CapacitorBankVoltage-Mon', 'ScopeSrcAddr-SP', 'ScopeSrcAddr-RB', 'ScopeFreq-SP', 'ScopeFreq-RB', 'ScopeDuration-SP', 'ScopeDuration-RB', 'WfmSyncMode-Sel', 'WfmSyncMode-Sts', 'WfmFreq-SP', 'WfmFreq-RB', 'WfmGain-SP', 'WfmGain-RB', 'WfmOffset-SP', 'WfmOffset-RB', ] def __init__(self, psname, parent=None, psmodel=None, pstype=None): """Class constructor.""" super(PSDetailWidget, self).__init__(psname, parent=parent) self._psmodel = psmodel or PSSearch.conv_psname_2_psmodel(psname) self._pstype = pstype or PSSearch.conv_psname_2_pstype(psname) self._db = get_ps_propty_database(self._psmodel, self._pstype) self._mods = get_ps_modules(psmodel=self._psmodel) if self._mods: self._mod2db = { mod: [ pv for pv in self._db if 'Mod'+mod in pv and 'IIB' in pv and 'Intlk' not in pv and 'Alarm' not in pv ] for mod in self._mods } else: self._mod2db = { 'main': [ pv for pv in self._db if 'IIB' in pv and 'Intlk' not in pv and 'Alarm' not in pv ] } self._auxmeasures = [ pv for pv in self._db if pv not in self.BasicParams and 'Intlk' not in pv and 'Alarm' not in pv and (self._metric not in pv if self._metric else True) and 'IIB' not in pv and 'Param' not in pv ] self._params = [ prm for prm in self._db if 'Param' in prm and '-Cte' in prm] self._auxdev = ['', ] self._auxdev2mod = self.AuxDev2ModDict if psname in self._auxdev2mod: self._auxdev = ['', 'a', 'b', 'c'] self._setup_ui() self.setStyleSheet(self.StyleSheet) def _setup_ui(self): # Group boxes that compose the widget self.frmwr_box = QGroupBox("Firmware && IOC") self.frmwr_box.setObjectName("version") self.frmwr_box.setSizePolicy(QSzPlcy.Preferred, QSzPlcy.Maximum) self.interlock_box = QGroupBox("Interlock") self.interlock_box.setObjectName("interlock") self.pwrstate_box = QGroupBox("PwrState") self.pwrstate_box.setObjectName("power_state") self.opmode_box = QGroupBox("OpMode") self.opmode_box.setObjectName("operation_mode") self.ctrlloop_box = QGroupBox('Control Loop') self.ctrlloop_box.setObjectName('ctrlloop_box') if self._psmodel == 'FBP': self.iocmode_box = QGroupBox('IOC Mode') self.iocmode_box.setObjectName('iocmode_box') self.genparams_box = QGroupBox('General Params') self.genparams_box.setObjectName('genparams_box') self.current_box = QGroupBox("Current") self.current_box.setObjectName("current") self.siggen_tab = QWidget() self.siggen_tab.setObjectName('cycle_tab') self.wfmplot_tab = QWidget() self.wfmplot_tab.setObjectName("wfm_tab") self.wfmparams_tab = QWidget() self.wfmparams_tab.setObjectName('wfmparams_tab') self.curve_tabs = QTabWidget() self.curve_tabs.setObjectName(self._psname.sec+'Tab') self.curve_tabs.setStyleSheet( '#'+self._psname.sec+'Tab::pane {' ' border-left: 2px solid gray;' ' border-bottom: 2px solid gray;' ' border-right: 2px solid gray;}') self.curve_tabs.addTab(self.siggen_tab, 'SigGen') self.curve_tabs.addTab(self.wfmplot_tab, 'WfmPlot') self.curve_tabs.addTab(self.wfmparams_tab, 'WfmParams') if self._psname.sec == 'BO': self.curve_tabs.setCurrentIndex(1) if self._metric: self.metric_box = QGroupBox(self._metric) self.metric_box.setObjectName("metric") # Set group boxes layouts self.frmwr_box.setLayout(self._frmwrLayout()) self.interlock_box.setLayout(self._interlockLayout()) self.pwrstate_box.setLayout(self._powerStateLayout()) self.opmode_box.setLayout(self._opModeLayout()) self.ctrlloop_box.setLayout(self._ctrlLoopLayout()) if self._psmodel == 'FBP': self.iocmode_box.setLayout(self._iocModeLayout()) self.genparams_box.setLayout(self._genParamsLayout()) self.current_box.setLayout(self._currentLayout()) self.siggen_tab.setLayout(self._siggenLayout()) self.wfmplot_tab.setLayout(self._wfmplotLayout()) self.wfmparams_tab.setLayout(self._wfmparamsLayout()) if self._metric: self.metric_box.setLayout(self._metricLayout()) # Add group boxes to laytout self.layout = self._setWidgetLayout() # Set widget layout self.setLayout(self.layout) def _setWidgetLayout(self): controls = QGridLayout() controls.addWidget(self.frmwr_box, 0, 0, 1, 2) controls.addWidget(self.opmode_box, 2, 0) controls.addWidget(self.pwrstate_box, 2, 1) controls.addWidget(self.ctrlloop_box, 3, 0) controls.addWidget(self.interlock_box, 3, 1) if self._psmodel == 'FBP': controls.addWidget(self.genparams_box, 4, 0) controls.addWidget(self.iocmode_box, 4, 1) else: controls.addWidget(self.genparams_box, 4, 0, 1, 2) analogs = QVBoxLayout() analogs.addWidget(self.current_box, Qt.AlignCenter) if self._metric: analogs.addWidget(self.metric_box, Qt.AlignCenter) analogs.addWidget(self.curve_tabs, Qt.AlignCenter) boxes_layout = QHBoxLayout() boxes_layout.addLayout(controls) boxes_layout.addLayout(analogs) boxes_layout.setStretch(0, 1) boxes_layout.setStretch(1, 1) dclink_button = QPushButton('DCLink', self) dclink_button.setObjectName('dclink_button') layout = QVBoxLayout() layout.addWidget(QLabel("<h2>" + self._psname + "</h2>")) layout.addLayout(boxes_layout) layout.addWidget(dclink_button) return layout def _frmwrLayout(self): self.version_label = QLabel('ARM & DSP') self.version_label.setObjectName("version_label") self.version_label.setSizePolicy(QSzPlcy.Minimum, QSzPlcy.Maximum) self.version_cte = SiriusLabel( self, self._prefixed_psname + ":Version-Cte") self.version_cte.displayFormat = \ SiriusLabel.DisplayFormat.BSMPUDCVersion self.version_cte.setObjectName("version_cte_label") self.version_cte.setSizePolicy(QSzPlcy.Minimum, QSzPlcy.Maximum) self.tstamp_boot_label = QLabel('IOC Boot') self.tstamp_boot_label.setObjectName("tstamp_label") self.tstamp_boot_label.setSizePolicy(QSzPlcy.Minimum, QSzPlcy.Maximum) self.tstamp_boot = QLabel('', self) self.tstamp_boot_ch = SiriusConnectionSignal( self._prefixed_psname + ":TimestampBoot-Cte") self.tstamp_boot_ch.new_value_signal[float].connect( self._tstamp_boot_met) self.tstamp_boot.setObjectName("tstamp_boot_label") self.tstamp_boot.setSizePolicy(QSzPlcy.Minimum, QSzPlcy.Maximum) self.tstamp_update_label = QLabel('IOC Update') self.tstamp_update_label.setObjectName("tstamp_label") self.tstamp_update_label.setSizePolicy( QSzPlcy.Minimum, QSzPlcy.Maximum) self.tstamp_update = QLabel('', self) self.tstamp_update_ch = SiriusConnectionSignal( self._prefixed_psname + ":TimestampUpdate-Mon") self.tstamp_update_ch.new_value_signal[float].connect( self._tstamp_update_met) self.tstamp_update.setObjectName("tstamp_update_label") self.tstamp_update.setSizePolicy(QSzPlcy.Minimum, QSzPlcy.Maximum) layout = QGridLayout() layout.addWidget(self.version_label, 0, 0, Qt.AlignHCenter) layout.addWidget(self.version_cte, 0, 1, Qt.AlignHCenter) layout.addWidget(self.tstamp_boot_label, 1, 0, Qt.AlignHCenter) layout.addWidget(self.tstamp_boot, 1, 1, Qt.AlignHCenter) layout.addWidget(self.tstamp_update_label, 2, 0, Qt.AlignHCenter) layout.addWidget(self.tstamp_update, 2, 1, Qt.AlignHCenter) return layout def _tstamp_update_met(self, value): time_str = self.conv_time_string(value) self.tstamp_update.setText(time_str) def _tstamp_boot_met(self, value): time_str = self.conv_time_string(value) self.tstamp_boot.setText(time_str) def _interlockLayout(self): # Widgets self.soft_label = QLabel('Soft', self, alignment=Qt.AlignCenter) self.soft_intlk_bt = QPushButton(qta.icon('fa5s.list-ul'), '', self) self.soft_intlk_bt.setObjectName('soft_intlk_bt') self.soft_intlk_bt.setStyleSheet( '#soft_intlk_bt{min-width:25px; max-width:25px; icon-size:20px;}') util.connect_window( self.soft_intlk_bt, InterlockWindow, self, devname=self._psname, database=self._db, interlock='IntlkSoft', auxdev=self._auxdev, auxdev2mod=self._auxdev2mod) self.soft_intlk_led = SiriusLedAlert( parent=self, init_channel=self._prefixed_psname + ":IntlkSoft-Mon") self.hard_label = QLabel('Hard', self, alignment=Qt.AlignCenter) self.hard_intlk_bt = QPushButton(qta.icon('fa5s.list-ul'), '', self) self.hard_intlk_bt.setObjectName('hard_intlk_bt') self.hard_intlk_bt.setStyleSheet( '#hard_intlk_bt{min-width:25px; max-width:25px; icon-size:20px;}') util.connect_window( self.hard_intlk_bt, InterlockWindow, self, devname=self._psname, database=self._db, interlock='IntlkHard', auxdev=self._auxdev, auxdev2mod=self._auxdev2mod) self.hard_intlk_led = SiriusLedAlert( parent=self, init_channel=self._prefixed_psname + ":IntlkHard-Mon") iib_intlks = [k.replace('Labels-Cte', '') for k in self._db if re.match('IntlkIIB.*Labels-Cte', k)] if iib_intlks: self.iib_label = QLabel('IIB', self, alignment=Qt.AlignCenter) self.iib_intlk_bt = QPushButton( qta.icon('fa5s.list-ul'), '', self) self.iib_intlk_bt.setObjectName('iib_intlk_bt') self.iib_intlk_bt.setStyleSheet( "#iib_intlk_bt{min-width:25px;max-width:25px;icon-size:20px;}") util.connect_window( self.iib_intlk_bt, InterlockWindow, self, devname=self._psname, database=self._db, interlock=iib_intlks, auxdev=self._auxdev, auxdev2mod=self._auxdev2mod) chs2vals = dict() for aux in self._auxdev: chs2vals.update({self._prefixed_psname+aux+":"+intlk+"-Mon": 0 for intlk in iib_intlks}) self.iib_intlk_led = PyDMLedMultiChannel(self, chs2vals) alarms = ['Alarms', ] if 'Alarms-Mon' in self._db else [] alarms.extend([k.replace('Labels-Cte', '') for k in self._db if re.match('AlarmsIIB.*Labels-Cte', k)]) if alarms: self.alarm_label = QLabel( 'Alarms', self, alignment=Qt.AlignCenter) self.alarm_bt = QPushButton(qta.icon('fa5s.list-ul'), '', self) self.alarm_bt.setObjectName('alarm_bt') self.alarm_bt.setStyleSheet( '#alarm_bt{min-width:25px;max-width:25px;icon-size:20px;}') util.connect_window( self.alarm_bt, InterlockWindow, self, devname=self._psname, database=self._db, interlock=alarms, auxdev=self._auxdev, auxdev2mod=self._auxdev2mod) chs2vals = dict() for aux in self._auxdev: chs2vals.update({self._prefixed_psname+aux+":"+alarm+"-Mon": 0 for alarm in alarms}) self.alarm_led = PyDMLedMultiChannel( self, chs2vals, color_list=[PyDMLed.Yellow, PyDMLed.LightGreen, PyDMLed.Gray]) self.reset_bt = PyDMPushButton( parent=self, icon=qta.icon('fa5s.sync'), pressValue=1, init_channel=self._prefixed_psname + ":Reset-Cmd") self.reset_bt.setObjectName('reset_bt') self.reset_bt.setStyleSheet( '#reset_bt{min-width:25px; max-width:25px; icon-size:20px;}') # Build layout layout = QGridLayout() layout.setAlignment(Qt.AlignCenter) layout.addWidget(self.soft_intlk_bt, 0, 0) layout.addWidget(self.soft_label, 0, 1) layout.addWidget(self.soft_intlk_led, 0, 2) layout.addWidget(self.hard_intlk_bt, 1, 0) layout.addWidget(self.hard_label, 1, 1) layout.addWidget(self.hard_intlk_led, 1, 2) if iib_intlks: layout.addWidget(self.iib_intlk_bt, 2, 0) layout.addWidget(self.iib_label, 2, 1) layout.addWidget(self.iib_intlk_led, 2, 2) if alarms: layout.addWidget(self.alarm_bt, 3, 0) layout.addWidget(self.alarm_label, 3, 1) layout.addWidget(self.alarm_led, 3, 2) layout.addWidget(self.reset_bt, 4, 2) return layout def _opModeLayout(self): self.opmode_sp = PyDMEnumComboBox( self, self._prefixed_psname + ":OpMode-Sel") self.opmode_sp.setObjectName("opmode_sp_cbox") self.opmode_rb = SiriusLabel( self, self._prefixed_psname + ":OpMode-Sts") self.opmode_rb.setObjectName("opmode_rb_label") self.ctrlmode_led = SiriusLedAlert( self, self._prefixed_psname + ":CtrlMode-Mon") self.ctrlmode_label = SiriusLabel( self, self._prefixed_psname + ":CtrlMode-Mon") self.ctrlmode_label.setObjectName("ctrlmode_label") ctrlmode_layout = QHBoxLayout() ctrlmode_layout.addWidget(self.ctrlmode_led) ctrlmode_layout.addWidget(self.ctrlmode_label) layout = QGridLayout() layout.setAlignment(Qt.AlignCenter) layout.addWidget(self.opmode_sp, 0, 0, Qt.AlignHCenter) layout.addWidget(self.opmode_rb, 1, 0, Qt.AlignHCenter) layout.addLayout(ctrlmode_layout, 2, 0, Qt.AlignHCenter) return layout def _ctrlLoopLayout(self): self.ctrlloop_btn = PyDMStateButton( parent=self, init_channel=self._prefixed_psname + ":CtrlLoop-Sel", invert=True) self.ctrlloop_label = SiriusLabel( parent=self, init_channel=self._prefixed_psname + ":CtrlLoop-Sts") self.ctrlloop_label.setObjectName('ctrlloop_label') self.ctrlloop_led = SiriusLedState( parent=self, init_channel=self._prefixed_psname + ":CtrlLoop-Sts") self.ctrlloop_led.setOffColor(SiriusLedState.LightGreen) self.ctrlloop_led.setOnColor(SiriusLedState.DarkGreen) lay_sts = QHBoxLayout() lay_sts.addWidget(self.ctrlloop_led) lay_sts.addWidget(self.ctrlloop_label) layout = QGridLayout() layout.setAlignment(Qt.AlignCenter) layout.addWidget(self.ctrlloop_btn, 0, 0, Qt.AlignHCenter) layout.addLayout(lay_sts, 1, 0) return layout def _siggenLayout(self): # Tab self.tab_siggen = QTabWidget(self) self.tab_siggen.setObjectName(self._psname.sec+'Tab') enbl_mon_ca = self._prefixed_psname + ':CycleEnbl-Mon' type_sp_ca = self._prefixed_psname + ':CycleType-Sel' type_rb_ca = self._prefixed_psname + ':CycleType-Sts' nrcycles_sp_ca = self._prefixed_psname + ':CycleNrCycles-SP' nrcycles_rb_ca = self._prefixed_psname + ':CycleNrCycles-RB' index_ca = self._prefixed_psname + ':CycleIndex-Mon' freq_sp_ca = self._prefixed_psname + ':CycleFreq-SP' freq_rb_ca = self._prefixed_psname + ':CycleFreq-RB' ampl_sp_ca = self._prefixed_psname + ':CycleAmpl-SP' ampl_rb_ca = self._prefixed_psname + ':CycleAmpl-RB' offset_sp_ca = self._prefixed_psname + ':CycleOffset-SP' offset_rb_ca = self._prefixed_psname + ':CycleOffset-RB' auxparam_sp_ca = self._prefixed_psname + ':CycleAuxParam-SP' auxparam_rb_ca = self._prefixed_psname + ':CycleAuxParam-RB' # Params self.cycle_enbl_label = QLabel('Enabled', self) self.cycle_enbl_mon_led = SiriusLedState(self, enbl_mon_ca) self.cycle_type_label = QLabel('Type', self) self.cycle_type_sp_cb = PyDMEnumComboBox(self, type_sp_ca) self.cycle_type_rb_label = SiriusLabel(self, type_rb_ca) self.cycle_nr_label = QLabel('Nr. Cycles', self) self.cycle_nr_sp_sb = PyDMLineEdit(self, nrcycles_sp_ca) self.cycle_nr_rb_label = SiriusLabel(self, nrcycles_rb_ca) self.cycle_index_label = QLabel('Index', self) self.cycle_index_mon_label = SiriusLabel(self, index_ca) self.cycle_freq_label = QLabel('Frequency', self) self.cycle_freq_sp_sb = PyDMLineEdit(self, freq_sp_ca) self.cycle_freq_rb_label = SiriusLabel(self, freq_rb_ca) self.cycle_ampl_label = QLabel('Amplitude', self) self.cycle_ampl_sp_sb = PyDMLineEdit(self, ampl_sp_ca) self.cycle_ampl_rb_label = SiriusLabel(self, ampl_rb_ca) self.cycle_offset_label = QLabel('Offset', self) self.cycle_offset_sp_sb = PyDMLineEdit(self, offset_sp_ca) self.cycle_offset_rb_label = SiriusLabel(self, offset_rb_ca) self.cycle_auxparam_label = QLabel('AuxParams', self) self.cycle_auxparam_sp_le = PyDMLineEdit(self, auxparam_sp_ca) self.cycle_auxparam_rb_label = SiriusLabel(self, auxparam_rb_ca) self.cycle_auxparam_helpbut = QPushButton( qta.icon('mdi.help'), '', self) self.cycle_auxparam_helpbut.setToolTip( 'Show AuxParam help message') self.cycle_auxparam_helpbut.setObjectName('help_bt') self.cycle_auxparam_helpbut.setStyleSheet( '#help_bt{min-width:20px;max-width:20px;icon-size:16px;}') self.cycle_auxparam_helpwid = QWidget() self.cycle_auxparam_helpwid.setObjectName(self.parent().objectName()) self.cycle_auxparam_helpwid.setWindowTitle('AuxParam Help Message') self.cycle_auxparam_helpbut.clicked.connect( self.cycle_auxparam_helpwid.show) text = getattr(PowerSupply, 'cycle_aux_param').__doc__ self.cycle_auxparam_helplab = QLabel(text, self) lay_help = QHBoxLayout(self.cycle_auxparam_helpwid) lay_help.addWidget(self.cycle_auxparam_helplab) parms = QWidget() lay_parms = QGridLayout(parms) lay_parms.setAlignment(Qt.AlignTop) lay_parms.addWidget(self.cycle_enbl_label, 0, 0, Qt.AlignRight) lay_parms.addWidget(self.cycle_enbl_mon_led, 0, 1, Qt.AlignCenter) lay_parms.addWidget(self.cycle_type_label, 1, 0, Qt.AlignRight) lay_parms.addWidget(self.cycle_type_sp_cb, 1, 1) lay_parms.addWidget(self.cycle_type_rb_label, 1, 2, 1, 2) lay_parms.addWidget(self.cycle_nr_label, 2, 0, Qt.AlignRight) lay_parms.addWidget(self.cycle_nr_sp_sb, 2, 1) lay_parms.addWidget(self.cycle_nr_rb_label, 2, 2, 1, 2) lay_parms.addWidget(self.cycle_index_label, 3, 0, Qt.AlignRight) lay_parms.addWidget(self.cycle_index_mon_label, 3, 2, 1, 2) lay_parms.addWidget(self.cycle_freq_label, 4, 0, Qt.AlignRight) lay_parms.addWidget(self.cycle_freq_sp_sb, 4, 1) lay_parms.addWidget(self.cycle_freq_rb_label, 4, 2, 1, 2) lay_parms.addWidget(self.cycle_ampl_label, 5, 0, Qt.AlignRight) lay_parms.addWidget(self.cycle_ampl_sp_sb, 5, 1) lay_parms.addWidget(self.cycle_ampl_rb_label, 5, 2, 1, 2) lay_parms.addWidget(self.cycle_offset_label, 6, 0, Qt.AlignRight) lay_parms.addWidget(self.cycle_offset_sp_sb, 6, 1) lay_parms.addWidget(self.cycle_offset_rb_label, 6, 2, 1, 2) lay_parms.addWidget(self.cycle_auxparam_label, 7, 0, Qt.AlignRight) lay_parms.addWidget(self.cycle_auxparam_sp_le, 7, 1) lay_parms.addWidget(self.cycle_auxparam_rb_label, 7, 2) lay_parms.addWidget(self.cycle_auxparam_helpbut, 7, 3) self.tab_siggen.addTab(parms, 'Params') # Default Curve try: self._siggen = PSSearch.conv_psname_2_siggenconf(self._psname) except KeyError: self._siggen = None if self._siggen is not None: self._siggen_nrpts = DEF_WFMSIZE_FBP if self._psmodel == 'FBP' \ else DEF_WFMSIZE_OTHERS self._siggen_w = self._siggen.get_waveform(self._siggen_nrpts) self.curve_siggen = SiriusWaveformPlot() self.curve_siggen.setObjectName('graph') self.curve_siggen.setStyleSheet( '#graph{max-height:15em; max-width:16.5em;}') self.curve_siggen.setLabel('left', text='Current [A]', color='gray') self.curve_siggen.setLabel('bottom', text='Time [s]', color='gray') self.curve_siggen.setSizePolicy(QSzPlcy.Maximum, QSzPlcy.Maximum) self.curve_siggen.autoRangeX = True self.curve_siggen.autoRangeY = True self.curve_siggen.showXGrid = True self.curve_siggen.showYGrid = True self.curve_siggen.setBackgroundColor(QColor(255, 255, 255)) self.curve_siggen.addChannel( y_channel='SigGen', x_channel='T [s]', color='black', lineWidth=2) self.curve_siggen.curve = self.curve_siggen.curveAtIndex(0) self.curve_siggen.curve.receiveXWaveform(_np.array(self._siggen_w[1])) self.curve_siggen.curve.receiveYWaveform(_np.array(self._siggen_w[0])) self.curve_siggen.curve.redrawCurve() defcurve = QWidget() lay_defcurve = QGridLayout(defcurve) lay_defcurve.addWidget(self.curve_siggen) self.tab_siggen.addTab(defcurve, 'Default Curve') layout = QGridLayout() layout.setContentsMargins(0, 6, 0, 0) layout.addWidget(self.tab_siggen, 0, 0) return layout def _iocModeLayout(self): idff_mode_sel = self._prefixed_psname + ':IDFFMode-Sel' idff_mode_sts = self._prefixed_psname + ':IDFFMode-Sts' idff_mode_label = QLabel('IDFF', self) idff_mode_btn = PyDMStateButton(self, idff_mode_sel) idff_mode_led = SiriusLedState(self, idff_mode_sts) layout = QGridLayout() layout.setAlignment(Qt.AlignTop) layout.setColumnStretch(2, 1) layout.addWidget(idff_mode_label, 0, 0, Qt.AlignRight) layout.addWidget(idff_mode_btn, 0, 1, Qt.AlignHCenter) layout.addWidget(idff_mode_led, 0, 2) return layout def _genParamsLayout(self): queue_size_ca = self._prefixed_psname + ':PRUCtrlQueueSize-Mon' queue_size_label = QLabel('IOC Queue Size', self) queue_size_rb_label = SiriusLabel(self, queue_size_ca) layout = QGridLayout() layout.setAlignment(Qt.AlignTop) layout.setColumnStretch(3, 1) layout.addWidget(queue_size_label, 0, 0, Qt.AlignRight) layout.addWidget(queue_size_rb_label, 0, 1) if 'DCLink' not in self._prefixed_psname: syncpulse_cmd_ca = self._prefixed_psname + ':SyncPulse-Cmd' syncpulse_cmd_lb = QLabel('Sync Pulse Cmd', self) syncpulse_cmd_btn = PyDMPushButton( parent=self, icon=qta.icon('fa5s.step-forward'), pressValue=1, init_channel=syncpulse_cmd_ca) syncpulse_cmd_btn.setObjectName('syncpulse') syncpulse_cmd_btn.setStyleSheet( '#syncpulse{min-width:25px; max-width:32px; icon-size:20px;}') layout.addWidget(syncpulse_cmd_lb, 1, 0, Qt.AlignRight) layout.addWidget(syncpulse_cmd_btn, 1, 1) pbaux = QPushButton( qta.icon('mdi.open-in-new'), 'Aux. Measures', self) util.connect_window( pbaux, PSAuxMeasWidget, self, psname=self._psname, auxmeas=self._auxmeasures, mod2dbase=self._mod2db, auxdev=self._auxdev, auxdev2mod=self._auxdev2mod) layout.addWidget(pbaux, 2, 0, 1, 2) pbprm = QPushButton(qta.icon('mdi.open-in-new'), 'Parameters', self) util.connect_window( pbprm, PSParamsWidget, self, psname=self._psname, params=self._params) layout.addWidget(pbprm, 3, 0, 1, 2) return layout def _wfmplotLayout(self): # graph self.wfm_graph = SiriusWaveformPlot() self.wfm_graph.setObjectName('graph') self.wfm_graph.setStyleSheet( '#graph{max-height:15em; max-width:16.5em;}') self.wfm_graph.setSizePolicy(QSzPlcy.Maximum, QSzPlcy.Maximum) self.wfm_graph.autoRangeX = True self.wfm_graph.autoRangeY = True self.wfm_graph.showXGrid = True self.wfm_graph.showYGrid = True self.wfm_graph.setLabel('left', text='Current [A]', color='gray') self.wfm_graph.setLabel('bottom', text='Time [s]') self.wfm_graph.plotItem.ctrl.fftCheck.toggled.connect( self._wfmUpdAxisLabel) self.wfm_graph.setBackgroundColor(QColor(255, 255, 255)) # nrpts label self.wfm_nrpts_lb = QLabel('Nrpts (SP|RB|Ref-Mon|Mon):', self) self.wfm_nrpts_lb.setSizePolicy(QSzPlcy.Maximum, QSzPlcy.Maximum) # checkbox layout hbox_show = QHBoxLayout() hbox_show.setSpacing(9) # create auxiliary channels self._scopedur_ch_rb = SiriusConnectionSignal( self._prefixed_psname + ':ScopeDuration-RB') self._scopefreq_ch_rb = SiriusConnectionSignal( self._prefixed_psname + ':ScopeFreq-RB') self._wfmfreq_ch_rb = SiriusConnectionSignal( self._prefixed_psname + ':ParamWfmRefFreq-Cte') # fill graph, label and show layout self._wfm_chs, self._wfm_nrpts = dict(), dict() self._wfm_curves, self._wfm_show_cbs = dict(), dict() suf2color = { '-SP': 'red', '-RB': 'blue', 'Ref-Mon': 'green', '-Mon': 'black', } for idx, suf in enumerate(suf2color): propty = 'Wfm' + suf color = suf2color[suf] channel = self._prefixed_psname + ':' + propty # initialize nrpts self._wfm_nrpts[suf] = 0 # create channel to listen curve updates self._wfm_chs[suf] = SiriusConnectionSignal(channel) # listen to curve channel to update NrPts label self._wfm_chs[suf].new_value_signal[_np.ndarray].connect( self._update_wfm_nrpts_label) # add curve to wfm_graph self.wfm_graph.addChannel( y_channel=channel, name=propty, color=color, lineWidth=2) curve = self.wfm_graph.curveAtIndex(idx) # change xdata to show time indices according to ScopeDuration-RB curvetype = 'scope' if propty == 'Wfm-Mon' else 'wfm' self._scopedur_ch_rb.new_value_signal[float].connect( _part(self._wfmTimeData, propty)) self._wfm_chs[suf].new_value_signal[_np.ndarray].connect( _part(self._wfmTimeData, propty)) # reimplement fourier transform to use ScopeFreq-RB curve._fourierTransform = _part(self._wfmFourierData, curvetype) self._wfm_curves[propty] = curve # fill checkbox layout cbx = QCheckBox(suf.strip('-')) cbx.setChecked(True) cbx.setStyleSheet('color: '+color+';') cbx.stateChanged.connect(self._wfm_curves[propty].setVisible) self._wfm_show_cbs[propty] = cbx hbox_show.addWidget(cbx) layout = QVBoxLayout() layout.setAlignment(Qt.AlignCenter) layout.addWidget(self.wfm_graph) layout.addWidget(self.wfm_nrpts_lb) layout.addLayout(hbox_show) return layout def _wfmparamsLayout(self): # --- scope groupbox ---- src_sp = self._prefixed_psname + ':ScopeSrcAddr-SP' src_rb = self._prefixed_psname + ':ScopeSrcAddr-RB' freq_sp = self._prefixed_psname + ':ScopeFreq-SP' freq_rb = self._prefixed_psname + ':ScopeFreq-RB' dur_sp = self._prefixed_psname + ':ScopeDuration-SP' dur_rb = self._prefixed_psname + ':ScopeDuration-RB' self.scope_src_label = QLabel('Source', self) self.scope_src_sp_sb = SiriusHexaSpinbox(self, src_sp) self.scope_src_rb_lb = SiriusLabel(self, src_rb) self.scope_src_rb_lb.displayFormat = SiriusLabel.DisplayFormat.Hex self.scope_freq_label = QLabel('Frequency [Hz]', self) self.scope_freq_sp_sb = SiriusSpinbox(self, freq_sp) self.scope_freq_rb_lb = SiriusLabel(self, freq_rb, keep_unit=True) self.scope_freq_rb_lb.showUnits = True self.scope_dur_label = QLabel('Duration [s]', self) self.scope_dur_sp_sb = SiriusSpinbox(self, dur_sp) self.scope_dur_rb_lb = SiriusLabel(self, dur_rb) self.scope_dur_rb_lb.showUnits = True layout_scope = QGridLayout() layout_scope.setAlignment(Qt.AlignTop) layout_scope.setContentsMargins(6, 6, 3, 3) layout_scope.addWidget(self.scope_src_label, 0, 0, Qt.AlignRight) layout_scope.addWidget(self.scope_src_rb_lb, 0, 3) layout_scope.addWidget( self.scope_freq_label, 1, 0, 1, 2, Qt.AlignRight) layout_scope.addWidget(self.scope_freq_sp_sb, 1, 2) layout_scope.addWidget(self.scope_freq_rb_lb, 1, 3) layout_scope.addWidget(self.scope_dur_label, 2, 0, 1, 2, Qt.AlignRight) layout_scope.addWidget(self.scope_dur_sp_sb, 2, 2) layout_scope.addWidget(self.scope_dur_rb_lb, 2, 3) try: self.scope_src_sp_cb = SiriusStringComboBox( self, src_sp, items=get_ps_scopesourcemap(self._psname)) self.scope_src_sp_opt = QComboBox(self) self.scope_src_sp_opt.addItems(['[list]', '[0x]']) self.scope_src_sp_opt.currentIndexChanged.connect( self.scope_src_sp_cb.setHidden) self.scope_src_sp_opt.currentIndexChanged.connect( self.scope_src_sp_sb.setVisible) self.scope_src_sp_sb.setVisible(False) layout_scope.addWidget(self.scope_src_label, 0, 0, Qt.AlignRight) layout_scope.addWidget(self.scope_src_sp_opt, 0, 1) layout_scope.addWidget(self.scope_src_sp_cb, 0, 2) layout_scope.addWidget(self.scope_src_sp_sb, 0, 2) except KeyError: layout_scope.addWidget( self.scope_src_label, 0, 0, 1, 2, Qt.AlignRight) layout_scope.addWidget(self.scope_src_sp_sb, 0, 2) self.scope_box = QGroupBox("Scope") self.scope_box.setObjectName("Scope") self.scope_box.setSizePolicy(QSzPlcy.Preferred, QSzPlcy.Maximum) self.scope_box.setLayout(layout_scope) # --- wfm groupbox --- wfm_selected_mon = self._prefixed_psname + ':WfmSelected-Mon' wfm_syncmode_sel = self._prefixed_psname + ':WfmSyncMode-Sel' wfm_syncmode_sts = self._prefixed_psname + ':WfmSyncMode-Sts' wfm_freq_sp = self._prefixed_psname + ':WfmFreq-SP' wfm_freq_rb = self._prefixed_psname + ':WfmFreq-RB' wfm_gain_sp = self._prefixed_psname + ':WfmGain-SP' wfm_gain_rb = self._prefixed_psname + ':WfmGain-RB' wfm_offset_sp = self._prefixed_psname + ':WfmOffset-SP' wfm_offset_rb = self._prefixed_psname + ':WfmOffset-RB' wfm_index_ca = self._prefixed_psname + ':WfmIndex-Mon' wfm_count_ca = self._prefixed_psname + ':WfmSyncPulseCount-Mon' wfm_updateauto_ca = self._prefixed_psname + ':WfmUpdateAuto-Sts' wfm_updateauto_sel = self._prefixed_psname + ':WfmUpdateAuto-Sel' self.wfm_selected_label = QLabel('Wfm Selected', self) self.wfm_selected_mon = SiriusLabel(self, wfm_selected_mon) self.wfm_syncmode_label = QLabel('Wfm SyncMode', self) self.wfm_syncmode_sel_cb = PyDMEnumComboBox(self, wfm_syncmode_sel) self.wfm_syncmode_sts_lb = SiriusLabel(self, wfm_syncmode_sts) self.wfm_syncmode_sts_lb.showUnits = True self.wfm_freq_label = QLabel('Wfm Frequency [Hz]', self) self.wfm_freq_sp_sb = SiriusSpinbox(self, wfm_freq_sp) self.wfm_freq_rb_lb = SiriusLabel(self, wfm_freq_rb, keep_unit=True) self.wfm_freq_rb_lb.showUnits = True self.wfm_gain_label = QLabel('Wfm Gain', self) self.wfm_gain_sp_sb = SiriusSpinbox(self, wfm_gain_sp) self.wfm_gain_rb_lb = SiriusLabel(self, wfm_gain_rb) self.wfm_gain_rb_lb.showUnits = True self.wfm_offset_label = QLabel('Wfm Offset [A]', self) self.wfm_offset_sp_sb = SiriusSpinbox(self, wfm_offset_sp) self.wfm_offset_rb_lb = SiriusLabel(self, wfm_offset_rb) self.wfm_offset_rb_lb.showUnits = True wfm_index_label = QLabel('Wfm Index', self) wfm_index_rb_label = SiriusLabel(self, wfm_index_ca) wfm_count_label = QLabel('Wfm Pulse Count', self) wfm_count_rb_label = SiriusLabel(self, wfm_count_ca) wfm_updateauto_label = QLabel('Wfm UpdateAuto', self) wfm_updateauto_sts_led = SiriusLedState(self, wfm_updateauto_ca) wfm_updateauto_btn = PyDMStateButton(self, wfm_updateauto_sel) layout_wfm = QGridLayout() layout_wfm.setAlignment(Qt.AlignTop) layout_wfm.setContentsMargins(6, 6, 3, 3) layout_wfm.addWidget( self.wfm_selected_label, 0, 0, Qt.AlignRight) layout_wfm.addWidget(self.wfm_selected_mon, 0, 1, 1, 2) layout_wfm.addWidget( self.wfm_syncmode_label, 1, 0, Qt.AlignRight) layout_wfm.addWidget(self.wfm_syncmode_sel_cb, 1, 1) layout_wfm.addWidget(self.wfm_syncmode_sts_lb, 1, 2) layout_wfm.addWidget(self.wfm_freq_label, 2, 0, Qt.AlignRight) layout_wfm.addWidget(self.wfm_freq_sp_sb, 2, 1) layout_wfm.addWidget(self.wfm_freq_rb_lb, 2, 2) layout_wfm.addWidget(self.wfm_gain_label, 3, 0, Qt.AlignRight) layout_wfm.addWidget(self.wfm_gain_sp_sb, 3, 1) layout_wfm.addWidget(self.wfm_gain_rb_lb, 3, 2) layout_wfm.addWidget(self.wfm_offset_label, 4, 0, Qt.AlignRight) layout_wfm.addWidget(self.wfm_offset_sp_sb, 4, 1) layout_wfm.addWidget(self.wfm_offset_rb_lb, 4, 2) layout_wfm.addWidget(wfm_index_label, 5, 0, Qt.AlignRight) layout_wfm.addWidget(wfm_index_rb_label, 5, 1) layout_wfm.addWidget(wfm_count_label, 6, 0, Qt.AlignRight) layout_wfm.addWidget(wfm_count_rb_label, 6, 1) layout_wfm.addWidget(wfm_updateauto_label, 7, 0, Qt.AlignRight) layout_wfm.addWidget(wfm_updateauto_btn, 7, 1, Qt.AlignHCenter) layout_wfm.addWidget(wfm_updateauto_sts_led, 7, 2) self.wfm_box = QGroupBox("Wfm") self.wfm_box.setObjectName("Wfm") self.wfm_box.setSizePolicy(QSzPlcy.Preferred, QSzPlcy.Maximum) self.wfm_box.setLayout(layout_wfm) # --- wfmlayout --- layout = QGridLayout() layout.setAlignment(Qt.AlignTop) layout.setContentsMargins(6, 6, 3, 3) layout.addWidget(self.scope_box, 1, 1) layout.addWidget(self.wfm_box, 2, 1) return layout def _update_wfm_nrpts_label(self, value): pvtype = self.sender().address.split('Wfm')[-1] self._wfm_nrpts[pvtype] = len(value) self.wfm_nrpts_lb.setText( "Nrpts (SP|RB|Ref-Mon|Mon): {}|{}|{}|{}".format( self._wfm_nrpts['-SP'], self._wfm_nrpts['-RB'], self._wfm_nrpts['Ref-Mon'], self._wfm_nrpts['-Mon'])) def _wfmUpdAxisLabel(self, state): xlabel = 'Frequency [Hz]' if state else 'Time [s]' self.wfm_graph.setLabel('bottom', text=xlabel) def _wfmTimeData(self, propty, value): if value is None: return channel = self.sender().address curve = self._wfm_curves[propty] if 'Duration' in channel: duration = value latest_y = curve.latest_y else: duration = self._scopedur_ch_rb.value latest_y = value if latest_y is None: return curve.receiveXWaveform(_np.linspace(0, duration, len(latest_y))) curve.redrawCurve() def _wfmFourierData(self, curvetype, x, y): """Perform Fourier transform. This code is a copy of pyqtgraph.graphicsItems.PlotDataItem, just changing the sampling frequency to the ScopeFreq-RB value. """ # If x values are not sampled uniformly, # then use np.interp to resample before taking fft. dx = _np.diff(x) uniform = not _np.any(_np.abs(dx-dx[0]) > (abs(dx[0]) / 1000.)) if not uniform: x2 = _np.linspace(x[0], x[-1], len(x)) y = _np.interp(x2, x, y) x = x2 n = y.size f = _np.fft.rfft(y) / n # Diff: use scope frequency chfreq = self._scopefreq_ch_rb if curvetype else self._wfmfreq_ch_rb freq = chfreq.value if isinstance(freq, _np.ndarray): freq = freq[0] d = 1./freq if freq is not None else 1 x = _np.fft.rfftfreq(n, d) y = _np.abs(f) return x, y
[docs] class LIPSDetailWidget(_BaseDetailWidget): """.""" def __init__(self, psname, parent=None): """Class constructor.""" super(LIPSDetailWidget, self).__init__(psname, parent=parent) self._setup_ui() self.setStyleSheet(self.StyleSheet) def _setup_ui(self): # Group boxes that compose the widget self.frmwr_box = QGroupBox("IOC && Net") self.frmwr_box.setObjectName("version") self.frmwr_box.setSizePolicy(QSzPlcy.Preferred, QSzPlcy.Maximum) self.pwrstate_box = QGroupBox("PwrState") self.pwrstate_box.setObjectName("power_state") self.interlock_box = QGroupBox("Interlock") self.interlock_box.setObjectName("interlock") self.params_box = QGroupBox('Params') self.params_box.setObjectName('params_box') self.current_box = QGroupBox("Current") self.current_box.setObjectName("current") if self._metric: self.metric_box = QGroupBox(self._metric) self.metric_box.setObjectName("metric") # Set group boxes layouts self.frmwr_box.setLayout(self._frmwrLayout()) self.pwrstate_box.setLayout(self._powerStateLayout()) self.interlock_box.setLayout(self._interlockLayout()) self.params_box.setLayout(self._paramsLayout()) self.current_box.setLayout(self._currentLayout(has_refmon=False)) if self._metric: self.metric_box.setLayout(self._metricLayout(has_refmon=False)) # Add group boxes to laytout self.layout = self._setWidgetLayout() # Set widget layout self.setLayout(self.layout) def _setWidgetLayout(self): controls = QGridLayout() controls.addWidget(self.frmwr_box, 0, 0, 1, 2) controls.addWidget(self.pwrstate_box, 1, 0) controls.addWidget(self.interlock_box, 1, 1) analogs = QVBoxLayout() analogs.addWidget(self.current_box, Qt.AlignCenter) if self._metric: analogs.addWidget(self.metric_box, Qt.AlignCenter) controls.addWidget(self.params_box, 2, 0, 1, 2) else: analogs.addWidget(self.params_box, Qt.AlignCenter) boxes_layout = QHBoxLayout() boxes_layout.addLayout(controls) boxes_layout.addLayout(analogs) boxes_layout.setStretch(0, 1) boxes_layout.setStretch(1, 1) layout = QVBoxLayout() layout.addWidget(QLabel("<h2>" + self._psname + "</h2>")) layout.addLayout(boxes_layout) return layout def _frmwrLayout(self): self.version_label = QLabel('Version') self.version_label.setObjectName("version_label") self.version_label.setSizePolicy(QSzPlcy.Minimum, QSzPlcy.Maximum) self.version_cte = SiriusLabel( self, self._prefixed_psname + ":Version-Cte") self.version_cte.setObjectName("version_cte_label") self.version_cte.setSizePolicy(QSzPlcy.Minimum, QSzPlcy.Maximum) self.tstamp_boot_label = QLabel('IOC Boot') self.tstamp_boot_label.setObjectName("tstamp_label") self.tstamp_boot_label.setSizePolicy(QSzPlcy.Minimum, QSzPlcy.Maximum) self.tstamp_boot_cte = SiriusLabel( self, self._prefixed_psname + ":TimestampBoot-Cte") self.tstamp_boot_cte.setObjectName("tstamp_cte_label") self.tstamp_boot_cte.setSizePolicy(QSzPlcy.Minimum, QSzPlcy.Maximum) self.tstamp_boot_cte_ch = SiriusConnectionSignal( self._prefixed_psname + ":TimestampBoot-Cte") self.tstamp_boot_cte_ch.new_value_signal[float].connect( self._tstamp_boot_cte_met) self.tstamp_update_label = QLabel('IOC Update') self.tstamp_update_label.setObjectName("tstampupdate_label") self.tstamp_update_label.setSizePolicy( QSzPlcy.Minimum, QSzPlcy.Maximum) self.tstamp_update_mon = SiriusLabel( self, self._prefixed_psname + ":TimestampUpdate-Mon") self.tstamp_update_mon.setObjectName("tstampupdate_mon_label") self.tstamp_update_mon.setSizePolicy(QSzPlcy.Minimum, QSzPlcy.Maximum) self.tstamp_update_mon_ch = SiriusConnectionSignal( self._prefixed_psname + ":TimestampUpdate-Mon") self.tstamp_update_mon_ch.new_value_signal[float].connect( self._tstamp_update_mon_met) self.conn_label = QLabel('Net Status') self.conn_label.setObjectName("net_label") self.conn_label.setSizePolicy(QSzPlcy.Minimum, QSzPlcy.Maximum) self.conn_sts = SiriusLabel( self, self._prefixed_psname + ":Connected-Mon") self.conn_sts.setObjectName("net_cte_label") self.conn_sts.setSizePolicy(QSzPlcy.Minimum, QSzPlcy.Maximum) layout = QGridLayout() layout.addWidget(self.version_label, 0, 0, Qt.AlignHCenter) layout.addWidget(self.version_cte, 0, 1, Qt.AlignHCenter) layout.addWidget(self.tstamp_boot_label, 1, 0, Qt.AlignHCenter) layout.addWidget(self.tstamp_boot_cte, 1, 1, Qt.AlignHCenter) layout.addWidget(self.tstamp_update_label, 2, 0, Qt.AlignHCenter) layout.addWidget(self.tstamp_update_mon, 2, 1, Qt.AlignHCenter) layout.addWidget(self.conn_label, 3, 0, Qt.AlignHCenter) layout.addWidget(self.conn_sts, 3, 1, Qt.AlignHCenter) return layout def _tstamp_update_mon_met(self, value): time_str = self.conv_time_string(value) self.tstamp_update_mon.setText(time_str) def _tstamp_boot_cte_met(self, value): time_str = self.conv_time_string(value) self.tstamp_boot_cte.setText(time_str) def _interlockLayout(self): self.intlk_bt = QPushButton(qta.icon('fa5s.list-ul'), '', self) self.intlk_bt.setObjectName('intlk_bt') self.intlk_bt.setStyleSheet( '#intlk_bt{min-width:25px; max-width:25px; icon-size:20px;}') util.connect_window(self.intlk_bt, LIInterlockWindow, self, **{'devname': self._prefixed_psname}) if self._psname.dev == 'Spect': self.intlk_led = LISpectIntlkLed(self) else: ch2vals = {self._prefixed_psname+':StatusIntlk-Mon': { 'value': _PS_LI_INTLK, 'comp': 'lt'}} self.intlk_led = PyDMLedMultiChannel(self, channels2values=ch2vals) layout = QGridLayout() layout.setAlignment(Qt.AlignCenter) layout.setContentsMargins(6, 6, 3, 3) layout.addWidget(self.intlk_bt, 0, 0) layout.addWidget(QLabel('Intlk', self, alignment=Qt.AlignCenter), 0, 1) layout.addWidget(self.intlk_led, 0, 2) return layout def _paramsLayout(self): temp_label = QLabel('Temperature', self) self.temp_mon_label = SiriusLabel( self, self._prefixed_psname + ':Temperature-Mon') loadv_label = QLabel('Load Voltage', self) self.loadv_mon_label = SiriusLabel( self, self._prefixed_psname + ':LoadVoltage-Mon') busv_label = QLabel('Bus Voltage', self) self.busv_mon_label = SiriusLabel( self, self._prefixed_psname + ':BusVoltage-Mon') layout = QGridLayout() layout.addWidget(temp_label, 0, 0, Qt.AlignRight) layout.addWidget(self.temp_mon_label, 0, 1) layout.addWidget(loadv_label, 1, 0, Qt.AlignRight) layout.addWidget(self.loadv_mon_label, 1, 1) layout.addWidget(busv_label, 2, 0, Qt.AlignRight) layout.addWidget(self.busv_mon_label, 2, 1) return layout
[docs] class DCLinkDetailWidget(PSDetailWidget): def _setup_ui(self): # Group boxes that compose the widget self.frmwr_box = QGroupBox('Firmware && IOC') self.frmwr_box.setObjectName("Firmware") self.interlock_box = QGroupBox('Interlock') self.interlock_box.setObjectName('interlock') self.pwrstate_box = QGroupBox('PwrState') self.pwrstate_box.setObjectName('power_state') self.opmode_box = QGroupBox('OpMode') self.opmode_box.setObjectName('operation_mode') self.ctrlloop_box = QGroupBox('Control Loop') self.ctrlloop_box.setObjectName('ctrlloop_box') self.params_box = QGroupBox('General Params') self.params_box.setObjectName('genparams_box') self.analog_box = QGroupBox(self._analog_varname) self.analog_box.setObjectName('current') self.aux_box = QGroupBox('DCLink Auxiliar Params') self.aux_box.setObjectName('aux_box') # Set group boxes layouts self.frmwr_box.setLayout(self._frmwrLayout()) self.interlock_box.setLayout(self._interlockLayout()) self.pwrstate_box.setLayout(self._powerStateLayout()) self.opmode_box.setLayout(self._opModeLayout()) self.ctrlloop_box.setLayout(self._ctrlLoopLayout()) self.params_box.setLayout(self._genParamsLayout()) self.analog_box.setLayout(self._analogLayout()) self.aux_box.setLayout(self._auxLayout()) # Add group boxes to laytout self.layout = self._setWidgetLayout() # Set widget layout self.setLayout(self.layout) def _setWidgetLayout(self): controls = QGridLayout() controls.addWidget(self.frmwr_box, 0, 0, 1, 2) controls.addWidget(self.opmode_box, 1, 0) controls.addWidget(self.pwrstate_box, 1, 1) controls.addWidget(self.ctrlloop_box, 2, 0) controls.addWidget(self.interlock_box, 2, 1) controls.addWidget(self.params_box, 3, 0, 1, 2) analogs = QVBoxLayout() analogs.addWidget(self.analog_box) analogs.addWidget(self.aux_box) boxes_layout = QHBoxLayout() boxes_layout.addLayout(controls) boxes_layout.addLayout(analogs) layout = QVBoxLayout() layout.addWidget(QLabel("<h2>" + self._psname + "</h2>")) layout.addLayout(boxes_layout) return layout def _analogLayout(self): raise NotImplementedError def _auxLayout(self): raise NotImplementedError def _opModeLayout(self): self.opmode_rb = SiriusLabel( self, self._prefixed_psname + ":OpMode-Sts") self.opmode_rb.setObjectName("opmode1_rb_label") self.ctrlmode_led = SiriusLedAlert( self, self._prefixed_psname + ":CtrlMode-Mon") self.ctrlmode_label = SiriusLabel( self, self._prefixed_psname + ":CtrlMode-Mon") self.ctrlmode_label.setObjectName("ctrlmode1_label") ctrlmode_layout = QHBoxLayout() ctrlmode_layout.addWidget(self.ctrlmode_led) ctrlmode_layout.addWidget(self.ctrlmode_label) layout = QGridLayout() layout.setAlignment(Qt.AlignCenter) layout.addWidget(self.opmode_rb, 0, 0, Qt.AlignHCenter) layout.addLayout(ctrlmode_layout, 1, 0, Qt.AlignHCenter) return layout
[docs] class FBPDCLinkDetailWidget(DCLinkDetailWidget): def __init__(self, psname, parent=None): self._analog_varname = 'Current' super().__init__(psname, parent) def _analogLayout(self): self.current_sp_label = QLabel("Setpoint") self.current_rb_label = QLabel("Readback") self.current_ref_label = QLabel("Ref Mon") self.current_mon_label = QLabel("Mon") self.current_sp_widget = PyDMSpinboxScrollbar( self, self._prefixed_psname + ":Voltage-SP") self.current_rb_val = SiriusLabel( self, self._prefixed_psname+":Voltage-RB", keep_unit=True) self.current_rb_val.showUnits = True self.current_rb_val.precFromPV = True self.current_ref_val = SiriusLabel( self, self._prefixed_psname+":VoltageRef-Mon", keep_unit=True) self.current_ref_val.showUnits = True self.current_ref_val.precFromPV = True self.current_mon_val = SiriusLabel( self, self._prefixed_psname+":Voltage-Mon", keep_unit=True) self.current_mon_val.showUnits = True self.current_mon_val.precFromPV = True layout = QGridLayout() layout.setAlignment(Qt.AlignTop) layout.addWidget(self.current_sp_label, 0, 0, Qt.AlignRight) layout.addWidget(self.current_sp_widget, 0, 1) layout.addWidget(self.current_rb_label, 1, 0, Qt.AlignRight) layout.addWidget(self.current_rb_val, 1, 1) layout.addWidget(self.current_ref_label, 2, 0, Qt.AlignRight) layout.addWidget(self.current_ref_val, 2, 1) layout.addWidget(self.current_mon_label, 3, 0, Qt.AlignRight) layout.addWidget(self.current_mon_val, 3, 1) layout.setColumnStretch(2, 1) return layout def _auxLayout(self): layout = QFormLayout() for auxmeas in self._auxmeasures: text = auxmeas.split('-')[0] label = SiriusLabel( self, self._prefixed_psname + ':' + auxmeas) label.showUnits = True layout.addRow(text, label) pbprm = QPushButton(qta.icon('mdi.open-in-new'), 'Parameters', self) util.connect_window( pbprm, PSParamsWidget, self, psname=self._psname, params=self._params) layout.addRow(pbprm) return layout
[docs] class FACDCLinkDetailWidget(DCLinkDetailWidget): def __init__(self, psname, parent=None): self._analog_varname = 'Capacitor Bank Voltage' super().__init__(psname, parent) def _analogLayout(self): self.cap_bank_sp_label = QLabel("Setpoint") self.cap_bank_rb_label = QLabel("Readback") self.cap_bank_ref_label = QLabel("Ref Mon") self.cap_bank_mon_label = QLabel("Mon") self.cap_bank_sp_widget = PyDMSpinboxScrollbar( self, self._prefixed_psname + ":CapacitorBankVoltage-SP") self.cap_bank_rb_val = SiriusLabel( self, self._prefixed_psname + ":CapacitorBankVoltage-RB", keep_unit=True) self.cap_bank_rb_val.showUnits = True self.cap_bank_ref_val = SiriusLabel( self, self._prefixed_psname + ":CapacitorBankVoltageRef-Mon", keep_unit=True) self.cap_bank_ref_val.showUnits = True self.cap_bank_mon_val = SiriusLabel( self, self._prefixed_psname + ":CapacitorBankVoltage-Mon", keep_unit=True) self.cap_bank_mon_val.showUnits = True layout = QGridLayout() layout.setAlignment(Qt.AlignTop) layout.addWidget(self.cap_bank_sp_label, 0, 0, Qt.AlignRight) layout.addWidget(self.cap_bank_sp_widget, 0, 1) layout.addWidget(self.cap_bank_rb_label, 1, 0, Qt.AlignRight) layout.addWidget(self.cap_bank_rb_val, 1, 1) layout.addWidget(self.cap_bank_ref_label, 2, 0, Qt.AlignRight) layout.addWidget(self.cap_bank_ref_val, 2, 1) layout.addWidget(self.cap_bank_mon_label, 3, 0, Qt.AlignRight) layout.addWidget(self.cap_bank_mon_val, 3, 1) layout.setColumnStretch(2, 1) return layout def _auxLayout(self): layout = QFormLayout() for auxmeas in self._auxmeasures: pydmlbl = SiriusLabel( self, self._prefixed_psname + ':' + auxmeas) layout.addRow(auxmeas.split('-')[0], pydmlbl) pbaux = QPushButton( qta.icon('mdi.open-in-new'), 'Aux. Measures', self) util.connect_window( pbaux, PSAuxMeasWidget, self, psname=self._psname, auxmeas=list(), mod2dbase=self._mod2db, auxdev=self._auxdev, auxdev2mod=self._auxdev2mod) layout.addRow(pbaux) pbprm = QPushButton(qta.icon('mdi.open-in-new'), 'Parameters', self) util.connect_window( pbprm, PSParamsWidget, self, psname=self._psname, params=self._params) layout.addRow(pbprm) return layout
[docs] class FastCorrPSDetailWidget(_BaseDetailWidget): def __init__(self, psname, parent=None): """Class constructor.""" super(FastCorrPSDetailWidget, self).__init__(psname, parent=parent) self._psmodel = 'FOFB_PS' self._pstype = 'si-corrector-fc1-ch' self._db = get_ps_propty_database(self._psmodel, self._pstype) self._setup_ui() def _setup_ui(self): # Group boxes that compose the widget self.opmode_box = QGroupBox('OpMode') self.opmode_box.setObjectName('operation_mode') self.pwrstate_box = QGroupBox('PwrState') self.pwrstate_box.setObjectName('power_state') self.interlock_box = QGroupBox('Interlock') self.interlock_box.setObjectName('interlock') self.analogtab = QTabWidget() self.analogtab.setObjectName(self._psname.sec+'Tab') self.current_box = QWidget() self.current_box.setObjectName('current') self.analogtab.addTab(self.current_box, 'Current [A]') self.current_raw_box = QWidget() self.current_raw_box.setObjectName('current') self.analogtab.addTab(self.current_raw_box, 'Curr.[Raw]') self.voltage_box = QWidget() self.voltage_box.setObjectName('voltage') self.analogtab.addTab(self.voltage_box, 'Volt.[V]') self.voltage_raw_box = QWidget() self.voltage_raw_box.setObjectName('voltage') self.analogtab.addTab(self.voltage_raw_box, 'Volt.[Raw]') if self._metric: self.metric_box = QGroupBox(self._metric) self.metric_box.setObjectName('metric') self.paramstab = QTabWidget() self.paramstab.setObjectName(self._psname.sec+'Tab') self.currloop_box = QWidget() self.currloop_box.setObjectName('currloop_box') self.paramstab.addTab(self.currloop_box, 'Current Loop Controls') self.fofbctrl_box = QWidget() self.fofbctrl_box.setObjectName('fofbctrl_box') self.paramstab.addTab(self.fofbctrl_box, 'FOFB Parameters') # Set group boxes layouts self.opmode_box.setLayout(self._opModeLayout()) self.pwrstate_box.setLayout(self._powerStateLayout()) self.interlock_box.setLayout(self._interlockLayout()) self.current_box.setLayout(self._currentLayout(prec=6)) self.current_raw_box.setLayout(self._currentRawLayout()) self.voltage_box.setLayout(self._voltageLayout()) self.voltage_raw_box.setLayout(self._voltageRawLayout()) if self._metric: self.metric_box.setLayout(self._metricLayout()) self.currloop_box.setLayout(self._currLoopLayout()) self.fofbctrl_box.setLayout(self._fofbctrlLayout()) self.setStyleSheet( '#'+self._psname.sec+'Tab::pane {' ' border-left: 2px solid gray;' ' border-bottom: 2px solid gray;' ' border-right: 2px solid gray;}') # Add group boxes to laytout self.layout = self._setWidgetLayout() # Set widget layout self.setLayout(self.layout) def _setWidgetLayout(self): lay1 = QGridLayout() lay1.setContentsMargins(0, 0, 0, 0) lay1.addWidget(self.opmode_box, 0, 0) lay1.addWidget(self.pwrstate_box, 0, 1) lay1.addWidget(self.interlock_box, 1, 0, 1, 2) lay2 = QVBoxLayout() lay2.setContentsMargins(0, 0, 0, 0) lay2.addWidget(self.analogtab) if self._metric: lay2.addWidget(self.metric_box) boxes_layout = QGridLayout() boxes_layout.addLayout(lay1, 0, 0) boxes_layout.addLayout(lay2, 0, 1) boxes_layout.addWidget(self.paramstab, 2, 0, 1, 2) layout = QVBoxLayout() layout.addWidget(QLabel("<h2>" + self._psname + "</h2>", self)) layout.addLayout(boxes_layout) return layout def _opModeLayout(self): self.opmode_sp = PyDMEnumComboBox( self, self._prefixed_psname + ":OpMode-Sel") self.opmode_sp.setObjectName("opmode_sp_cbox") self.opmode_rb = SiriusLabel( self, self._prefixed_psname + ":OpMode-Sts") self.opmode_rb.setObjectName("opmode_rb_label") layout = QGridLayout() layout.setAlignment(Qt.AlignCenter) layout.addWidget(self.opmode_sp, 0, 0, Qt.AlignHCenter) layout.addWidget(self.opmode_rb, 1, 0, Qt.AlignHCenter) return layout def _currentRawLayout(self): current_sp_label = QLabel("Setpoint") current_rb_label = QLabel("Readback") current_ref_label = QLabel("Ref Mon") current_mon_label = QLabel("Mon") self.current_raw_sp = PyDMSpinboxScrollbar( self, self._prefixed_psname + ":CurrentRaw-SP") self.current_raw_rb = SiriusLabel( self, self._prefixed_psname+":CurrentRaw-RB") self.current_raw_ref = SiriusLabel( self, self._prefixed_psname+":CurrentRawRef-Mon") self.current_raw_mon = SiriusLabel( self, self._prefixed_psname+":CurrentRaw-Mon") layout = QGridLayout() layout.setAlignment(Qt.AlignTop) layout.addWidget(current_sp_label, 0, 0, Qt.AlignRight) layout.addWidget(self.current_raw_sp, 0, 1) layout.addWidget(current_rb_label, 1, 0, Qt.AlignRight) layout.addWidget(self.current_raw_rb, 1, 1) layout.addWidget(current_ref_label, 2, 0, Qt.AlignRight) layout.addWidget(self.current_raw_ref, 2, 1) layout.addWidget(current_mon_label, 3, 0, Qt.AlignRight) layout.addWidget(self.current_raw_mon, 3, 1) layout.setColumnStretch(2, 1) return layout def _voltageLayout(self): voltage_sp_label = QLabel("Setpoint") voltage_rb_label = QLabel("Readback") voltage_mn_label = QLabel("Mon") self.voltage_sp = PyDMLinEditScrollbar( self, self._prefixed_psname + ":Voltage-SP") self.voltage_sp.lineedit.precisionFromPV = False self.voltage_sp.lineedit.precision = 6 self.voltage_rb = SiriusLabel( self, self._prefixed_psname+":Voltage-RB", keep_unit=True) self.voltage_rb.precisionFromPV = False self.voltage_rb.precision = 6 self.voltage_rb.showUnits = True self.voltage_mn = SiriusLabel( self, self._prefixed_psname+":Voltage-Mon", keep_unit=True) self.voltage_mn.precisionFromPV = False self.voltage_mn.precision = 6 self.voltage_mn.showUnits = True layout = QGridLayout() layout.setAlignment(Qt.AlignTop) layout.addWidget(voltage_sp_label, 0, 0, Qt.AlignRight) layout.addWidget(self.voltage_sp, 0, 1) layout.addWidget(voltage_rb_label, 1, 0, Qt.AlignRight) layout.addWidget(self.voltage_rb, 1, 1) layout.addWidget(voltage_mn_label, 2, 0, Qt.AlignRight) layout.addWidget(self.voltage_mn, 2, 1) layout.setColumnStretch(2, 1) return layout def _voltageRawLayout(self): voltage_sp_label = QLabel("Setpoint") voltage_rb_label = QLabel("Readback") voltage_mn_label = QLabel("Mon") self.voltage_raw_sp = PyDMLinEditScrollbar( self, self._prefixed_psname + ":VoltageRaw-SP") self.voltage_raw_rb = SiriusLabel( self, self._prefixed_psname+":VoltageRaw-RB", keep_unit=True) self.voltage_rb.showUnits = True self.voltage_raw_mn = SiriusLabel( self, self._prefixed_psname+":VoltageRaw-Mon", keep_unit=True) self.voltage_raw_mn.showUnits = True layout = QGridLayout() layout.setAlignment(Qt.AlignTop) layout.addWidget(voltage_sp_label, 0, 0, Qt.AlignRight) layout.addWidget(self.voltage_raw_sp, 0, 1) layout.addWidget(voltage_rb_label, 1, 0, Qt.AlignRight) layout.addWidget(self.voltage_raw_rb, 1, 1) layout.addWidget(voltage_mn_label, 2, 0, Qt.AlignRight) layout.addWidget(self.voltage_raw_mn, 2, 1) layout.setColumnStretch(2, 1) return layout def _interlockLayout(self): layout = QGridLayout() layout.setAlignment(Qt.AlignCenter) row = 0 for pvn in ['AlarmsAmp', 'AlarmsAmpLtc']: alarm_label = QLabel(pvn, self, alignment=Qt.AlignCenter) alarm_bt = QPushButton(qta.icon('fa5s.list-ul'), '', self) alarm_bt.setObjectName('alarm_bt') alarm_bt.setStyleSheet( '#alarm_bt{min-width:25px; max-width:25px; icon-size:20px;}') util.connect_window( alarm_bt, InterlockWindow, self, devname=self._psname, database=self._db, interlock=pvn) alarm_led = SiriusLedAlert( parent=self, init_channel=self._prefixed_psname+':'+pvn+'-Mon') alarm_led.onColor = alarm_led.Yellow layout.addWidget(alarm_bt, row, 0) layout.addWidget(alarm_label, row, 1) layout.addWidget(alarm_led, row, 2) row += 1 self.reset_bt = PyDMPushButton( parent=self, icon=qta.icon('fa5s.sync'), pressValue=1, init_channel=self._prefixed_psname + ":AlarmsAmpLtcRst-Cmd") self.reset_bt.setObjectName('reset_bt') self.reset_bt.setStyleSheet( '#reset_bt{min-width:25px; max-width:25px; icon-size:20px;}') layout.addWidget(self.reset_bt, row, 2) return layout def _currLoopLayout(self): # controls tabctrl = QTabWidget() tabctrl.setObjectName(self._psname.sec+'Tab') # # loop parameters ctlmode_lb = QLabel( 'CurrLoopMode', self, alignment=Qt.AlignRight | Qt.AlignVCenter) self.ctlmode_cb = PyDMEnumComboBox( self, self._prefixed_psname + ':CurrLoopMode-Sel') self.ctlmode_lb = SiriusLabel( self, self._prefixed_psname + ':CurrLoopMode-Sts') ctlkp_lb = QLabel( 'CurrLoopKp', self, alignment=Qt.AlignRight | Qt.AlignVCenter) self.ctlkp_sp = SiriusSpinbox( self, self._prefixed_psname + ':CurrLoopKp-SP') self.ctlkp_sp.limitsFromChannel = False self.ctlkp_sp.setMinimum(0.0) self.ctlkp_sp.setMaximum(2**31 - 1) self.ctlkp_rb = SiriusLabel( self, self._prefixed_psname + ':CurrLoopKp-RB') ctlti_lb = QLabel( 'CurrLoopKi', self, alignment=Qt.AlignRight | Qt.AlignVCenter) self.ctlti_sp = SiriusSpinbox( self, self._prefixed_psname + ':CurrLoopKi-SP') self.ctlti_sp.limitsFromChannel = False self.ctlti_sp.setMinimum(0.0) self.ctlti_sp.setMaximum(2**31 - 1) self.ctlti_rb = SiriusLabel( self, self._prefixed_psname + ':CurrLoopKi-RB') cgain_lb = QLabel( 'CurrGain', self, alignment=Qt.AlignRight | Qt.AlignVCenter) self.cgain_sp = SiriusSpinbox( self, self._prefixed_psname + ':CurrGain-SP') self.cgain_sp.precisionFromPV = False self.cgain_sp.precision = 8 self.cgain_sp.limitsFromChannel = False self.cgain_sp.setMinimum(-1) self.cgain_sp.setMaximum(+1) self.cgain_rb = SiriusLabel( self, self._prefixed_psname + ':CurrGain-RB') self.cgain_rb.precisionFromPV = False self.cgain_rb.precision = 8 coffs_lb = QLabel( 'CurrOffset', self, alignment=Qt.AlignRight | Qt.AlignVCenter) self.coffs_sp = SiriusSpinbox( self, self._prefixed_psname + ':CurrOffset-SP') self.coffs_sp.limitsFromChannel = False self.coffs_sp.setMinimum(-100) self.coffs_sp.setMaximum(+100) self.coffs_rb = SiriusLabel( self, self._prefixed_psname + ':CurrOffset-RB') vgain_lb = QLabel( 'VoltGain', self, alignment=Qt.AlignRight | Qt.AlignVCenter) self.vgain_sp = SiriusSpinbox( self, self._prefixed_psname + ':VoltGain-SP') self.vgain_sp.precisionFromPV = False self.vgain_sp.precision = 8 self.vgain_sp.limitsFromChannel = False self.vgain_sp.setMinimum(-1) self.vgain_sp.setMaximum(+1) self.vgain_rb = SiriusLabel( self, self._prefixed_psname + ':VoltGain-RB') self.vgain_rb.precisionFromPV = False self.vgain_rb.precision = 8 voffs_lb = QLabel( 'VoltOffset', self, alignment=Qt.AlignRight | Qt.AlignVCenter) self.voffs_sp = SiriusSpinbox( self, self._prefixed_psname + ':VoltOffset-SP') self.voffs_sp.limitsFromChannel = False self.voffs_sp.setMinimum(-100) self.voffs_sp.setMaximum(+100) self.voffs_rb = SiriusLabel( self, self._prefixed_psname + ':VoltOffset-RB') widgetparms = QWidget() lay = QGridLayout(widgetparms) lay.setAlignment(Qt.AlignTop) lay.addWidget(ctlmode_lb, 0, 0, Qt.AlignRight) lay.addWidget(self.ctlmode_cb, 0, 1) lay.addWidget(self.ctlmode_lb, 0, 2) lay.addWidget(ctlkp_lb, 1, 0, Qt.AlignRight) lay.addWidget(self.ctlkp_sp, 1, 1) lay.addWidget(self.ctlkp_rb, 1, 2) lay.addWidget(ctlti_lb, 2, 0, Qt.AlignRight) lay.addWidget(self.ctlti_sp, 2, 1) lay.addWidget(self.ctlti_rb, 2, 2) lay.addWidget(cgain_lb, 3, 0, Qt.AlignRight) lay.addWidget(self.cgain_sp, 3, 1) lay.addWidget(self.cgain_rb, 3, 2) lay.addWidget(coffs_lb, 4, 0, Qt.AlignRight) lay.addWidget(self.coffs_sp, 4, 1) lay.addWidget(self.coffs_rb, 4, 2) lay.addWidget(vgain_lb, 5, 0, Qt.AlignRight) lay.addWidget(self.vgain_sp, 5, 1) lay.addWidget(self.vgain_rb, 5, 2) lay.addWidget(voffs_lb, 6, 0, Qt.AlignRight) lay.addWidget(self.voffs_sp, 6, 1) lay.addWidget(self.voffs_rb, 6, 2) tabctrl.addTab(widgetparms, 'Parameters') # # tests testlima_lb = QLabel( 'Limit A', self, alignment=Qt.AlignRight | Qt.AlignVCenter) self.testlima_sp = SiriusSpinbox( self, self._prefixed_psname + ':TestLimA-SP') self.testlima_rb = SiriusLabel( self, self._prefixed_psname + ':TestLimA-RB') testlimb_lb = QLabel( 'Limit B', self, alignment=Qt.AlignRight | Qt.AlignVCenter) self.testlimb_sp = SiriusSpinbox( self, self._prefixed_psname + ':TestLimB-SP') self.testlimb_rb = SiriusLabel( self, self._prefixed_psname + ':TestLimB-RB') testwaveper_lb = QLabel( 'Wave Period', self, alignment=Qt.AlignRight | Qt.AlignVCenter) self.testwaveper_sp = SiriusSpinbox( self, self._prefixed_psname + ':TestWavePeriod-SP') self.testwaveper_rb = SiriusLabel( self, self._prefixed_psname + ':TestWavePeriod-RB') widgettest = QWidget() lay = QGridLayout(widgettest) lay.setAlignment(Qt.AlignTop) lay.addWidget(testlima_lb, 0, 0, Qt.AlignRight) lay.addWidget(self.testlima_sp, 0, 1) lay.addWidget(self.testlima_rb, 0, 2) lay.addWidget(testlimb_lb, 1, 0, Qt.AlignRight) lay.addWidget(self.testlimb_sp, 1, 1) lay.addWidget(self.testlimb_rb, 1, 2) lay.addWidget(testwaveper_lb, 2, 0, Qt.AlignRight) lay.addWidget(self.testwaveper_sp, 2, 1) lay.addWidget(self.testwaveper_rb, 2, 2) tabctrl.addTab(widgettest, 'Tests') # monitoring tabmon = QTabWidget(self) tabmon.setObjectName(self._psname.sec+'Tab') # # current waveform self.graph_curr = SiriusWaveformPlot() self.graph_curr.addChannel( y_channel=self._prefixed_psname + ':LAMPCurrentData', name='Current', color='blue', lineWidth=1) self.graph_curr.addChannel( y_channel=self._prefixed_psname + ':LAMPCurrentRefData', name='CurrentRef', color='green', lineWidth=1) # self.graph_curr.setSizePolicy(QSzPlcy.Maximum, QSzPlcy.Maximum) self.graph_curr.autoRangeX = True self.graph_curr.autoRangeY = True self.graph_curr.showXGrid = True self.graph_curr.showYGrid = True self.graph_curr.title = 'Current' self.graph_curr.setLabel('left', text='Current [A]', color='gray') self.graph_curr.setLabel('bottom', text='Index') self.graph_curr.setBackgroundColor(QColor(255, 255, 255)) tabmon.addTab(self.graph_curr, 'Current Acq.') # # voltage waveform self.graph_volt = SiriusWaveformPlot() self.graph_volt.addChannel( y_channel=self._prefixed_psname + ':LAMPVoltageData', name='Voltage', color='blue', lineWidth=1) # self.graph_volt.setSizePolicy(QSzPlcy.Maximum, QSzPlcy.Maximum) self.graph_volt.autoRangeX = True self.graph_volt.autoRangeY = True self.graph_volt.showXGrid = True self.graph_volt.showYGrid = True self.graph_volt.title = 'Voltage' self.graph_volt.setLabel('left', text='Voltage [V]', color='gray') self.graph_volt.setLabel('bottom', text='Index') self.graph_volt.setBackgroundColor(QColor(255, 255, 255)) tabmon.addTab(self.graph_volt, 'Voltage Acq.') # # current history self.graph_chist = SiriusTimePlot() timespan = 5*60 # 5min self.graph_chist.timeSpan = timespan # [s] self.graph_chist.bufferSize = 5*timespan # [max 5 samples/s] pvsuf2color = { '-SP': 'red', '-RB': 'blue', 'Ref-Mon': 'green', '-Mon': 'black', } hbox_show = QHBoxLayout() hbox_show.setSpacing(9) for pvs, color in pvsuf2color.items(): pvname = self._prefixed_psname.substitute(propty='Current'+pvs) legtxt = pvs.replace('-', '') self.graph_chist.addYChannel( y_channel=pvname, name=legtxt, color=color, lineWidth=1) curve = self.graph_chist.curveAtIndex(-1) cb_show = QCheckBox(legtxt) cb_show.setChecked(True) cb_show.setStyleSheet('color: '+color+';') cb_show.stateChanged.connect(curve.setVisible) hbox_show.addWidget(cb_show) self.graph_chist.setSizePolicy(QSzPlcy.Maximum, QSzPlcy.Maximum) self.graph_chist.autoRangeX = True self.graph_chist.autoRangeY = True self.graph_chist.showXGrid = True self.graph_chist.showYGrid = True self.graph_chist.timeSpan = 30 # [s] self.graph_chist.title = 'Current Mean History' self.graph_chist.setLabel('left', text='Current [A]', color='gray') self.graph_chist.showLegend = True self.graph_chist.setBackgroundColor(QColor(255, 255, 255)) wid_currhist = QWidget() lay_currhist = QVBoxLayout(wid_currhist) lay_currhist.setContentsMargins(0, 0, 0, 0) lay_currhist.addWidget(self.graph_chist) lay_currhist.addLayout(hbox_show) tabmon.addTab(wid_currhist, 'Current Hist.') tabmon.setCurrentIndex(2) layout = QHBoxLayout() layout.addWidget(tabctrl) layout.addWidget(tabmon) return layout def _fofbctrlLayout(self): # controls fofbacc_lb = QLabel( 'Accumulator', self, alignment=Qt.AlignRight | Qt.AlignVCenter) self.fofbacc_mon = SiriusLabel( self, self._prefixed_psname + ':FOFBAcc-Mon') self.fofbacc_mon.setSizePolicy(QSzPlcy.Preferred, QSzPlcy.Maximum) fofbaccgain_lb = QLabel( 'Acc. Gain', self, alignment=Qt.AlignRight | Qt.AlignVCenter) self.fofbaccgain_sp = PyDMLineEdit( self, self._prefixed_psname + ':FOFBAccGain-SP') self.fofbaccgain_sp.precisionFromPV = False self.fofbaccgain_sp.precision = 8 self.fofbaccgain_rb = SiriusLabel( self, self._prefixed_psname + ':FOFBAccGain-RB') self.fofbaccgain_rb.precisionFromPV = False self.fofbaccgain_rb.precision = 8 fofbaccfreeze_lb = QLabel( 'Acc. Freeze', self, alignment=Qt.AlignRight | Qt.AlignVCenter) self.fofbaccfreeze_sp = PyDMEnumComboBox( self, self._prefixed_psname + ':FOFBAccFreeze-Sel') self.fofbaccfreeze_rb = SiriusLabel( self, self._prefixed_psname + ':FOFBAccFreeze-Sts') fofbaccclear_lb = QLabel( 'Acc. Clear', self, alignment=Qt.AlignRight | Qt.AlignVCenter) self.fofbaccclear_bt = PyDMPushButton( parent=self, icon=qta.icon('mdi.sync'), pressValue=1, init_channel=self._prefixed_psname + ":FOFBAccClear-Cmd") self.fofbaccclear_bt.setObjectName('accclear_bt') self.fofbaccclear_bt.setStyleSheet( '#accclear_bt{min-width:25px; max-width:25px; icon-size:20px;}') fofbaccmaxsat_lb = QLabel( 'Max. Sat. Current', self, alignment=Qt.AlignRight | Qt.AlignVCenter) self.fofbaccmaxsat_sp = SiriusSpinbox( self, self._prefixed_psname + ':FOFBAccSatMax-SP') self.fofbaccmaxsat_sp.precisionFromPV = False self.fofbaccmaxsat_sp.precision = 8 self.fofbaccmaxsat_rb = SiriusLabel( self, self._prefixed_psname + ':FOFBAccSatMax-RB') self.fofbaccmaxsat_rb.precisionFromPV = False self.fofbaccmaxsat_rb.precision = 8 fofbaccminsat_lb = QLabel( 'Min. Sat. Current', self, alignment=Qt.AlignRight | Qt.AlignVCenter) self.fofbaccminsat_sp = SiriusSpinbox( self, self._prefixed_psname + ':FOFBAccSatMin-SP') self.fofbaccminsat_sp.precisionFromPV = False self.fofbaccminsat_sp.precision = 8 self.fofbaccminsat_rb = SiriusLabel( self, self._prefixed_psname + ':FOFBAccSatMin-RB') self.fofbaccminsat_rb.precisionFromPV = False self.fofbaccminsat_rb.precision = 8 fofbaccfiltgain_lb = QLabel( 'Filter Gain', self, alignment=Qt.AlignRight | Qt.AlignVCenter) self.fofbaccfiltgain_sp = PyDMLineEdit( self, self._prefixed_psname + ':FOFBAccFilterGain-SP') self.fofbaccfiltgain_rb = SiriusLabel( self, self._prefixed_psname + ':FOFBAccFilterGain-RB') widctrl = QWidget() lay = QGridLayout(widctrl) lay.addWidget(fofbacc_lb, 0, 0, Qt.AlignRight) lay.addWidget(self.fofbacc_mon, 0, 1) lay.addWidget(fofbaccgain_lb, 1, 0, Qt.AlignRight) lay.addWidget(self.fofbaccgain_sp, 1, 1) lay.addWidget(self.fofbaccgain_rb, 1, 2) lay.addWidget(fofbaccfreeze_lb, 2, 0, Qt.AlignRight) lay.addWidget(self.fofbaccfreeze_sp, 2, 1) lay.addWidget(self.fofbaccfreeze_rb, 2, 2) lay.addWidget(fofbaccclear_lb, 3, 0, Qt.AlignRight) lay.addWidget(self.fofbaccclear_bt, 3, 1) lay.addWidget(fofbaccmaxsat_lb, 4, 0, Qt.AlignRight) lay.addWidget(self.fofbaccmaxsat_sp, 4, 1) lay.addWidget(self.fofbaccmaxsat_rb, 4, 2) lay.addWidget(fofbaccminsat_lb, 5, 0, Qt.AlignRight) lay.addWidget(self.fofbaccminsat_sp, 5, 1) lay.addWidget(self.fofbaccminsat_rb, 5, 2) lay.addWidget(fofbaccfiltgain_lb, 6, 0, Qt.AlignRight) lay.addWidget(self.fofbaccfiltgain_sp, 6, 1) lay.addWidget(self.fofbaccfiltgain_rb, 6, 2) # coefficients gph_fofbcoeffs = dict() for plane in ['X', 'Y']: colorsp = 'darkBlue' if plane == 'X' else 'darkRed' colorrb = 'blue' if plane == 'X' else 'red' gph_fofbcoeffs[plane] = SiriusWaveformPlot() gph_fofbcoeffs[plane].setSizePolicy( QSzPlcy.Maximum, QSzPlcy.Maximum) gph_fofbcoeffs[plane].showLegend = True gph_fofbcoeffs[plane].autoRangeX = True gph_fofbcoeffs[plane].autoRangeY = True gph_fofbcoeffs[plane].showXGrid = True gph_fofbcoeffs[plane].showYGrid = True gph_fofbcoeffs[plane].title = 'InvRespMatRow'+plane+' Coefficients' gph_fofbcoeffs[plane].setBackgroundColor(QColor(255, 255, 255)) gph_fofbcoeffs[plane].addChannel( y_channel=self._prefixed_psname+':InvRespMatRow'+plane+'-SP', name='SP', color=colorsp, lineWidth=2, symbol='o') gph_fofbcoeffs[plane].addChannel( y_channel=self._prefixed_psname+':InvRespMatRow'+plane+'-RB', name='RB', color=colorrb, lineWidth=2, symbol='o') self.show_coeff_sp = QCheckBox('SP') self.show_coeff_sp.setChecked(True) self.show_coeff_rb = QCheckBox('RB') self.show_coeff_rb.setChecked(True) for plane in ['X', 'Y']: self.show_coeff_sp.stateChanged.connect( gph_fofbcoeffs[plane].curveAtIndex(0).setVisible) self.show_coeff_rb.stateChanged.connect( gph_fofbcoeffs[plane].curveAtIndex(1).setVisible) hbox_coeffshow = QHBoxLayout() hbox_coeffshow.setAlignment(Qt.AlignCenter) hbox_coeffshow.addWidget(self.show_coeff_sp) hbox_coeffshow.addWidget(self.show_coeff_rb) widcoeff = QWidget() lay = QVBoxLayout(widcoeff) lay.setAlignment(Qt.AlignTop) for plane in ['X', 'Y']: lay.addWidget(gph_fofbcoeffs[plane]) lay.addLayout(hbox_coeffshow) # filters gph_filt = SiriusWaveformPlot() gph_filt.setSizePolicy(QSzPlcy.Maximum, QSzPlcy.Maximum) gph_filt.showLegend = True gph_filt.autoRangeX = True gph_filt.autoRangeY = True gph_filt.showXGrid = True gph_filt.showYGrid = True gph_filt.title = 'Filter Coefficients' gph_filt.setBackgroundColor(QColor(255, 255, 255)) gph_filt.addChannel( y_channel=self._prefixed_psname+':FOFBAccFilter-SP', name='SP', color='darkBlue', lineWidth=2, symbol='o') gph_filt.addChannel( y_channel=self._prefixed_psname+':FOFBAccFilter-RB', name='RB', color='blue', lineWidth=2, symbol='o') self.show_filt_sp = QCheckBox('SP') self.show_filt_sp.setChecked(True) self.show_filt_rb = QCheckBox('RB') self.show_filt_rb.setChecked(True) self.show_filt_sp.stateChanged.connect( gph_filt.curveAtIndex(0).setVisible) self.show_filt_rb.stateChanged.connect( gph_filt.curveAtIndex(1).setVisible) hbox_filtshow = QHBoxLayout() hbox_filtshow.setAlignment(Qt.AlignCenter) hbox_filtshow.addWidget(self.show_filt_sp) hbox_filtshow.addWidget(self.show_filt_rb) widfilt = QWidget() lay = QVBoxLayout(widfilt) lay.setAlignment(Qt.AlignTop) lay.addWidget(gph_filt) lay.addLayout(hbox_filtshow) widmon = QTabWidget() widmon.setObjectName(self._psname.sec+'Tab') widmon.addTab(widcoeff, 'InvRespMat') widmon.addTab(widfilt, 'Filter') layout = QHBoxLayout() layout.addWidget(widctrl) layout.addWidget(widmon) return layout
[docs] class PSAuxMeasWidget(SiriusDialog): """PS Modules Detail Widget.""" def __init__(self, parent, psname, auxmeas, mod2dbase, auxdev, auxdev2mod): """Init.""" super().__init__(parent) self._psname = [psname, ] if auxdev: self._psname = list() for aux in auxdev: self._psname.append(psname+aux) self._prefixed_psname = SiriusPVName(psname).substitute( prefix=VACA_PREFIX) self.auxmeas = auxmeas self.mod2dbase = mod2dbase self.auxdev2mod = auxdev2mod self.title_text = psname + ' - Auxiliary Measures' self.setWindowTitle(self.title_text) self.setObjectName(parent.objectName()) self._setupUi() self.setStyleSheet('SiriusLabel{qproperty-alignment: AlignCenter;}') def _setupUi(self): text_psname = QLabel('<h3>' + self._psname[0] + '</h3>', self, alignment=Qt.AlignCenter) pswid = None if self.auxmeas: title_main = QLabel('<h3>Main Measures</h3>', self, alignment=Qt.AlignCenter) pswid = self._setupPSWidget() if len(self.mod2dbase) > 1: title_iib = QLabel('<h3>IIB Measures</h3>', self, alignment=Qt.AlignCenter) lay_mod = QGridLayout() ncols = 4 if len(self.mod2dbase)*len(self._psname) > 4 else 2 idx = 0 for psn in self._psname: for mod, dbase in self.mod2dbase.items(): modwid = self._setupModWidget(psn, mod, dbase) lay_mod.addWidget(modwid, idx//ncols, idx % ncols) idx += 1 lay = QGridLayout(self) lay.setHorizontalSpacing(20) lay.setVerticalSpacing(20) if pswid: lay.addWidget(text_psname, 0, 0, 1, 2) lay.addWidget(title_main, 1, 0) lay.addWidget(pswid, 2, 0) lay.addWidget(title_iib, 1, 1) lay.addLayout(lay_mod, 2, 1) else: lay.addWidget(text_psname, 0, 0) lay.addWidget(title_iib, 1, 0) lay.addLayout(lay_mod, 2, 0) else: lay = QVBoxLayout(self) lay.setSpacing(15) lay.addWidget(text_psname) if pswid: lay.addWidget(title_main) lay.addWidget(pswid) dbase = self.mod2dbase['main'] if dbase: title_iib = QLabel('<h3>IIB Measures</h3>', self, alignment=Qt.AlignCenter) modwid = self._setupModWidget(self._psname[0], 'main', dbase) lay.addWidget(title_iib) lay.addWidget(modwid) def _setupPSWidget(self): wid = QWidget() if len(self.auxmeas) > 32: lay = QHBoxLayout(wid) lay.setSpacing(20) half1 = self.auxmeas[:20] flay1 = QFormLayout() flay1.setVerticalSpacing(9) for pv in half1: text = pv.split('-')[0] lbl = SiriusLabel( self, self._prefixed_psname.substitute(propty=pv), keep_unit=True) lbl.showUnits = True flay1.addRow(text, lbl) half2 = self.auxmeas[20:] flay2 = QFormLayout() flay2.setVerticalSpacing(9) for pv in half2: text = pv.split('-')[0] lbl = SiriusLabel( self, self._prefixed_psname.substitute(propty=pv), keep_unit=True) lbl.showUnits = True flay2.addRow(text, lbl) lay.addLayout(flay1) lay.addLayout(flay2) else: flay = QFormLayout(wid) for pv in self.auxmeas: text = pv.split('-')[0] if 'SOFB' not in pv else pv lbl = SiriusLabel( self, self._prefixed_psname.substitute(propty=pv), keep_unit=True) lbl.showUnits = True lbl.setObjectName('auxmeaslabel') flay.addRow(text, lbl) return wid def _setupModWidget(self, psname, mod, dbase): wid = QWidget() lay = QVBoxLayout(wid) lay.setAlignment(Qt.AlignTop) modname = mod if psname in self.auxdev2mod: modname = self.auxdev2mod[psname][mod] if mod != 'main': self.title = QLabel('<h3>Mod'+modname+'</h3>', self, alignment=Qt.AlignCenter) lay.addWidget(self.title) flay = QFormLayout() for pv in dbase: text = pv.split('Mod'+mod)[0].split('IIB')[0] lbl = SiriusLabel(self, psname + ':' + pv, keep_unit=True) lbl.showUnits = True lbl.setObjectName('auxmeaslabel') flay.addRow(text, lbl) lay.addLayout(flay) return wid
[docs] class PSParamsWidget(SiriusDialog): """PS Parameters Widget.""" def __init__(self, parent, psname, params): """Init.""" super().__init__(parent) self._psname = SiriusPVName(psname) self._prefix = VACA_PREFIX self._prefixed_psname = self._psname.substitute(prefix=self._prefix) self.params = params self.title_text = psname + ' - Parameters' self.setWindowTitle(self.title_text) self.setObjectName(parent.objectName()) self._setupUi() self.setStyleSheet( 'SiriusLabel{qproperty-alignment: AlignVCenter;}') def _setupUi(self): lay = QVBoxLayout(self) lay.setSpacing(15) text_psname = QLabel('<h3>' + self._psname + '</h3>', self, alignment=Qt.AlignCenter) lay.addWidget(text_psname) scr_area = QScrollArea(self) scr_area.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) scr_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) scr_area.setWidgetResizable(True) scr_area.setFrameShape(QFrame.NoFrame) scr_area_wid = QWidget() scr_area_wid.setObjectName('scr_ar_wid') scr_area_wid.setStyleSheet( '#scr_ar_wid {background-color: transparent;}') scr_area.setWidget(scr_area_wid) flay = QFormLayout(scr_area_wid) flay.setLabelAlignment(Qt.AlignRight | Qt.AlignVCenter) # Update text = 'Update Command' wid = PyDMPushButton( parent=self, icon=qta.icon('fa5s.redo-alt'), pressValue=1, init_channel=self._prefixed_psname + ":ParamUpdate-Cmd") wid.setObjectName('updt_bt') wid.setStyleSheet( '#updt_bt{min-width:25px; max-width:25px; icon-size:20px;}') flay.addRow(text, wid) # Params for param in self.params: pvname = self._prefixed_psname + ':' + param text = param.split('-')[0].split('Param')[1] if 'Intlk' in pvname or 'Analog' in pvname: wid = self._create_table_wid(pvname) text += ' [us]' else: wid = self._create_label_wid(pvname) flay.addRow(text, wid) lay.addWidget(scr_area) def _create_label_wid(self, pvname): lbl = CustomLabel(self, keep_unit=True) if 'PSName' in pvname: lbl.displayFormat = SiriusLabel.DisplayFormat.String elif 'PSModel' in pvname: lbl.enum_strings = _PSet.MODELS elif 'SigGenType' in pvname: lbl.enum_strings = _PSet.CYCLE_TYPES elif 'WfmRefSyncMode' in pvname: lbl.enum_strings = _PSet.WFMREF_SYNCMODE else: lbl.showUnits = True lbl.channel = pvname return lbl def _create_table_wid(self, pvname): table = SiriusWaveformTable(self, pvname) table.showUnits = True col_count = 32 if 'Intlk' in pvname else 64 table.setColumnCount(col_count) table.setObjectName('table') table.setStyleSheet('#table{max-width:24em; max-height: 3em;}') table.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) table.horizontalHeader().setStyleSheet( "min-height:1em; max-height:1em;") table.verticalHeader().setSectionResizeMode(QHeaderView.Stretch) table.verticalHeader().setVisible(False) table.setEditTriggers(QAbstractItemView.NoEditTriggers) table.columnHeaderLabels = [str(i) for i in range(col_count)] table.rowHeaderLabels = [] return table
[docs] class CustomLabel(SiriusLabel):
[docs] def value_changed(self, new_value): super().value_changed(new_value) new_value = parse_value_for_display( value=new_value, precision=self.precision, display_format_type=self._display_format_type, string_encoding=self._string_encoding, widget=self) if isinstance(new_value, str): if self._show_units and self._unit != "": new_value = "{} {}".format(new_value, self._unit) self.setText(new_value) return if self.enum_strings and isinstance(new_value, (int, float)): try: self.setText(self.enum_strings[int(new_value)]) except IndexError: self.setText(f'Index Overflow [{new_value}]') return if self.enum_strings and isinstance(new_value, _np.ndarray): text = '['+', '.join([self.enum_strings[int(idx)] if idx < len(self.enum_strings) else 'UNDEF' for idx in new_value])+']' self.setText(text) return if isinstance(new_value, (int, float)): self.setText(self.format_string.format(new_value)) return self.setText(str(new_value))