def _setupui(self): evg = PVName(LLTimeSearch.get_evg_name()) g1 = LLButton(evg, '', self.prefix, self) self.g1 = g1 fouts = LLTimeSearch.get_evg2fout_mapping() fouts = [(out, down) for out, down in fouts.items()] g2 = self.setupdown(fouts) self.g2 = g2 g3 = list() trgsrcs = LLTimeSearch.get_fout2trigsrc_mapping() for _, down in fouts: downs = trgsrcs[down.device_name] downs = sorted([(ou, dwn) for ou, dwn in downs.items()]) g3.append(self.setupdown(downs)) lay = QGridLayout(self) lay.setHorizontalSpacing(12) lay.setVerticalSpacing(20) align = Qt.AlignHCenter | Qt.AlignTop lay.addWidget(g1, 0, 0, 1, len(g3), align) for i, g in enumerate(g2): lay.addWidget(g, 1, i, align) self.g3 = list() for i, gs in enumerate(g3): for j, g in enumerate(gs): if not j: self.g3.append(g) lay.addWidget(g, j + 2, i)
def __init__(self, parent=None, prefix='', is_main=False): """Init.""" super().__init__(parent) self.setObjectName('ITApp') ld_tienbl = QLabel('Enable Pulses', self, alignment=Qt.AlignCenter) bt_tienblsel = PyDMStateButton( self, prefix + 'IT-EGH:TI-TrigGen:ChanOut-Sel') led_tienblsts = SiriusLedState( self, prefix + 'IT-EGH:TI-TrigGen:ChanOut-Sts') lay = QGridLayout(self) lay.setAlignment(Qt.AlignCenter) lay.setContentsMargins(0, 0, 0, 0) glay = QGridLayout() glay.addWidget(ld_tienbl, 0, 0, 1, 2) glay.addWidget(bt_tienblsel, 1, 0) glay.addWidget(led_tienblsts, 1, 1) if not is_main: gbox = QGroupBox('Timing', self) gbox.setLayout(glay) lay.addWidget(gbox) else: lb_title = QLabel('<h3>IT - Timing</h3>', self, alignment=Qt.AlignCenter) lay.setHorizontalSpacing(15) lay.setVerticalSpacing(15) lay.addWidget(lb_title, 0, 0) lay.addLayout(glay, 1, 0)
def _setupUi(self): self.title = QLabel('<h2>PS & PU</h2>', alignment=Qt.AlignCenter) self.title.setStyleSheet('max-height:1.29em;') layout = QGridLayout(self) layout.setHorizontalSpacing(12) layout.addWidget(self.title, 0, 0, 1, 2) for sec in ['LI', 'TB', 'BO', 'TS', 'SI']: status = self._make_groupbox(sec) if sec == 'LI': layout.addWidget(status, 1, 0) elif sec == 'TB': layout.addWidget(status, 1, 1) elif sec == 'BO': layout.addWidget(status, 2, 0) elif sec == 'TS': layout.addWidget(status, 2, 1) elif sec == 'SI': layout.addWidget(status, 3, 0, 1, 2) layout.setColumnStretch(0, 6) layout.setColumnStretch(1, 5) self.setStyleSheet(""" QLed { min-height: 1.1em; max-height: 1.1em; min-width: 1.1em; max-width: 1.1em;} """)
def _setupUi(self): cw = QWidget(self) glay = QGridLayout(cw) glay.setHorizontalSpacing(10) glay.setVerticalSpacing(10) lab = QLabel('<h3>Booster Energy Ramping</h3>', cw) lab.setStyleSheet(""" min-height:1.55em; max-height: 1.55em; qproperty-alignment: 'AlignVCenter | AlignRight'; background-color: qlineargradient(spread:pad, x1:1, y1:0.0227273, x2:0, y2:0, stop:0 rgba(173, 190, 207, 255), stop:1 rgba(213, 213, 213, 255));""") glay.addWidget(lab, 0, 0, 1, 2) self.settings = Settings( self, self.prefix, self.ramp_config, self._tunecorr_configname, self._chromcorr_configname) self.setMenuBar(self.settings) self.status_and_commands = StatusAndCommands( self, self.prefix, self.ramp_config) glay.addWidget(self.status_and_commands, 1, 1) self.config_parameters = ConfigParameters( self, self.prefix, self.ramp_config, self._undo_stack, self._tunecorr_configname, self._chromcorr_configname) self.config_parameters.setObjectName('ConfigParameters') glay.addWidget(self.config_parameters, 1, 0) glay.setColumnStretch(0, 15) glay.setColumnStretch(1, 1) self.setCentralWidget(cw)
def _setupUi(self): self.sb_confignumber = QSpinBoxPlus(self) self.sb_confignumber.setMinimum(1) self.sb_confignumber.setMaximum(max(self.table_map['rows'].keys()) + 1) self.sb_confignumber.setStyleSheet("""max-width:5em;""") self.sb_confignumber.valueChanged.connect(self._searchConfigByIndex) self.bt_delete = QPushButton('Delete', self) self.bt_delete.setAutoDefault(False) self.bt_delete.setDefault(False) self.bt_delete.clicked.connect(self._emitConfigData) self.l_configid = QLabel('', self) self.l_configid.setSizePolicy(QSzPlcy.MinimumExpanding, QSzPlcy.Expanding) self.sb_confignumber.setValue(self.selected_row + 1) self._searchConfigByIndex(self.selected_row + 1) self.bt_cancel = QPushButton('Cancel', self) self.bt_cancel.setAutoDefault(False) self.bt_cancel.setDefault(False) self.bt_cancel.clicked.connect(self.close) glay = QGridLayout() glay.setVerticalSpacing(15) glay.setHorizontalSpacing(10) label = QLabel('<h4>Delete a Normalized Configuration</h4>', self) label.setAlignment(Qt.AlignCenter) glay.addWidget(label, 0, 0, 1, 2) glay.addWidget(self.sb_confignumber, 2, 0) glay.addWidget(self.l_configid, 2, 1) glay.addWidget(self.bt_cancel, 4, 0) glay.addWidget(self.bt_delete, 4, 1) self.setLayout(glay)
def create_statistics(self, wid, position=True): text, unit, names, _ = self._get_properties(position) wid = QWidget(wid) hbl = QHBoxLayout(wid) hbl.addStretch() grpbx = QGroupBox('Statistics', wid) hbl.addWidget(grpbx) hbl.addStretch() gdl = QGridLayout(grpbx) gdl.setHorizontalSpacing(20) gdl.setVerticalSpacing(20) stats = ('MeanValue', 'Sigma', 'MinValue', 'MaxValue') for j, stat in enumerate(('Average', 'Sigma', 'Minimum', 'Maximum')): lab = QLabel(stat, wid) lab.setAlignment(Qt.AlignCenter) gdl.addWidget(lab, 0, j+1) for i, name in enumerate(names): lab = QLabel(text[:3] + name, wid) lab.setAlignment(Qt.AlignCenter) gdl.addWidget(lab, i+1, 0) for j, stat in enumerate(stats): lab = SiriusLabel(wid, init_channel=self.get_pvname( name+'_STATS'+stat+'_RBV')) lab.setAlignment(Qt.AlignCenter) lab.unit_changed(unit) lab.showUnits = True lab.precisionFromPV = False lab.precision = 3 gdl.addWidget(lab, i+1, j+1) return wid
def _setupUi(self): self.currhist = self._setupTimeHistory() self.currhist.setVisible(not self.use_raw) self.rawreads = self._setupRawReadings() self.rawreads.setVisible(self.use_raw) self.pb_vis = QPushButton(self) self.pb_vis.setStyleSheet( 'QPushButton{min-width: 0.8em; max-width: 0.8em;}') self.menu_vis = QMenu() self.switch_act = self.menu_vis.addAction('Switch to ' + ( 'Time History' if self.use_raw else 'Raw Readings')) self.switch_act.triggered.connect(self._handle_data_visualization) self.pb_vis.setMenu(self.menu_vis) self.setStyleSheet(""" .QLabel{max-height:1.5em;} PyDMWaveformPlot, PyDMTimePlot{min-width:30em; min-height:20em;} """) lay = QGridLayout(self) lay.setContentsMargins(0, 0, 0, 0) lay.setHorizontalSpacing(0) lay.addWidget(self.pb_vis, 0, 0, alignment=Qt.AlignTop | Qt.AlignLeft) lay.addWidget(self.currhist, 0, 1) lay.addWidget(self.rawreads, 0, 1)
def _setupCoeffSettingsWidget(self): ld_coefchoo = QLabel('Choose Set', self, alignment=Qt.AlignRight) cb_coefchoo = PyDMEnumComboBox(self, self.dev_pref + ':LDSET') pb_coefload = PyDMPushButton(parent=self, label='Apply Set', icon=qta.icon('mdi.upload'), init_channel=self.dev_pref + ':BO_CPCOEFF', pressValue=1) pb_coefload.setStyleSheet("icon-size:20px;") pb_coefvrfy = PyDMPushButton(parent=self, label='Verify Set', icon=qta.icon('mdi.check-circle-outline'), init_channel=self.dev_pref + ':BO_CVERIFY', pressValue=1) pb_coefvrfy.setStyleSheet("icon-size:20px;") ld_gen = QLabel('<h4>Generate Coefficients</h4>', self, alignment=Qt.AlignCenter) ld_gengain = QLabel('Gain [0-1]', self, alignment=Qt.AlignRight) sb_gengain = PyDMSpinbox(self, self.dev_pref + ':FLT_GAIN') sb_gengain.showStepExponent = False ld_genphs = QLabel('Phase [°]', self, alignment=Qt.AlignRight) sb_genphs = PyDMSpinbox(self, self.dev_pref + ':FLT_PHASE') sb_genphs.showStepExponent = False ld_genfreq = QLabel('Frequency [0-1]', self, alignment=Qt.AlignRight) sb_genfreq = PyDMSpinbox(self, self.dev_pref + ':FLT_FREQ') sb_genfreq.showStepExponent = False ld_genntap = QLabel('Number of taps', self, alignment=Qt.AlignRight) sb_genntap = PyDMSpinbox(self, self.dev_pref + ':FLT_TAPS') sb_genntap.showStepExponent = False wid = QWidget(self) lay_genset = QGridLayout(wid) lay_genset.setVerticalSpacing(6) lay_genset.setHorizontalSpacing(9) lay_genset.addWidget(ld_gen, 0, 1, 1, 2) lay_genset.addWidget(ld_gengain, 1, 1) lay_genset.addWidget(sb_gengain, 1, 2) lay_genset.addWidget(ld_genphs, 2, 1) lay_genset.addWidget(sb_genphs, 2, 2) lay_genset.addWidget(ld_genfreq, 3, 1) lay_genset.addWidget(sb_genfreq, 3, 2) lay_genset.addWidget(ld_genntap, 4, 1) lay_genset.addWidget(sb_genntap, 4, 2) lay_genset.addWidget(ld_coefchoo, 5, 1) lay_genset.addWidget(cb_coefchoo, 5, 2) lay = QGridLayout() lay_genset.addLayout(lay, 6, 1, 1, 2) lay.addWidget(pb_coefload, 0, 0) lay.addWidget(pb_coefvrfy, 0, 2) lay.setColumnStretch(1, 2) lay_genset.setRowStretch(7, 2) lay_genset.setColumnStretch(0, 2) lay_genset.setColumnStretch(3, 2) return wid
def _setupUi(self): cwid = QWidget(self) self.setCentralWidget(cwid) title = QLabel('<h3>Machine Reports</h3>', self, alignment=Qt.AlignCenter) self._timesel_gbox = self._setupTimePeriodSelWidget() self._timesel_gbox.setObjectName('timesel_gbox') self._timesel_gbox.setStyleSheet( "#timesel_gbox{min-height: 8em; max-height: 8em;}") self._progress_list = QListWidget(self) self._progress_list.setObjectName('progress_list') self._progress_list.setStyleSheet( "#progress_list{min-height: 8em; max-height: 8em;}") self._reports_wid = QTabWidget(cwid) self._reports_wid.setObjectName('ASTab') self._reports_wid.addTab(self._setupUserShiftStatsWidget(), 'User Shift Stats') self._reports_wid.addTab(self._setupLightSourceUsageStats(), 'Light Source Usage Stats') self._reports_wid.addTab(self._setupStoredCurrentStats(), 'Stored Current Stats') self._pb_showraw = QPushButton(qta.icon('mdi.chart-line'), 'Show Raw Data', self) self._pb_showraw.setEnabled(False) self._pb_showraw.clicked.connect(self._show_raw_data) self._pb_showpvsd = QPushButton(qta.icon('mdi.chart-line'), 'Show Progrmd.vs.Delivered Hours', self) self._pb_showpvsd.setEnabled(False) self._pb_showpvsd.clicked.connect(self._show_progmd_vs_delivd) lay = QGridLayout(cwid) lay.setVerticalSpacing(10) lay.setHorizontalSpacing(10) lay.setContentsMargins(18, 9, 18, 9) lay.addWidget(title, 0, 0, 1, 3) lay.addWidget(self._timesel_gbox, 1, 0) lay.addWidget(self._progress_list, 1, 1, 1, 2, alignment=Qt.AlignBottom) lay.addWidget(self._reports_wid, 2, 0, 1, 3) lay.addWidget(self._pb_showpvsd, 4, 0, alignment=Qt.AlignLeft) lay.addWidget(self._pb_showraw, 4, 2, alignment=Qt.AlignRight) self._updateUserShiftStats(setup=True) self._updateStoredCurrentStats(setup=True) self._updateLightSourceUsageStats(setup=True)
def _setupUi(self): cw = QWidget(self) self.setCentralWidget(cw) self.title = QLabel('<h2>' + self.dev_desc + ' E-gun</h2>', self) wid_sysstatus = self._setupSysStatusWidget() wid_hvps = self._setupHVPSWidget() if self.sec == 'IT': wid_timing = ITTIWidget(self, self.prefix) wid_trigger = self._setupTriggerWidget() wid_filaps = self._setupFilaPSWidget() wid_biasps = self._setupBiasPSWidget() wid_pulseps = self._setupPulsePSWidget() wid_multipulseps = self._setupMultiPulsePSWidget() layout = QGridLayout(cw) layout.setVerticalSpacing(12) layout.setHorizontalSpacing(12) layout.addWidget(self.title, 0, 0, 1, 6) if self.sec == 'IT': layout.addWidget(wid_sysstatus, 1, 0, 2, 1) layout.addWidget(wid_hvps, 1, 1, 2, 4) layout.addWidget(wid_timing, 1, 5) layout.addWidget(wid_trigger, 2, 5) layout.addWidget(wid_filaps, 3, 0, 1, 6) layout.addWidget(wid_biasps, 4, 0, 1, 6) layout.addWidget(wid_pulseps, 5, 0, 1, 3) layout.addWidget(wid_multipulseps, 5, 3, 1, 3) layout.setRowStretch(1, 1) layout.setRowStretch(2, 3) else: layout.addWidget(wid_sysstatus, 1, 0, 1, 1) layout.addWidget(wid_hvps, 1, 1, 1, 4) layout.addWidget(wid_trigger, 1, 5) layout.addWidget(wid_filaps, 2, 0, 1, 6) layout.addWidget(wid_biasps, 3, 0, 1, 6) layout.addWidget(wid_pulseps, 4, 0, 1, 3) layout.addWidget(wid_multipulseps, 4, 3, 1, 3) layout.setColumnStretch(0, 3) layout.setColumnStretch(1, 2) layout.setColumnStretch(2, 2) layout.setColumnStretch(3, 2) layout.setColumnStretch(4, 2) layout.setColumnStretch(5, 3) self.setStyleSheet(""" QLabel{ max-height: 2em; qproperty-alignment: AlignCenter; }""")
def _setupUi(self): self.label_description = QLabel( '<h2>'+self.norm_config['label']+'</h2>', self) self.label_description.setAlignment(Qt.AlignCenter) self.label_time = QLabel('<h2>T = '+str(self.time)+'ms</h2>', self) self.label_time.setAlignment(Qt.AlignCenter) self.strengths = self._setupStrengthWidget() self.orbit = self._setupOrbitWidget() self.tune = self._setupTuneWidget() self.chrom = self._setupChromWidget() self.bt_apply = QPushButton(qta.icon('fa5s.angle-right'), '', self) self.bt_apply.setToolTip('Apply Changes to Machine') self.bt_apply.setStyleSheet('icon-size: 30px 30px;') self.bt_apply.clicked.connect(self._updateRampConfig) cw = QWidget() lay = QGridLayout() lay.setVerticalSpacing(10) lay.setHorizontalSpacing(10) lay.addWidget(self.label_description, 0, 0, 1, 2) lay.addWidget(self.label_time, 1, 0, 1, 2) lay.addWidget(self.strengths, 2, 0, 4, 1) lay.addWidget(self.orbit, 2, 1) lay.addWidget(self.tune, 3, 1) lay.addWidget(self.chrom, 4, 1) lay.addWidget(self.bt_apply, 5, 1) lay.setColumnStretch(0, 2) lay.setColumnStretch(1, 2) lay.setRowStretch(0, 2) lay.setRowStretch(1, 2) lay.setRowStretch(2, 8) lay.setRowStretch(3, 8) lay.setRowStretch(4, 8) lay.setRowStretch(5, 1) cw.setLayout(lay) cw.setStyleSheet(""" QGroupBox::title{ subcontrol-origin: margin; subcontrol-position: top center; padding: 0 2px 0 2px;}""") cw.setFocusPolicy(Qt.StrongFocus) self.setCentralWidget(cw)
def _setupUi(self): gbox_feedback = self._setupFBSettingsWidget() gbox_coefview = self._setupCoefficientsViewWidget() gbox_coefedit = self._setupCoefficientsEditWidget() lay = QGridLayout(self) lay.setAlignment(Qt.AlignLeft | Qt.AlignTop) lay.setVerticalSpacing(9) lay.setHorizontalSpacing(15) lay.addWidget(gbox_coefedit, 0, 0, 1, 2) lay.addWidget(gbox_feedback, 1, 0) if not self.dev_pref.endswith('-L'): gbox_bun_clean = self._setupBCSettingsWidget() lay.addWidget(gbox_bun_clean, 1, 1) lay.addWidget(gbox_coefview, 0, 2, 2, 1) lay.setColumnStretch(0, 2) lay.setColumnStretch(2, 1)
def _setupUi(self): self.gbox_reliablemeas = self._setupReliableMeasWidget() self.gbox_generalsettings = self._setupGeneralSettingsWidget() self.gbox_trigger = self._setupTriggerWidget() self.gbox_config = self._setupConfigurationWidget() self.gbox_normalmode = self._setupMeasSettingsWidget('Normal') self.gbox_fastmode = self._setupMeasSettingsWidget('Fast') lay_mode = QGridLayout() lay_mode.addWidget(self.gbox_normalmode, 0, 0) lay_mode.addWidget(self.gbox_fastmode, 0, 0) self.mode_channel = SiriusConnectionSignal( self.dcct_prefix.substitute(propty='MeasMode-Sel')) self.mode_channel.new_value_signal.connect(self._showMeasModeSettings) lay = QGridLayout() lay.addWidget( QLabel('<h3>' + self.device + ' Settings Details</h3>', self, alignment=Qt.AlignCenter), 0, 0, 1, 2) lay.addWidget(self.gbox_reliablemeas, 1, 0) lay.addWidget(self.gbox_generalsettings, 2, 0) lay.addWidget(self.gbox_config, 3, 0) lay.addWidget(self.gbox_trigger, 3, 1) lay.addLayout(lay_mode, 1, 1, 2, 1) lay.setVerticalSpacing(15) lay.setHorizontalSpacing(15) lay.setRowStretch(0, 1) lay.setRowStretch(1, 3) lay.setRowStretch(2, 7) lay.setRowStretch(3, 2) self.setLayout(lay) self.setStyleSheet(""" PyDMSpinbox, PyDMLabel{ min-width:6em; max-width:6em; qproperty-alignment: AlignCenter;} PyDMLedMultiChannel, PyDMStateButton, PyDMEnumComboBox{ min-width:6em; max-width:6em;}""")
def _setupStatusLayout(self): self.log = PyDMLogLabel( self, self.posang_prefix.substitute(propty='Log-Mon')) self.lb_sts0 = QLabel(Const.STATUSLABELS[0], self) self.led_sts0 = SiriusLedAlert( self, self.posang_prefix.substitute(propty='Status-Mon'), bit=0) self.lb_sts1 = QLabel(Const.STATUSLABELS[1], self) self.led_sts1 = SiriusLedAlert( self, self.posang_prefix.substitute(propty='Status-Mon'), bit=1) self.lb_sts2 = QLabel(Const.STATUSLABELS[2], self) self.led_sts2 = SiriusLedAlert( self, self.posang_prefix.substitute(propty='Status-Mon'), bit=2) self.lb_sts3 = QLabel(Const.STATUSLABELS[3], self) self.led_sts3 = SiriusLedAlert( self, self.posang_prefix.substitute(propty='Status-Mon'), bit=3) self.pb_config = PyDMPushButton( self, label='Config Correctors', pressValue=1, init_channel=self.posang_prefix.substitute(propty='ConfigPS-Cmd')) lay = QGridLayout() lay.setVerticalSpacing(12) lay.setHorizontalSpacing(12) lay.addWidget(self.log, 0, 0, 6, 1) lay.addWidget(self.lb_sts0, 1, 2) lay.addWidget(self.led_sts0, 1, 1) lay.addWidget(self.lb_sts1, 2, 2) lay.addWidget(self.led_sts1, 2, 1) lay.addWidget(self.lb_sts2, 3, 2) lay.addWidget(self.led_sts2, 3, 1) lay.addWidget(self.lb_sts3, 4, 2) lay.addWidget(self.led_sts3, 4, 1) lay.addWidget(self.pb_config, 5, 1, 1, 2) if self._tl == 'TS': self.led_corrtype = PyDMLedMultiChannel( self, {self.posang_prefix.substitute( propty='CH1-Cte'): self.corrs['CH1']}) self.lb_corrtype = QLabel( 'Control ' + ('CH-Sept' if self._is_chsept else 'Sept-Sept')) lay.addWidget(self.led_corrtype, 0, 1) lay.addWidget(self.lb_corrtype, 0, 2) return lay
def setupui(self): self.setupmenus() mainwid = QWidget(self) self.setCentralWidget(mainwid) gridlayout = QGridLayout(mainwid) gridlayout.setHorizontalSpacing(20) gridlayout.setVerticalSpacing(20) globpars = self.setglobalparameters() gridlayout.addWidget(globpars, 0, 0) splitter = QSplitter(Qt.Horizontal) gridlayout.addWidget(splitter, 1, 0) events = self.setevents() events.setObjectName('events') splitter.addWidget(events) triggers = self.settriggers() triggers.setObjectName('triggers') splitter.addWidget(triggers)
def displayTempGroup(self, pv_data, title): ''' Display one temperature group''' dtg_glay = QGridLayout() dtg_glay.setHorizontalSpacing(0) group = QGroupBox() count = [1, 1] dtg_glay = self.getSingleTitle(title, dtg_glay) for counter_prefix in range(1, pv_data[0][0] + 1): for counter_name in range(1, pv_data[0][1] + 1): pv_name = self.genStringTempPV(pv_data[1], counter_prefix, counter_name) dtg_glay.addLayout(self.tempMonBox(pv_name), count[0], count[1], 1, 1) count = self.updateCount(count, title) group.setTitle(title) group.setLayout(dtg_glay) return group
def _setupUi(self): lay = QGridLayout(self) lay.setAlignment(Qt.AlignTop) lay.setHorizontalSpacing(25) lay.setVerticalSpacing(15) self.title = QLabel( '<h4>LLRF Interlock Details</h4>', self, alignment=Qt.AlignCenter) lay.addWidget(self.title, 0, 0, 1, 3) # inputs col = 0 for name, dic in self.chs['LLRF Intlk Details']['Inputs'].items(): gbox = QGroupBox(name, self) lay_intlk = QGridLayout(gbox) lay_intlk.setAlignment(Qt.AlignTop) lay_intlk.setHorizontalSpacing(9) lay_intlk.setVerticalSpacing(0) icol = 0 for key in dic['Status']: desc = QLabel(key, self, alignment=Qt.AlignCenter) desc.setStyleSheet('QLabel{min-width:1em; max-width:2.5em;}') lay_intlk.addWidget(desc, 0, icol) icol += 1 labels = dic['Labels'] for idx, label in enumerate(labels): irow, icol = idx+1, 0 for key, pvn in dic['Status'].items(): led = SiriusLedAlert(self, self.prefix+pvn, bit=idx) led.shape = led.Square if key != 'Mon': led.offColor = led.DarkRed lay_intlk.addWidget(led, irow, icol) icol += 1 lbl = QLabel(label, self) lbl.setStyleSheet('QLabel{min-width:12em;}') lay_intlk.addWidget(lbl, irow, icol) lay.addWidget(gbox, 1, col) col += 1 # timestamps gbox_time = QGroupBox('Timestamps', self) lay_time = QGridLayout(gbox_time) lay_time.setAlignment(Qt.AlignTop) lay_time.setHorizontalSpacing(9) lay_time.setVerticalSpacing(9) for idx, pvn in self.chs['LLRF Intlk Details']['Timestamps'].items(): irow = int(idx)-1 desc = QLabel('Interlock '+idx, self, alignment=Qt.AlignCenter) desc.setStyleSheet('QLabel{min-width:6em;}') lbl = PyDMLabel(self, self.prefix+pvn) lbl.showUnits = True lay_time.addWidget(desc, irow, 0) lay_time.addWidget(lbl, irow, 1) lay.addWidget(gbox_time, 1, col)
def _setupUi(self): self._lb_desc = QLabel('<h3>Are you sure to Poweroff ' + self._device.dev + ' ' + self._device.idx + '?</h3>') self._pb_yes = PyDMPushButton(self, label='YES', pressValue=1, init_channel=self._mod_prefix + ':EMER_STOP') self._pb_yes.setObjectName('yes') self._pb_yes.setStyleSheet('#yes{background-color:red;}') self._pb_exit = QPushButton('EXIT', self) self._pb_exit.clicked.connect(self.close) lay = QGridLayout(self) lay.setHorizontalSpacing(20) lay.setVerticalSpacing(20) lay.addWidget(self._lb_desc, 0, 0, 1, 2) lay.addWidget(self._pb_yes, 1, 0, alignment=Qt.AlignCenter) lay.addWidget(self._pb_exit, 1, 1, alignment=Qt.AlignCenter)
def _setupDeltaControlLayout(self, axis=''): # pos label_pos = QLabel("<h4>Δ"+axis+"</h4>", self) sb_deltapos = PyDMSpinbox(self, self.posang_prefix.substitute( propty='DeltaPos'+axis.upper()+'-SP')) sb_deltapos.step_exponent = -2 sb_deltapos.update_step_size() sb_deltapos.showStepExponent = False lb_deltapos = PyDMLabel(self, self.posang_prefix.substitute( propty='DeltaPos'+axis.upper()+'-RB')) lb_deltapos.showUnits = True self._my_input_widgets.append(sb_deltapos) # ang label_ang = QLabel("<h4>Δ"+axis+"'</h4>", self) sb_deltaang = PyDMSpinbox(self, self.posang_prefix.substitute( propty='DeltaAng'+axis.upper()+'-SP')) sb_deltaang.step_exponent = -2 sb_deltaang.update_step_size() sb_deltaang.showStepExponent = False lb_deltaang = PyDMLabel(self, self.posang_prefix.substitute( propty='DeltaAng'+axis.upper()+'-RB')) lb_deltaang.showUnits = True self._my_input_widgets.append(sb_deltaang) lay = QGridLayout() lay.setVerticalSpacing(12) lay.setHorizontalSpacing(12) lay.addItem( QSpacerItem(10, 0, QSzPlcy.Expanding, QSzPlcy.Ignored), 0, 0) lay.addWidget(label_pos, 0, 1) lay.addWidget(sb_deltapos, 0, 2) lay.addWidget(lb_deltapos, 0, 3) lay.addWidget(label_ang, 1, 1) lay.addWidget(sb_deltaang, 1, 2) lay.addWidget(lb_deltaang, 1, 3) lay.addItem( QSpacerItem(10, 0, QSzPlcy.Expanding, QSzPlcy.Ignored), 0, 4) return lay
def _setupUi(self): lay = QGridLayout(self) lay.setAlignment(Qt.AlignTop) lay.setHorizontalSpacing(25) lay.setVerticalSpacing(15) self.title = QLabel( '<h3>RF Temperature Monitor</h3>', self, alignment=Qt.AlignCenter) lay.addWidget(self.title, 0, 0) if len(self.chs['TempMon']) == 1: dettab = QTabWidget(self) else: dettab = DetachableTabWidget(self) dettab.setObjectName(self.section+'Tab') for dettabtitle, dtcontent in self.chs['TempMon'].items(): if dettabtitle == 'Power': labels = list(dtcontent.keys()) channels = [self.prefix+ch for ch in dtcontent.values()] wid = BarGraph( channels=channels, xLabels=labels, yLabel='Power [kW]', title=dettabtitle) else: wid = QTabWidget() for tabtitle, content in dtcontent.items(): labels = list(content.keys()) channels = [self.prefix+ch for ch in content.values()] ylabel = 'Temperature [°C]' \ if 'temp' in dettabtitle.lower() \ else 'Diss. Power [kW]' tabwid = BarGraph( channels=channels, xLabels=labels, yLabel=ylabel, title=dettabtitle) wid.addTab(tabwid, tabtitle) dettab.addTab(wid, dettabtitle) lay.addWidget(dettab, 1, 0)
def _setupUi(self): label = QLabel('<h3>Sirius Monitor</h3>', alignment=Qt.AlignCenter) label.setStyleSheet('max-height:1.29em;') self.wid_asmon = PSMonitor(self, self._prefix, get_label2devices_method=get_label2devices, get_sec2devlaypos_method=get_sec2dev_laypos) self.wid_asmon.title.setText('<h3>PS, PU & RF</h3>') self.wid_asmon.setStyleSheet(""" QLed{ min-height: 0.98em; max-height: 0.98em; min-width: 0.98em; max-width: 0.98em;}""") self.wid_timon = TIMonitor(self, self._prefix) self.wid_timon.title.setText('<h3>TI</h3>') self.wid_timon.setStyleSheet(""" QLed{ min-height: 0.98em; max-height: 0.98em; min-width: 0.98em; max-width: 0.98em;}""") self.wid_mpsmon = LIMPSMonitor(self, self._prefix) self.wid_mpsmon.title.setText('<h3>LI MPS</h3>') self.wid_mpsmon.setObjectName('ASApp') self.wid_mpsmon.setStyleSheet(""" QLabel { qproperty-alignment: AlignCenter; } QLed{ min-height: 0.98em; max-height: 0.98em; min-width: 0.98em; max-width: 0.98em;}""") layout = QGridLayout(self) layout.setHorizontalSpacing(12) layout.addWidget(label, 0, 0, 1, 3) layout.addWidget(self.wid_asmon, 1, 0, alignment=Qt.AlignTop) layout.addWidget(self.wid_timon, 1, 1, alignment=Qt.AlignTop) layout.addWidget(self.wid_mpsmon, 1, 2, alignment=Qt.AlignTop)
def _setupUi(self): # controls self.ld_machsht = QLabel('<h3>Shift: </h3>', self, alignment=Qt.AlignCenter) self.lb_machsht = MachShiftLabel(self, prefix=self.prefix) self.lb_machsht.label.setStyleSheet('QLabel{font-size: 45pt;}') box_mach = QHBoxLayout() box_mach.addWidget(self.ld_machsht) box_mach.addWidget(self.lb_machsht) box_mach.setStretch(0, 1) box_mach.setStretch(1, 4) pvname = _PVName('RA-RaSIA02:RF-IntlkCtrl:IntlkSirius-Mon') pvname = pvname.substitute(prefix=self.prefix) self._led_siriusintlk = SiriusLedAlert(self, pvname) self._led_siriusintlk.setStyleSheet( 'QLed{min-width:3em;min-height:3em;max-width:3em;max-height:3em;}') self._gbox_siriusintlk = self._create_groupbox('Sirius Interlock', self._led_siriusintlk) self._led_injsyssts = InjSysStbyLed(self) self._led_injsyssts.setStyleSheet( 'QLed{min-width:3em;min-height:3em;max-width:3em;max-height:3em;}') self._gbox_injsyssts = self._create_groupbox('Injection System', self._led_injsyssts) pvname = _PVName('SI-Glob:AP-SOFB:LoopState-Sts') pvname = pvname.substitute(prefix=self.prefix) self._led_sofbloop = SiriusLedState(self, pvname) self._led_sofbloop.setStyleSheet( 'QLed{min-width:3em;min-height:3em;max-width:3em;max-height:3em;}') self._led_sofbloop.offColor = SiriusLedState.Red self._gbox_sofbloop = self._create_groupbox('SOFB Loop', self._led_sofbloop) bbbdev_pref = _PVName('SI-Glob:DI-BbBProc-L') bbbdev_pref = bbbdev_pref.substitute(prefix=self.prefix) self._led_bbbloop = SiriusLedState( self, bbbdev_pref.substitute(propty_name='FBCTRL')) self._led_bbbloop.setStyleSheet( 'QLed{min-width:3em;min-height:3em;max-width:3em;max-height:3em;}') self._led_bbbloop.offColor = SiriusLedState.Red chs2vals = { bbbdev_pref.substitute(propty_name='CLKMISS'): 0, bbbdev_pref.substitute(propty_name='PLL_UNLOCK'): 0, bbbdev_pref.substitute(propty_name='DCM_UNLOCK'): 0, bbbdev_pref.substitute(propty_name='ADC_OVR'): 0, bbbdev_pref.substitute(propty_name='SAT'): 0, bbbdev_pref.substitute(propty_name='FID_ERR'): 0 } self._led_bbbsts = PyDMLedMultiChannel(self, chs2vals) self._led_bbbsts.setStyleSheet( 'QLed{min-width:3em;min-height:3em;max-width:3em;max-height:3em;}') self._led_bbbsts.offColor = SiriusLedState.Red self._gbox_bbbloop = self._create_groupbox( 'BbB Loop', [self._led_bbbloop, self._led_bbbsts], orientation='H') # current self.ld_curr = QLabel('<h3>Current [mA]</h3>', self, alignment=Qt.AlignCenter) self.ld_curr.setStyleSheet('max-height: 2em;') pvname = _PVName('SI-Glob:AP-CurrInfo:Current-Mon') pvname = pvname.substitute(prefix=self.prefix) self.lb_curr = PyDMLabel(self, pvname) self.lb_curr.setAlignment(Qt.AlignCenter) self.lb_curr.setStyleSheet('QLabel{background-color: ' + self.app_color + ';font-size: 45pt;}') pvname = _PVName('SI-Glob:AP-CurrInfo:StoredEBeam-Mon') pvname = pvname.substitute(prefix=self.prefix) self.frm_curr = SiriusFrame( self, pvname, color_list=[SiriusFrame.DarkGreen, SiriusFrame.LightGreen], is_float=False) self.frm_curr.borderWidth = 5 self.frm_curr.add_widget(self.lb_curr) box_curr = QWidget() lay_curr = QVBoxLayout(box_curr) lay_curr.setAlignment(Qt.AlignVCenter) lay_curr.addWidget(self.ld_curr) lay_curr.addWidget(self.frm_curr) self.ld_lifetime = QLabel('<h3>Lifetime</h3>', self, alignment=Qt.AlignCenter) self.ld_lifetime.setStyleSheet('max-height: 2em;') self.lb_lifetime = QLabel('0:00:00', self, alignment=Qt.AlignCenter) self.lb_lifetime.setStyleSheet('QLabel{font-size: 45pt;}') pvname = _PVName('SI-Glob:AP-CurrInfo:Lifetime-Mon') pvname = pvname.substitute(prefix=self.prefix) self.ch_lifetime = SiriusConnectionSignal(pvname) self.ch_lifetime.new_value_signal[float].connect( self.formatLifetimeLabel) box_lt = QWidget() lay_lt = QVBoxLayout(box_lt) lay_lt.setAlignment(Qt.AlignVCenter) lay_lt.addWidget(self.ld_lifetime) lay_lt.addWidget(self.lb_lifetime) self.tune_mon = SITuneMonitor(self, self.prefix, description='short', use_color_labels=False) self.tune_mon.lb_tunefrach.setStyleSheet('QLabel{font-size: 45pt;}') self.tune_mon.lb_tunefracv.setStyleSheet('QLabel{font-size: 45pt;}') self.curr_graph = SiriusTimePlot(self) self.curr_graph.setObjectName('curr_graph') self.curr_graph.setStyleSheet( '#curr_graph{min-width: 20em; min-height: 14em;}') self.curr_graph.showXGrid = True self.curr_graph.showYGrid = True self.curr_graph.backgroundColor = QColor(255, 255, 255) self.curr_graph.setYLabels(['Current [mA]']) for ax in self.curr_graph.getPlotItem().axes.values(): sty = ax['item'].labelStyle sty['font-size'] = '18pt' ax['item'].setLabel(text=None, **sty) font = QFont() font.setPointSize(18) self.curr_graph.plotItem.getAxis('bottom').setStyle( tickTextOffset=5, autoExpandTextSpace=False, tickTextWidth=50, tickFont=font) self.curr_graph.plotItem.getAxis('left').setStyle( tickTextOffset=5, autoExpandTextSpace=False, tickTextWidth=50, tickFont=font) curr_pvname = _PVName('SI-Glob:AP-CurrInfo:Current-Mon') curr_pvname = curr_pvname.substitute(prefix=self.prefix) self.curr_graph.addYChannel(y_channel=curr_pvname, name='Current', color='blue', lineStyle=Qt.SolidLine, lineWidth=2) self.curve = self.curr_graph.curveAtIndex(0) self.curve.setFillLevel(0) self.curve.setBrush(QBrush(QGradient(QGradient.ColdEvening))) timespan = 12 * 60 * 60 self.curr_graph.timeSpan = timespan self.curr_graph.bufferSize = timespan * 10 self.curr_graph.maxRedrawRate = 2 t_end = Time.now() t_init = t_end - timespan self.curr_graph.fill_curve_with_archdata(self.curve, curr_pvname, t_init=t_init.get_iso8601(), t_end=t_end.get_iso8601(), process_type='mean', process_bin_intvl=10) cw = QWidget() hlay1 = QHBoxLayout() hlay1.setSpacing(30) hlay1.setAlignment(Qt.AlignVCenter) hlay1.addWidget(box_curr) hlay1.addWidget(box_lt) hlay1.addWidget(self.tune_mon) hlay2 = QHBoxLayout() hlay2.setSpacing(14) hlay2.addWidget(self._gbox_siriusintlk) hlay2.addWidget(self._gbox_injsyssts) hlay2.addWidget(self._gbox_sofbloop) hlay2.addWidget(self._gbox_bbbloop) hlay2.setStretch(0, 1) hlay2.setStretch(1, 1) hlay2.setStretch(2, 1) hlay2.setStretch(3, 1) lay = QGridLayout(cw) lay.setVerticalSpacing(16) lay.setHorizontalSpacing(14) lay.addLayout(box_mach, 0, 1) lay.addLayout(hlay1, 1, 0, 1, 3) lay.addWidget(self.curr_graph, 2, 0, 1, 3) lay.addLayout(hlay2, 3, 0, 1, 3) lay.setRowStretch(0, 1) lay.setRowStretch(1, 2) lay.setRowStretch(2, 10) lay.setRowStretch(3, 2) lay.setColumnStretch(0, 1) lay.setColumnStretch(1, 1) lay.setColumnStretch(2, 1) self.setCentralWidget(cw)
def _setupUi(self): self.cameraview_widget = QWidget() self.cameraview_widget.setLayout(self._cameraviewLayout()) self.settings_widget = QWidget(self) self.settings_widget.setLayout(self._settingsLayout()) self.settings_widget.setStyleSheet(""" .QLabel{ min-width: 5em;} QLabel{ qproperty-alignment: AlignCenter;}""") self.calibrationgrid_widget = QWidget(self) self.calibrationgrid_widget.setLayout(self._calibrationgridLayout()) self.calibrationgrid_widget.setSizePolicy(QSzPlcy.Expanding, QSzPlcy.Expanding) self.calibrationgrid_widget.layout().setAlignment(Qt.AlignHCenter) self.tab = QTabWidget(self) self.tab.setStyleSheet(""" QTabWidget::pane { border-left: 2px solid gray; border-bottom: 2px solid gray; border-right: 2px solid gray; }""") self.tab.addTab(self.settings_widget, 'Camera Settings') self.tab.addTab(self.calibrationgrid_widget, 'Calibration') self.statistics_groupBox = QGroupBox('Statistics', self) self.statistics_groupBox.setLayout(self._statisticsLayout()) self.statistics_groupBox.setSizePolicy(QSzPlcy.Expanding, QSzPlcy.Expanding) self.statistics_groupBox.setStyleSheet(""" .QLabel{ min-width:0.28em; max-width:0.28em; min-height:1.29em; max-height:1.29em;} QLabel{ qproperty-alignment: AlignCenter;} PyDMWidget{ min-width:4.84em; max-width:4.84em; min-height:1.29em; max-height:1.29em;}""") self.trigger_groupBox = QGroupBox('Trigger', self) if 'TB' in self.device or 'BO' in self.device: trg_prefix = 'AS-Fam:TI-Scrn-TBBO' elif 'TS' in self.device: trg_prefix = 'TS-Fam:TI-Scrn' hbl = QHBoxLayout(self.trigger_groupBox) hbl.addWidget( HLTriggerSimple(parent=self.trigger_groupBox, device=trg_prefix, prefix=self.prefix)) self.trigger_groupBox.setLayout(hbl) self.trigger_groupBox.setStyleSheet(""" PyDMWidget{ min-width:4.84em; max-width:4.84em; min-height:1.29em; max-height:1.29em;}""") vlay = QVBoxLayout() vlay.addWidget(self.statistics_groupBox) vlay.addWidget(self.trigger_groupBox) vlay.setSpacing(10) lay = QGridLayout(self) lay.setHorizontalSpacing(10) lay.setVerticalSpacing(10) lay.addWidget(self.cameraview_widget, 0, 0, 1, 2) lay.addWidget(self.tab, 1, 0) lay.addLayout(vlay, 1, 1) lay.setRowStretch(0, 15) lay.setRowStretch(1, 7)
def _setupUi(self): # Layout to enter matype_label = QLabel('Choose a magnet: ', self) self._matype_cb = QComboBox(self) self._matype_items = MASearch.get_pwrsupply_manames() self._matype_cb.addItem('Select...') self._matype_cb.addItems(self._matype_items) self._matype_cb.setEditable(True) self._matype_cb.setMaxVisibleItems(10) self._matype_cb.currentIndexChanged.connect( self._fill_normalizer_layout) hlmatype = QHBoxLayout() hlmatype.setAlignment(Qt.AlignLeft) hlmatype.addWidget(matype_label) hlmatype.addWidget(self._matype_cb) # Layout to enter normalizer data self._lb_current = QLabel('Current [A]: ') lb_arrow = QLabel('↔', self, alignment=Qt.AlignCenter) lb_arrow.setStyleSheet('min-width:1.2em; max-width:1.2em;') self._lb_strength = QLabel('Strength: ') self._lb_energy = QLabel('Dipole Energy [GeV]: ') self._lb_energy.setVisible(False) self._lb_quadfam_kl = QLabel('Family KL [1/m]: ') self._lb_quadfam_kl.setVisible(False) for name in ['_sb_current', '_sb_strength', '_sb_energy', '_sb_quadfam_kl']: setattr(self, name, QDoubleSpinBoxPlus()) sb = getattr(self, name) sb.setObjectName(name) sb.setValue(0) sb.setMinimum(-100000) sb.setMaximum(100000) sb.setDecimals(4) sb.setStyleSheet("min-width:8em; max-width:8em;") sb.editingFinished.connect(self._update_inputs) if name in ['_sb_current', '_sb_strength']: sb.setEnabled(False) else: sb.setVisible(False) norm_lay = QGridLayout() norm_lay.setAlignment(Qt.AlignLeft) norm_lay.setHorizontalSpacing(5) norm_lay.addItem( QSpacerItem(15, 1, QSzPlcy.Fixed, QSzPlcy.Ignored), 1, 0) norm_lay.addWidget(self._lb_current, 0, 1) norm_lay.addWidget(self._sb_current, 1, 1) norm_lay.addWidget(lb_arrow, 0, 2, 2, 1) norm_lay.addWidget(self._lb_strength, 0, 3) norm_lay.addWidget(self._sb_strength, 1, 3) norm_lay.addItem( QSpacerItem(15, 1, QSzPlcy.Fixed, QSzPlcy.Ignored), 1, 4) norm_lay.addWidget(self._lb_energy, 0, 5) norm_lay.addWidget(self._sb_energy, 1, 5) norm_lay.addItem( QSpacerItem(15, 1, QSzPlcy.Fixed, QSzPlcy.Ignored), 1, 6) norm_lay.addWidget(self._lb_quadfam_kl, 0, 7) norm_lay.addWidget(self._sb_quadfam_kl, 1, 7) self.norm_gb = QGroupBox('', self) self.norm_gb.setLayout(norm_lay) # General layout layout = QVBoxLayout() layout.setSpacing(20) layout.addWidget( QLabel('<h2>Offline Strength/Current Converter</h2>', self, alignment=Qt.AlignCenter)) layout.addLayout(hlmatype) layout.addWidget(self.norm_gb) cw = QWidget(self) cw.setObjectName('central_widget') cw.setStyleSheet("""#central_widget{min-width:42em;}""") cw.setLayout(layout) self.setCentralWidget(cw) self.setFocusPolicy(Qt.StrongFocus)
def _setupControlsWidget(self): ld_acqtime = QLabel('Acquisition Time [ms]', self) sb_acqtime = PyDMSpinbox(self, self.dev_pref + ':SB_ACQTIME') sb_acqtime.showStepExponent = False ld_bunid = QLabel('Bunch Number', self) sb_bunid = PyDMSpinbox(self, self.dev_pref + ':SB_BUNCH_ID') sb_bunid.showStepExponent = False ld_acqsmpl = QLabel('Acq Samples', self) lb_acqsmpl = PyDMLabel(self, self.dev_pref + ':SB_ACQ_SAMPLES') ld_currbun = QLabel('Current Bunch', self) lb_currbun = PyDMLabel(self, self.dev_pref + ':SB_RAW_BUNCH_ID') gbox_dtacq = QGroupBox('Data Acquisition', self) lay_dtacq = QGridLayout(gbox_dtacq) lay_dtacq.addWidget(ld_acqtime, 0, 0) lay_dtacq.addWidget(sb_acqtime, 0, 1) lay_dtacq.addWidget(ld_bunid, 1, 0) lay_dtacq.addWidget(sb_bunid, 1, 1) lay_dtacq.addWidget(ld_acqsmpl, 2, 0) lay_dtacq.addWidget(lb_acqsmpl, 2, 1) lay_dtacq.addWidget(ld_currbun, 3, 0) lay_dtacq.addWidget(lb_currbun, 3, 1) ld_trgexten = QLabel('Internal/External', self) cb_trgexten = PyDMEnumComboBox(self, self.dev_pref + ':SB_EXTEN') ld_trginsel = QLabel('Selection', self) cb_trginsel = PyDMEnumComboBox(self, self.dev_pref + ':SB_TRIG_IN_SEL') ld_trgarm = QLabel('Arm', self) cb_trgarm = PyDMStateButton(self, self.dev_pref + ':SB_ARM') lb_armmon = SiriusLedState(self, self.dev_pref + ':SB_ARM_MON') ld_trgbrarm = QLabel('Auto re-arm', self) cb_trgbrarm = PyDMStateButton(self, self.dev_pref + ':SB_BR_ARM') gbox_trig = QGroupBox('Trigger', self) lay_trig = QGridLayout(gbox_trig) lay_trig.addWidget(ld_trgexten, 0, 0) lay_trig.addWidget(cb_trgexten, 0, 1, 1, 2) lay_trig.addWidget(ld_trginsel, 1, 0) lay_trig.addWidget(cb_trginsel, 1, 1, 1, 2) lay_trig.addWidget(ld_trgarm, 2, 0) lay_trig.addWidget(cb_trgarm, 2, 1) lay_trig.addWidget(lb_armmon, 2, 2) lay_trig.addWidget(ld_trgbrarm, 3, 0) lay_trig.addWidget(cb_trgbrarm, 3, 1) ld_phtrkctrl = QLabel('<h4>Controls</h4>', self, alignment=Qt.AlignCenter) ld_bunnr = QLabel('Bunch Number', self) sb_bunnr = PyDMSpinbox(self, self.dev_pref + ':SB_BUNCH_ID') sb_bunnr.showStepExponent = False ld_gain = QLabel('Gain', self) sb_gain = PyDMSpinbox(self, self.dev_pref + ':PHTRK_GAIN') sb_gain.showStepExponent = False ld_sp = QLabel('Setpoint [deg]', self) sb_sp = PyDMSpinbox(self, self.dev_pref + ':PHTRK_SETPT') sb_sp.showStepExponent = False ld_range = QLabel('Range [kHz]', self) sb_range = PyDMSpinbox(self, self.dev_pref + ':PHTRK_RANGE') sb_range.showStepExponent = False ld_dec = QLabel('Decimation', self) sb_dec = PyDMSpinbox(self, self.dev_pref + ':PHTRK_DECIM') sb_dec.showStepExponent = False ld_rate = QLabel('Rate', self) lb_rate = PyDMLabel(self, self.dev_pref + ':PHTRK_RATE') lb_rate.showUnits = True ld_bw = QLabel('Bandwidth', self) lb_bw = PyDMLabel(self, self.dev_pref + ':PHTRK_BANDWIDTH') lb_bw.showUnits = True ld_loopctrl = QLabel('Loop Control', self) cb_loopctrl = PyDMStateButton(self, self.dev_pref + ':PHTRK_LOOPCTRL') ld_drv2 = QLabel('Use Drive 2', self) cb_drv2 = PyDMStateButton(self, self.dev_pref + ':DRIVE2_TRACK') ld_mod = QLabel('Modulation', self) cb_mod = PyDMStateButton(self, self.dev_pref + ':PHTRK_MOD') lay_phtrkctrl = QGridLayout() lay_phtrkctrl.addWidget(ld_phtrkctrl, 0, 0, 1, 2) lay_phtrkctrl.addWidget(ld_bunnr, 1, 0) lay_phtrkctrl.addWidget(sb_bunnr, 1, 1) lay_phtrkctrl.addWidget(ld_gain, 2, 0) lay_phtrkctrl.addWidget(sb_gain, 2, 1) lay_phtrkctrl.addWidget(ld_sp, 3, 0) lay_phtrkctrl.addWidget(sb_sp, 3, 1) lay_phtrkctrl.addWidget(ld_range, 4, 0) lay_phtrkctrl.addWidget(sb_range, 4, 1) lay_phtrkctrl.addWidget(ld_dec, 5, 0) lay_phtrkctrl.addWidget(sb_dec, 5, 1) lay_phtrkctrl.addWidget(ld_rate, 6, 0) lay_phtrkctrl.addWidget(lb_rate, 6, 1) lay_phtrkctrl.addWidget(ld_bw, 7, 0) lay_phtrkctrl.addWidget(lb_bw, 7, 1) lay_phtrkctrl.addWidget(ld_loopctrl, 8, 0) lay_phtrkctrl.addWidget(cb_loopctrl, 8, 1) lay_phtrkctrl.addWidget(ld_drv2, 9, 0) lay_phtrkctrl.addWidget(cb_drv2, 9, 1) lay_phtrkctrl.addWidget(ld_mod, 10, 0) lay_phtrkctrl.addWidget(cb_mod, 10, 1) ld_phtrkdata = QLabel('<h4>Data</h4>', self, alignment=Qt.AlignCenter) ld_mag = QLabel('Magnitude', self) lb_mag = PyDMLabel(self, self.dev_pref + ':PHTRK_MAG') lb_mag.showUnits = True ld_trgain = QLabel('Transfer Gain', self) lb_trgain = PyDMLabel(self, self.dev_pref + ':PHTRK_TFGAIN') lb_trgain.showUnits = True ld_nshift = QLabel('Normalizing Shift', self) lb_nshift = PyDMLabel(self, self.dev_pref + ':PHTRK_SHIFT') ld_phase = QLabel('Phase', self) lb_phase = PyDMLabel(self, self.dev_pref + ':PHTRK_PHASE') lb_phase.showUnits = True ld_error = QLabel('Error', self) lb_error = PyDMLabel(self, self.dev_pref + ':PHTRK_ERROR') lb_error.showUnits = True ld_trfreq = QLabel('Tracking Frequency', self) lb_trfreq = PyDMLabel(self, self.dev_pref + ':PHTRK_FREQ0') lb_trfreq.showUnits = True ld_trtune = QLabel('Tracking Tune', self) lb_trtune = PyDMLabel(self, self.dev_pref + ':PHTRK_TUNE') lay_phtrkdata = QGridLayout() lay_phtrkdata.addWidget(ld_phtrkdata, 0, 0, 1, 2) lay_phtrkdata.addWidget(ld_mag, 1, 0) lay_phtrkdata.addWidget(lb_mag, 1, 1) lay_phtrkdata.addWidget(ld_trgain, 2, 0) lay_phtrkdata.addWidget(lb_trgain, 2, 1) lay_phtrkdata.addWidget(ld_nshift, 3, 0) lay_phtrkdata.addWidget(lb_nshift, 3, 1) lay_phtrkdata.addWidget(ld_phase, 4, 0) lay_phtrkdata.addWidget(lb_phase, 4, 1) lay_phtrkdata.addWidget(ld_error, 5, 0) lay_phtrkdata.addWidget(lb_error, 5, 1) lay_phtrkdata.addWidget(ld_trfreq, 6, 0) lay_phtrkdata.addWidget(lb_trfreq, 6, 1) lay_phtrkdata.addWidget(ld_trtune, 7, 0) lay_phtrkdata.addWidget(lb_trtune, 7, 1) gbox_phtrk = QGroupBox('Phase Tracking', self) lay_phtrk = QGridLayout(gbox_phtrk) lay_phtrk.setHorizontalSpacing(20) lay_phtrk.addLayout(lay_phtrkctrl, 0, 0) lay_phtrk.addLayout(lay_phtrkdata, 1, 0) gbox_phtrk.setStyleSheet(""" PyDMLabel{ min-width: 6em; max-width: 6em; }""") wid = QWidget() lay = QGridLayout(wid) lay.addWidget(gbox_dtacq, 0, 0) lay.addWidget(gbox_trig, 1, 0) lay.addWidget(gbox_phtrk, 2, 0) return wid
class SliceViewerDataView(QWidget): """The view for the data portion of the sliceviewer""" def __init__(self, presenter: IDataViewSubscriber, dims_info, can_normalise, parent=None, conf=None): super().__init__(parent) self.presenter = presenter self.image = None self.line_plots_active = False self.can_normalise = can_normalise self.nonortho_transform = None self.conf = conf self._line_plots = None self._image_info_tracker = None self._region_selection_on = False self._orig_lims = None # Dimension widget self.dimensions_layout = QGridLayout() self.dimensions = DimensionWidget(dims_info, parent=self) self.dimensions.dimensionsChanged.connect(self.presenter.dimensions_changed) self.dimensions.valueChanged.connect(self.presenter.slicepoint_changed) self.dimensions_layout.addWidget(self.dimensions, 1, 0, 1, 1) self.colorbar_layout = QVBoxLayout() self.colorbar_layout.setContentsMargins(0, 0, 0, 0) self.colorbar_layout.setSpacing(0) self.image_info_widget = ImageInfoWidget(self) self.image_info_widget.setToolTip("Information about the selected pixel") self.track_cursor = QCheckBox("Track Cursor", self) self.track_cursor.setToolTip( "Update the image readout table when the cursor is over the plot. " "If unticked the table will update only when the plot is clicked") self.dimensions_layout.setHorizontalSpacing(10) self.dimensions_layout.addWidget(self.track_cursor, 0, 1, Qt.AlignRight) self.dimensions_layout.addWidget(self.image_info_widget, 1, 1) self.track_cursor.setChecked(True) self.track_cursor.stateChanged.connect(self.on_track_cursor_state_change) # normalization options if can_normalise: self.norm_label = QLabel("Normalization") self.colorbar_layout.addWidget(self.norm_label) self.norm_opts = QComboBox() self.norm_opts.addItems(["None", "By bin width"]) self.norm_opts.setToolTip("Normalization options") self.colorbar_layout.addWidget(self.norm_opts) # MPL figure + colorbar self.fig = Figure() self.ax = None self.image = None self._grid_on = False self.fig.set_facecolor(self.palette().window().color().getRgbF()) self.canvas = SliceViewerCanvas(self.fig) self.canvas.mpl_connect('button_release_event', self.mouse_release) self.canvas.mpl_connect('button_press_event', self.presenter.canvas_clicked) self.colorbar_label = QLabel("Colormap") self.colorbar_layout.addWidget(self.colorbar_label) norm_scale = self.get_default_scale_norm() self.colorbar = ColorbarWidget(self, norm_scale) self.colorbar.cmap.setToolTip("Colormap options") self.colorbar.crev.setToolTip("Reverse colormap") self.colorbar.norm.setToolTip("Colormap normalisation options") self.colorbar.powerscale.setToolTip("Power colormap scale") self.colorbar.cmax.setToolTip("Colormap maximum limit") self.colorbar.cmin.setToolTip("Colormap minimum limit") self.colorbar.autoscale.setToolTip("Automatically changes colormap limits when zooming on the plot") self.colorbar_layout.addWidget(self.colorbar) self.colorbar.colorbarChanged.connect(self.update_data_clim) self.colorbar.scaleNormChanged.connect(self.scale_norm_changed) # make width larger to fit image readout table self.colorbar.setMaximumWidth(200) # MPL toolbar self.toolbar_layout = QHBoxLayout() self.mpl_toolbar = SliceViewerNavigationToolbar(self.canvas, self, False) self.mpl_toolbar.gridClicked.connect(self.toggle_grid) self.mpl_toolbar.linePlotsClicked.connect(self.on_line_plots_toggle) self.mpl_toolbar.regionSelectionClicked.connect(self.on_region_selection_toggle) self.mpl_toolbar.homeClicked.connect(self.on_home_clicked) self.mpl_toolbar.nonOrthogonalClicked.connect(self.on_non_orthogonal_axes_toggle) self.mpl_toolbar.zoomPanClicked.connect(self.presenter.zoom_pan_clicked) self.mpl_toolbar.zoomPanFinished.connect(self.on_data_limits_changed) self.toolbar_layout.addWidget(self.mpl_toolbar) # Status bar self.status_bar = QStatusBar(parent=self) self.status_bar.setStyleSheet('QStatusBar::item {border: None;}') # Hide spacers between button and label self.status_bar_label = QLabel() self.help_button = QToolButton() self.help_button.setText("?") self.status_bar.addWidget(self.help_button) self.status_bar.addWidget(self.status_bar_label) # layout layout = QGridLayout(self) layout.setSpacing(1) layout.addLayout(self.dimensions_layout, 0, 0, 1, 2) layout.addLayout(self.toolbar_layout, 1, 0, 1, 1) layout.addLayout(self.colorbar_layout, 1, 1, 3, 1) layout.addWidget(self.canvas, 2, 0, 1, 1) layout.addWidget(self.status_bar, 3, 0, 1, 1) layout.setRowStretch(2, 1) @property def grid_on(self): return self._grid_on @property def line_plotter(self): return self._line_plots @property def nonorthogonal_mode(self): return self.nonortho_transform is not None def create_axes_orthogonal(self, redraw_on_zoom=False): """Create a standard set of orthogonal axes :param redraw_on_zoom: If True then when scroll zooming the canvas is redrawn immediately """ self.clear_figure() self.nonortho_transform = None self.ax = self.fig.add_subplot(111, projection='mantid') self.enable_zoom_on_mouse_scroll(redraw_on_zoom) if self.grid_on: self.ax.grid(self.grid_on) if self.line_plots_active: self.add_line_plots() self.plot_MDH = self.plot_MDH_orthogonal self.canvas.draw_idle() def create_axes_nonorthogonal(self, transform): self.clear_figure() self.set_nonorthogonal_transform(transform) self.ax = CurveLinearSubPlot(self.fig, 1, 1, 1, grid_helper=GridHelperCurveLinear( (transform.tr, transform.inv_tr))) # don't redraw on zoom as the data is rebinned and has to be redrawn again anyway self.enable_zoom_on_mouse_scroll(redraw=False) self.set_grid_on() self.fig.add_subplot(self.ax) self.plot_MDH = self.plot_MDH_nonorthogonal self.canvas.draw_idle() def enable_zoom_on_mouse_scroll(self, redraw): """Enable zoom on scroll the mouse wheel for the created axes :param redraw: Pass through to redraw option in enable_zoom_on_scroll """ self.canvas.enable_zoom_on_scroll(self.ax, redraw=redraw, toolbar=self.mpl_toolbar, callback=self.on_data_limits_changed) def add_line_plots(self, toolcls, exporter): """Assuming line plots are currently disabled, enable them on the current figure The image axes must have been created first. :param toolcls: Use this class to handle creating the plots :param exporter: Object defining methods to export cuts/roi """ if self.line_plots_active: return self.line_plots_active = True self._line_plots = toolcls(LinePlots(self.ax, self.colorbar), exporter) self.status_bar_label.setText(self._line_plots.status_message()) self.canvas.setFocus() self.mpl_toolbar.set_action_checked(ToolItemText.LINEPLOTS, True, trigger=False) def switch_line_plots_tool(self, toolcls, exporter): """Assuming line plots are currently enabled then switch the tool used to generate the plot curves. :param toolcls: Use this class to handle creating the plots """ if not self.line_plots_active: return # Keep the same set of line plots axes but swap the selection tool plotter = self._line_plots.plotter plotter.delete_line_plot_lines() self._line_plots.disconnect() self._line_plots = toolcls(plotter, exporter) self.status_bar_label.setText(self._line_plots.status_message()) self.canvas.setFocus() self.canvas.draw_idle() def remove_line_plots(self): """Assuming line plots are currently enabled, remove them from the current figure """ if not self.line_plots_active: return self._line_plots.plotter.close() self.status_bar_label.clear() self._line_plots = None self.line_plots_active = False def plot_MDH_orthogonal(self, ws, **kwargs): """ clears the plot and creates a new one using a MDHistoWorkspace """ self.clear_image() self.image = self.ax.imshow(ws, origin='lower', aspect='auto', transpose=self.dimensions.transpose, norm=self.colorbar.get_norm(), **kwargs) # ensure the axes data limits are updated to match the # image. For example if the axes were zoomed and the # swap dimensions was clicked we need to restore the # appropriate extents to see the image in the correct place extent = self.image.get_extent() self.ax.set_xlim(extent[0], extent[1]) self.ax.set_ylim(extent[2], extent[3]) # Set the original data limits which get passed to the ImageInfoWidget so that # the mouse projection to data space is correct for MDH workspaces when zoomed/changing slices self._orig_lims = self.get_axes_limits() self.on_track_cursor_state_change(self.track_cursor_checked()) self.draw_plot() def plot_MDH_nonorthogonal(self, ws, **kwargs): self.clear_image() self.image = pcolormesh_nonorthogonal(self.ax, ws, self.nonortho_transform.tr, transpose=self.dimensions.transpose, norm=self.colorbar.get_norm(), **kwargs) self.on_track_cursor_state_change(self.track_cursor_checked()) # swapping dimensions in nonorthogonal mode currently resets back to the # full data limits as the whole axes has been recreated so we don't have # access to the original limits # pcolormesh clears any grid that was previously visible if self.grid_on: self.ax.grid(self.grid_on) self.draw_plot() def plot_matrix(self, ws, **kwargs): """ clears the plot and creates a new one using a MatrixWorkspace keeping the axes limits that have already been set """ # ensure view is correct if zoomed in while swapping dimensions # compute required extent and just have resampling imshow deal with it old_extent = None if self.image is not None: old_extent = self.image.get_extent() if self.image.transpose != self.dimensions.transpose: e1, e2, e3, e4 = old_extent old_extent = e3, e4, e1, e2 self.clear_image() self.image = self.ax.imshow(ws, origin='lower', aspect='auto', interpolation='none', transpose=self.dimensions.transpose, norm=self.colorbar.get_norm(), extent=old_extent, **kwargs) self.on_track_cursor_state_change(self.track_cursor_checked()) self.draw_plot() def clear_image(self): """Removes any image from the axes""" if self.image is not None: if self.line_plots_active: self._line_plots.plotter.delete_line_plot_lines() self.image_info_widget.cursorAt(DBLMAX, DBLMAX, DBLMAX) if hasattr(self.ax, "remove_artists_if"): self.ax.remove_artists_if(lambda art: art == self.image) else: self.image.remove() self.image = None def clear_figure(self): """Removes everything from the figure""" if self.line_plots_active: self._line_plots.plotter.close() self.line_plots_active = False self.image = None self.canvas.disable_zoom_on_scroll() self.fig.clf() self.ax = None def draw_plot(self): self.ax.set_title('') self.canvas.draw() if self.image: self.colorbar.set_mappable(self.image) self.colorbar.update_clim() self.mpl_toolbar.update() # clear nav stack if self.line_plots_active: self._line_plots.plotter.delete_line_plot_lines() self._line_plots.plotter.update_line_plot_labels() def export_region(self, limits, cut): """ React to a region selection that should be exported :param limits: 2-tuple of ((left, right), (bottom, top)) :param cut: A str denoting which cuts to export. """ self.presenter.export_region(limits, cut) def update_plot_data(self, data): """ This just updates the plot data without creating a new plot. The extents can change if the data has been rebinned. """ if self.nonortho_transform: self.image.set_array(data.T.ravel()) else: self.image.set_data(data.T) self.colorbar.update_clim() def track_cursor_checked(self): return self.track_cursor.isChecked() if self.track_cursor else False def on_track_cursor_state_change(self, state): """ Called to notify the current state of the track cursor box """ if self._image_info_tracker is not None: self._image_info_tracker.disconnect() if self._line_plots is not None and not self._region_selection_on: self._line_plots.disconnect() self._image_info_tracker = ImageInfoTracker(image=self.image, transform=self.nonortho_transform, do_transform=self.nonorthogonal_mode, widget=self.image_info_widget, cursor_transform=self._orig_lims) if state: self._image_info_tracker.connect() if self._line_plots and not self._region_selection_on: self._line_plots.connect() else: self._image_info_tracker.disconnect() if self._line_plots and not self._region_selection_on: self._line_plots.disconnect() def on_home_clicked(self): """Reset the view to encompass all of the data""" self.presenter.show_all_data_clicked() def on_line_plots_toggle(self, state): """Switch state of the line plots""" self.presenter.line_plots(state) def on_region_selection_toggle(self, state): """Switch state of the region selection""" self.presenter.region_selection(state) self._region_selection_on = state # If state is off and track cursor is on, make sure line plots are re-connected to move cursor if not state and self.track_cursor_checked(): if self._line_plots: self._line_plots.connect() def on_non_orthogonal_axes_toggle(self, state): """ Switch state of the non-orthognal axes on/off """ self.presenter.nonorthogonal_axes(state) def on_data_limits_changed(self): """ React to when the data limits have changed """ self.presenter.data_limits_changed() def deactivate_and_disable_tool(self, tool_text): """Deactivate a tool as if the control had been pressed and disable the functionality""" self.deactivate_tool(tool_text) self.disable_tool_button(tool_text) def activate_tool(self, tool_text): """Activate a given tool as if the control had been pressed""" self.mpl_toolbar.set_action_checked(tool_text, True) def deactivate_tool(self, tool_text): """Deactivate a given tool as if the tool button had been pressed""" self.mpl_toolbar.set_action_checked(tool_text, False) def enable_tool_button(self, tool_text): """Set a given tool button enabled so it can be interacted with""" self.mpl_toolbar.set_action_enabled(tool_text, True) def disable_tool_button(self, tool_text): """Set a given tool button disabled so it cannot be interacted with""" self.mpl_toolbar.set_action_enabled(tool_text, False) def get_axes_limits(self): """ Return the limits on the image axes transformed into the nonorthogonal frame if appropriate """ if self.image is None: return None else: xlim, ylim = self.ax.get_xlim(), self.ax.get_ylim() if self.nonorthogonal_mode: inv_tr = self.nonortho_transform.inv_tr # viewing axis y not aligned with plot axis xmin_p, ymax_p = inv_tr(xlim[0], ylim[1]) xmax_p, ymin_p = inv_tr(xlim[1], ylim[0]) xlim, ylim = (xmin_p, xmax_p), (ymin_p, ymax_p) return xlim, ylim def get_full_extent(self): """ Return the full extent of image - only applicable for plots of matrix workspaces """ if self.image and isinstance(self.image, samplingimage.SamplingImage): return self.image.get_full_extent() else: return None def set_axes_limits(self, xlim, ylim): """ Set the view limits on the image axes to the given extents. Assume the limits are in the orthogonal frame. :param xlim: 2-tuple of (xmin, xmax) :param ylim: 2-tuple of (ymin, ymax) """ self.ax.set_xlim(xlim) self.ax.set_ylim(ylim) def set_grid_on(self): """ If not visible sets the grid visibility """ if not self._grid_on: self._grid_on = True self.mpl_toolbar.set_action_checked(ToolItemText.GRID, state=self._grid_on) def set_nonorthogonal_transform(self, transform): """ Set the transform for nonorthogonal axes mode :param transform: An object with a tr method to transform from nonorthognal coordinates to display coordinates """ self.nonortho_transform = transform def show_temporary_status_message(self, msg, timeout_ms): """ Show a message in the status bar that disappears after a set period :param msg: A str message to display :param timeout_ms: Timeout in milliseconds to display the message for """ self.status_bar.showMessage(msg, timeout_ms) def toggle_grid(self, state): """ Toggle the visibility of the grid on the axes """ self._grid_on = state self.ax.grid(self._grid_on) self.canvas.draw_idle() def mouse_release(self, event): if event.inaxes != self.ax: return self.canvas.setFocus() if event.button == 1: self._image_info_tracker.on_cursor_at(event.xdata, event.ydata) if self.line_plots_active and not self._region_selection_on: self._line_plots.on_cursor_at(event.xdata, event.ydata) if event.button == 3: self.on_home_clicked() def deactivate_zoom_pan(self): self.deactivate_tool(ToolItemText.PAN) self.deactivate_tool(ToolItemText.ZOOM) def update_data_clim(self): self.image.set_clim(self.colorbar.colorbar.mappable.get_clim()) if self.line_plots_active: self._line_plots.plotter.update_line_plot_limits() self.canvas.draw_idle() def set_normalization(self, ws, **kwargs): normalize_by_bin_width, _ = get_normalize_by_bin_width(ws, self.ax, **kwargs) is_normalized = normalize_by_bin_width or ws.isDistribution() self.presenter.normalization = is_normalized if is_normalized: self.norm_opts.setCurrentIndex(1) else: self.norm_opts.setCurrentIndex(0) def get_default_scale_norm(self): scale = 'Linear' if self.conf is None: return scale if self.conf.has(SCALENORM): scale = self.conf.get(SCALENORM) if scale == 'Power' and self.conf.has(POWERSCALE): exponent = self.conf.get(POWERSCALE) scale = (scale, exponent) scale = "SymmetricLog10" if scale == 'Log' else scale return scale def scale_norm_changed(self): if self.conf is None: return scale = self.colorbar.norm.currentText() self.conf.set(SCALENORM, scale) if scale == 'Power': exponent = self.colorbar.powerscale_value self.conf.set(POWERSCALE, exponent)
def _setupUi(self): lay_temp1 = QFormLayout() lay_temp1.setHorizontalSpacing(9) lay_temp1.setVerticalSpacing(9) lay_temp1.setLabelAlignment(Qt.AlignRight) lay_temp1.setFormAlignment(Qt.AlignTop) lb_temp1 = QLabel('Cell and Coupler\nTemperatures\nPT100', self) lb_temp1.setStyleSheet( 'font-weight:bold; qproperty-alignment:AlignCenter;') lay_temp1.addRow(lb_temp1) lims = self.chs['Cav Sts']['Temp']['Cells Limits'] tooltip = 'Interlock limits: \nMin: ' + str(lims[0]) + \ '°C, Max: '+str(lims[1])+'°C' for idx, cell in enumerate(self.chs['Cav Sts']['Temp']['Cells']): lbl = PyDMLabel(self, self.prefix+cell[0]) lbl.showUnits = True lbl.setStyleSheet('min-width:3.5em; max-width:3.5em;') led = PyDMLedMultiChannel( self, {self.prefix+cell[0]: {'comp': 'wt', 'value': lims}, self.prefix+cell[0].replace('T-Mon', 'TUp-Mon'): 0, self.prefix+cell[0].replace('T-Mon', 'TDown-Mon'): 0}) led.setToolTip(tooltip) hbox = QHBoxLayout() hbox.setAlignment(Qt.AlignLeft) hbox.addWidget(lbl) hbox.addWidget(led) lay_temp1.addRow('Cell '+str(idx + 1)+': ', hbox) ch_coup = self.chs['Cav Sts']['Temp']['Coupler'][0] lims_coup = self.chs['Cav Sts']['Temp']['Coupler Limits'] lb_coup = PyDMLabel(self, self.prefix+ch_coup) lb_coup.setStyleSheet('min-width:3.5em; max-width:3.5em;') lb_coup.showUnits = True led_coup = PyDMLedMultiChannel( self, {self.prefix+ch_coup: {'comp': 'wt', 'value': lims_coup}, self.prefix+ch_coup.replace('T-Mon', 'TUp-Mon'): 0, self.prefix+ch_coup.replace('T-Mon', 'TDown-Mon'): 0}) led_coup.setToolTip( 'Interlock limits: \n' 'Min: '+str(lims_coup[0])+'°C, Max: '+str(lims_coup[1])+'°C') hb_coup = QHBoxLayout() hb_coup.setAlignment(Qt.AlignLeft) hb_coup.addWidget(lb_coup) hb_coup.addWidget(led_coup) lay_temp1.addRow('Coupler: ', hb_coup) lay_temp2 = QFormLayout() lay_temp2.setHorizontalSpacing(9) lay_temp2.setVerticalSpacing(9) lay_temp2.setLabelAlignment(Qt.AlignRight) lay_temp2.setFormAlignment(Qt.AlignTop | Qt.AlignHCenter) lb_temp2 = QLabel('Cell\nTemperatures\nThermostats', self) lb_temp2.setStyleSheet( 'font-weight:bold; qproperty-alignment:AlignCenter;') lay_temp2.addRow(lb_temp2) for idx, cell in enumerate(self.chs['Cav Sts']['Temp']['Cells']): led = SiriusLedAlert(self) led.setToolTip('Interlock limits:\nMax: 60°C') led.channel = self.prefix+cell[0].replace('T-Mon', 'Tms-Mon') lay_temp2.addRow('Cell '+str(idx + 1)+': ', led) lay_dtemp = QFormLayout() lay_dtemp.setHorizontalSpacing(9) lay_dtemp.setVerticalSpacing(9) lay_dtemp.setLabelAlignment(Qt.AlignRight) lay_dtemp.setFormAlignment(Qt.AlignTop | Qt.AlignHCenter) lb_dtemp = QLabel('Disc\nTemperatures\nThermostats', self) lb_dtemp.setStyleSheet( 'font-weight:bold; qproperty-alignment:AlignCenter;') lay_dtemp.addRow(lb_dtemp) for idx, disc in enumerate(self.chs['Cav Sts']['Temp']['Discs']): led = SiriusLedAlert(self) led.setToolTip('Interlock limits:\nMax: 60°C') led.channel = self.prefix+disc lay_dtemp.addRow('Disc '+str(idx)+': ', led) self.led_hdflwrt1 = SiriusLedAlert( self, self.prefix+self.chs['Cav Sts']['FlwRt'][0]) self.led_hdflwrt2 = SiriusLedAlert( self, self.prefix+self.chs['Cav Sts']['FlwRt'][1]) self.led_hdflwrt3 = SiriusLedAlert( self, self.prefix+self.chs['Cav Sts']['FlwRt'][2]) lay_flwrt = QFormLayout() lay_flwrt.setHorizontalSpacing(9) lay_flwrt.setVerticalSpacing(9) lay_flwrt.setLabelAlignment(Qt.AlignRight) lay_flwrt.setFormAlignment(Qt.AlignTop) lb_flwrf = QLabel('Flow Switches', self) lb_flwrf.setStyleSheet( 'font-weight:bold; qproperty-alignment:AlignCenter;') lay_flwrt.addRow(lb_flwrf) lay_flwrt.addRow('Flow Switch 1: ', self.led_hdflwrt1) lay_flwrt.addRow('Flow Switch 2: ', self.led_hdflwrt2) lay_flwrt.addRow('Flow Switch 3: ', self.led_hdflwrt3) self.led_couppressure = SiriusLedAlert( self, self.prefix+self.chs['Cav Sts']['Vac']['Coupler ok']) self.led_pressure = SiriusLedAlert(self) self.led_pressure.setToolTip('Interlock limits:\nMax: 5e-7mBar') self.led_pressure.channel = \ self.prefix+self.chs['Cav Sts']['Vac']['Cells ok'] lay_vac = QFormLayout() lay_vac.setHorizontalSpacing(9) lay_vac.setVerticalSpacing(9) lay_vac.setLabelAlignment(Qt.AlignRight) lay_vac.setFormAlignment(Qt.AlignTop) lb_vac = QLabel('Vacuum', self) lb_vac.setStyleSheet( 'font-weight:bold; qproperty-alignment:AlignCenter;') lay_flwrt.addRow(lb_vac) lay_vac.addRow('Pressure Sensor: ', self.led_couppressure) lay_vac.addRow('Vacuum: ', self.led_pressure) lbl = QLabel('Cavity - Detailed Status', self) lbl.setStyleSheet( 'font-weight:bold; qproperty-alignment:AlignCenter;') lay = QGridLayout(self) lay.setHorizontalSpacing(30) lay.setVerticalSpacing(20) lay.addWidget(lbl, 0, 0, 1, 4) lay.addLayout(lay_temp1, 1, 0, 2, 1) lay.addLayout(lay_temp2, 1, 1, 2, 1) lay.addLayout(lay_dtemp, 1, 2, 2, 1) lay.addLayout(lay_flwrt, 1, 3) lay.addLayout(lay_vac, 2, 3) self.setStyleSheet(""" PyDMLabel{ qproperty-alignment: AlignLeft; } QLed{ max-width: 1.29em; } .QLabel{ max-height:4em; qproperty-alignment: AlignRight; }""")
def __init__(self, model, *args, **kwargs): self.model = model super().__init__(*args, **kwargs) self.setLayout(QFormLayout()) # Radiobuttons to quickly select default time period self.all_widget = QRadioButton("All") self.year_widget = QRadioButton("1 Year") self.month_widget = QRadioButton("30 Days") self.week_widget = QRadioButton("1 Week") self.today_widget = QRadioButton("24h") self.hour_widget = QRadioButton("1 Hour") self.radio_button_group = QButtonGroup() self.radio_button_group.addButton(self.all_widget) self.radio_button_group.addButton(self.year_widget) self.radio_button_group.addButton(self.month_widget) self.radio_button_group.addButton(self.week_widget) self.radio_button_group.addButton(self.today_widget) self.radio_button_group.addButton(self.hour_widget) default_period_layout = QGridLayout() default_period_layout.setHorizontalSpacing(85) default_period_layout.setVerticalSpacing(10) default_period_layout.addWidget(self.all_widget, 0, 0, 1, 2) default_period_layout.addWidget(self.year_widget, 1, 0, 1, 2) default_period_layout.addWidget(self.month_widget, 2, 0, 1, 2) default_period_layout.addWidget(self.week_widget, 0, 1, 1, 2) default_period_layout.addWidget(self.today_widget, 1, 1, 1, 2) default_period_layout.addWidget(self.hour_widget, 2, 1, 1, 2) self.layout().addRow("When:", default_period_layout) # TODO: rethink if restriction to acceptable timedelta values is required # from ..models.search.search_input import SearchInput # self.allowed = {timedelta(days=-1), timedelta(days=-30), timedelta(minutes=-60), timedelta(days=-7), # timedelta(days=-365)} # def time_validator(since=None, until=None): # """ # Enforce that since and until are values that a UI can represent. # This is an example similar to what will be used in the Qt UI. # """ # now = timedelta() # if isinstance(since, timedelta): # if not (until is None or until == now): # raise ValueError( # "This UI cannot express since=timedelta(...) unless until " # "is timedelta() or None." # ) # for item in allowed: # if since == item: # break # else: # # No matches # raise ValueError( # "This UI can only express since as a timedelta if it is " # f"one of {allowed}. The value {since} is not allowed" # ) # s = SearchInput() # s.time_validator = time_validator # "Since: <datetime picker>" self.since_widget = QDateTimeEdit() self.since_widget.setCalendarPopup(True) self.since_widget.setDisplayFormat("yyyy-MM-dd HH:mm") self.layout().addRow("Since:", self.since_widget) # "Until: <datetime picker>" self.until_widget = QDateTimeEdit() self.until_widget.setCalendarPopup(True) self.until_widget.setDisplayFormat("yyyy-MM-dd HH:mm") self.layout().addRow("Until:", self.until_widget) # Refresh Button self.refresh_button = QPushButton("Refresh") self.layout().addWidget(self.refresh_button) # Changes to the GUI update the model. self.since_widget.dateTimeChanged.connect(self.on_since_view_changed) self.until_widget.dateTimeChanged.connect(self.on_until_view_changed) self.refresh_button.clicked.connect(self.model.request_reload) self.model.events.reload.connect(self.on_reload) self.model.events.query.connect(self.on_reload) # Changes to the model update the GUI. self.model.events.since.connect(self.on_since_model_changed) self.model.events.until.connect(self.on_until_model_changed) # connect QRadioButtons and change date dropdowns (since/until widgets) accordingly self.hour_widget.toggled.connect(self.on_toggle_hour) self.today_widget.toggled.connect(self.on_toggle_24h) self.week_widget.toggled.connect(self.on_toggle_week) self.month_widget.toggled.connect(self.on_toggle_month) self.year_widget.toggled.connect(self.on_toggle_year) self.all_widget.toggled.connect(self.on_toggle_all) self.all_widget.setChecked(True)
def _setupUi(self): # Machine Shift self.wid_shift = QGroupBox('Machine Shift') machshift_pvname = SiriusPVName( 'AS-Glob:AP-MachShift:Mode-Sel').substitute(prefix=self._prefix) cbox_shift_mode = SiriusEnumComboBox(self, machshift_pvname) label_shift_mode = MachShiftLabel(self, self._prefix) label_shift_mode.label.setStyleSheet( 'QLabel{max-height: 2em; min-width: 7em;}') lay_shift = QGridLayout(self.wid_shift) lay_shift.setVerticalSpacing(5) lay_shift.setAlignment(Qt.AlignCenter) lay_shift.addWidget(cbox_shift_mode, 1, 0) lay_shift.addWidget(label_shift_mode, 2, 0) # Injection System self.wid_injsys = QGroupBox('Inj.System') wid_injsys = InjSysStbyControlWidget(self, self._prefix, is_summary=True) lay_injsys = QGridLayout(self.wid_injsys) lay_injsys.setAlignment(Qt.AlignCenter) lay_injsys.setContentsMargins(0, 0, 0, 0) lay_injsys.addWidget(wid_injsys) # Egun triggers self.wid_egun = QGroupBox('Egun Trig.') self.wid_egun.setStyleSheet('min-width: 5em;') egun_dev = SiriusPVName('LI-01:EG-TriggerPS').substitute( prefix=self._prefix) but_egun_trigger = PyDMStateButton( self, egun_dev.substitute(propty_name='enable')) led_egun_trigger = SiriusLedState( self, egun_dev.substitute(propty_name='enablereal')) lay_egun = QGridLayout(self.wid_egun) lay_egun.setVerticalSpacing(5) lay_egun.addWidget(but_egun_trigger, 1, 0) lay_egun.addWidget(led_egun_trigger, 2, 0) # injection control injctrl_dev = SiriusPVName('AS-Glob:AP-InjCtrl') injctrl_dev = injctrl_dev.substitute(prefix=self._prefix) self.wid_inject = QGroupBox('Injection') self.ch_injmode = SiriusConnectionSignal( injctrl_dev.substitute(propty='Mode-Sts')) self.ch_injmode.new_value_signal[int].connect( self._handle_injmode_settings_vis) # # Settings label_sett = QLabel('<h4>Sett.</h4>', self, alignment=Qt.AlignCenter) led_sett = InjDiagLed(self) self.wid_injsett = QWidget() lay_injsett = QGridLayout(self.wid_injsett) lay_injsett.setContentsMargins(0, 0, 0, 0) lay_injsett.setAlignment(Qt.AlignTop) lay_injsett.addWidget(label_sett, 0, 0) lay_injsett.addWidget(led_sett, 1, 0) # # Auto Stop self.label_injauto = QLabel('<h4>AutoStop</h4>', self, alignment=Qt.AlignCenter) self.but_injauto = PyDMStateButton( self, injctrl_dev.substitute(propty='AutoStop-Sel')) self.led_injauto = SiriusLedState( self, injctrl_dev.substitute(propty='AutoStop-Sts')) self.wid_injauto = QWidget() self.wid_injauto.setObjectName('wid') self.wid_injauto.setStyleSheet("#wid{min-width: 8em; max-width: 8em;}") lay_injauto = QGridLayout(self.wid_injauto) lay_injauto.setContentsMargins(0, 0, 0, 0) lay_injauto.setAlignment(Qt.AlignTop) lay_injauto.addWidget(self.label_injauto, 0, 0) lay_injauto.addWidget(self.but_injauto, 1, 0) lay_injauto.addWidget(self.led_injauto, 2, 0) # # Top-up status label_tusts = QLabel('<h4>Status</h4>', self, alignment=Qt.AlignCenter) label_tunow = ClockLabel(self) label_tunow.setStyleSheet('max-height:2em;') label_tunxt = SiriusLabel( self, injctrl_dev.substitute(propty='TopUpNextInj-Mon')) label_tunxt.displayFormat = SiriusLabel.DisplayFormat.Time label_tunxt.setAlignment(Qt.AlignCenter) label_tunxt.setStyleSheet('max-height:2em;') but_round = PyDMPushButton( self, '', qta.icon('mdi.tilde'), 1, False, injctrl_dev.substitute(propty='TopUpNextInjRound-Cmd')) but_round.setObjectName('but') but_round.setStyleSheet( '#but{min-width:18px; max-width:18px; icon-size:16px;}') self.wid_tusts = QWidget() self.wid_tusts.setObjectName('wid') self.wid_tusts.setStyleSheet("#wid{min-width: 8em; max-width: 8em;}") lay_tusts = QGridLayout(self.wid_tusts) lay_tusts.setContentsMargins(0, 0, 0, 0) lay_tusts.setAlignment(Qt.AlignTop) lay_tusts.addWidget(label_tusts, 0, 0, 1, 2) lay_tusts.addWidget(QLabel('Now:', self), 1, 0) lay_tusts.addWidget(label_tunow, 1, 1) lay_tusts.addWidget(QLabel('Next:', self), 2, 0) lay_tusts.addWidget(label_tunxt, 2, 1) lay_tusts.addWidget(but_round, 2, 2) self.wid_tusts.setVisible(False) # # Control label_inj = QLabel('<h4>Control</h4>', self, alignment=Qt.AlignCenter) self.but_tiinj = EVGInjectionButton(self, self._prefix) self.but_topup = PyDMStateButton( self, injctrl_dev.substitute(propty='TopUpState-Sel')) self.but_topup.setVisible(False) lay_inject_sel = QGridLayout() lay_inject_sel.setAlignment(Qt.AlignCenter) lay_inject_sel.addWidget(self.but_tiinj, 0, 0) lay_inject_sel.addWidget(self.but_topup, 0, 0) led_injsts = EVGInjectionLed(self, self._prefix) label_injcnt = PyDMLabel(self) label_injcnt.setToolTip( 'Count injection pulses when Egun Trigger is enabled.') label_injcnt.channel = SiriusPVName( 'AS-Glob:AP-CurrInfo:InjCount-Mon').substitute(prefix=self._prefix) label_injcnt.setStyleSheet('QLabel{max-width: 3.5em;}') lay_inject_sts = QHBoxLayout() lay_inject_sts.setContentsMargins(0, 0, 0, 0) lay_inject_sts.setAlignment(Qt.AlignTop) lay_inject_sts.addWidget(led_injsts) lay_inject_sts.addWidget(label_injcnt) self.wid_injctrl = QWidget() lay_injctrl = QGridLayout(self.wid_injctrl) lay_injctrl.setContentsMargins(0, 0, 0, 0) lay_injctrl.setAlignment(Qt.AlignTop) lay_injctrl.addWidget(label_inj, 0, 2, alignment=Qt.AlignCenter) lay_injctrl.addLayout(lay_inject_sel, 1, 2, alignment=Qt.AlignCenter) lay_injctrl.addLayout(lay_inject_sts, 2, 2, alignment=Qt.AlignCenter) # # Injection Auxiliary section self.wid_injlog = QGroupBox('Injection Log') label_injlog = PyDMLogLabel(self, injctrl_dev.substitute(propty='Log-Mon'), replace=[ 'Remaining time', ]) lay_injlog = QGridLayout(self.wid_injlog) lay_injlog.addWidget(label_injlog, 0, 0) self.wid_injlog.setVisible(False) self.wid_mon = MonitorSummaryWidget(self, self._prefix) self.wid_mon.setVisible(False) # # Target Current self._ld_currtgt = QLabel('<h4>Target Curr.</h4>', self, alignment=Qt.AlignCenter) self._sb_currtgt = SiriusSpinbox( self, injctrl_dev.substitute(propty='TargetCurrent-SP')) self._sb_currtgt.showStepExponent = False self._lb_currtgt = PyDMLabel( self, injctrl_dev.substitute(propty='TargetCurrent-RB')) self._lb_currtgt.showUnits = True self._wid_tcurr = QWidget() lay_tcurr = QGridLayout(self._wid_tcurr) lay_tcurr.setContentsMargins(0, 0, 0, 0) lay_tcurr.setAlignment(Qt.AlignTop) lay_tcurr.addWidget(self._ld_currtgt, 0, 0) lay_tcurr.addWidget(self._sb_currtgt, 1, 0) lay_tcurr.addWidget(self._lb_currtgt, 2, 0) # # Bucket List self._bucket_list = BucketList(self, prefix=self._prefix, min_size=15) self.wid_fill = QWidget() lay_fill = QGridLayout(self.wid_fill) lay_fill.setContentsMargins(0, 0, 0, 0) lay_fill.setHorizontalSpacing(9) lay_fill.addWidget(self._wid_tcurr, 0, 0) lay_fill.addWidget(self._bucket_list, 0, 1) self.wid_fill.setVisible(False) pbt_aux = QPushButton('v', self) pbt_aux.setToolTip('Show Injection Auxiliary section.') pbt_aux.clicked.connect(self._toggle_show_injaux) pbt_aux.setStyleSheet('QPushButton{max-width: 0.8em;}') pbt_bl = QPushButton('>', self) pbt_bl.setToolTip('Show bucket list and target current controls.') pbt_bl.clicked.connect(self._toggle_show_bucketlist) pbt_bl.setStyleSheet('QPushButton{max-width: 0.8em;}') lay_inj = QGridLayout(self.wid_inject) lay_inj.setAlignment(Qt.AlignTop) lay_inj.setVerticalSpacing(5) lay_inj.setHorizontalSpacing(12) lay_inj.addWidget(self.wid_injsett, 0, 0, 2, 1) lay_inj.addWidget(self.wid_injauto, 0, 1, 2, 1) lay_inj.addWidget(self.wid_tusts, 0, 1, 2, 1) lay_inj.addWidget(self.wid_injctrl, 0, 2, 2, 1) lay_inj.addWidget(pbt_bl, 0, 3, alignment=Qt.AlignTop) lay_inj.addWidget(pbt_aux, 1, 3, alignment=Qt.AlignBottom) lay_inj.addWidget(self.wid_fill, 0, 4, 2, 1) # Current curr_pvname = SiriusPVName( 'SI-Glob:AP-CurrInfo:Current-Mon').substitute(prefix=self._prefix) self.label_curr = PyDMLabel(self, curr_pvname) self.label_curr.showUnits = True self.label_curr.setStyleSheet(""" QLabel{ font-size: 18pt; qproperty-alignment: AlignCenter; min-width: 6em; max-width: 6em; }""") self.wid_curr = QGroupBox('Current') lay_curr = QHBoxLayout(self.wid_curr) lay_curr.addWidget(self.label_curr) # RF Kill Beam self.wid_rfkill = QGroupBox('RF Kill Beam') self.wid_rfkill.setObjectName('RFKillBeam') rfkill_bt = RFKillBeamButton(self, self._prefix) rfkill_lay = QGridLayout(self.wid_rfkill) rfkill_lay.addWidget(rfkill_bt) # menu buttons self.wid_pbt = QPushButton('v', self) self.wid_pbt.clicked.connect(self._toggle_show_menubutton) self.wid_pbt.setStyleSheet('QPushButton{max-width: 0.8em;}') self._menubutton = get_object(ismenubar=False, parent=self) self._menubutton.layout().setContentsMargins(0, 0, 0, 0) self._menubutton.layout().setSpacing(4) self._menubutton.setVisible(False) hlay1 = QHBoxLayout() hlay1.setContentsMargins(0, 0, 0, 0) hlay1.addWidget(self.wid_shift) hlay1.addWidget(self.wid_injsys) hlay1.addWidget(self.wid_egun) hlay1.addWidget(self.wid_inject) hlay1.addWidget(self.wid_curr) hlay1.addWidget(self.wid_rfkill) hlay2 = QHBoxLayout() hlay2.setContentsMargins(0, 0, 0, 0) hlay2.addWidget(self.wid_injlog) hlay2.addWidget(self.wid_mon) cwid = QWidget(self) lay = QGridLayout(cwid) lay.addLayout(hlay1, 0, 0) lay.addLayout(hlay2, 1, 0) lay.addWidget(self._menubutton, 2, 0, 1, 2) lay.addWidget(self.wid_pbt, 0, 1, 2, 1, alignment=Qt.AlignRight | Qt.AlignBottom) self.setCentralWidget(cwid)
def _setup_ui(self): # central widget self.central_widget = QWidget() self.setCentralWidget(self.central_widget) # tree gb_tree = QGroupBox('Select power supplies:') self.pwrsupplies_tree = PVNameTree(self._psnames, ('sec', 'mag_group'), tuple(), self) self.pwrsupplies_tree.tree.setHeaderHidden(True) self.pwrsupplies_tree.tree.setColumnCount(1) glay_tree = QVBoxLayout(gb_tree) glay_tree.addWidget(self.pwrsupplies_tree) # commands lb_prep_ti = QLabel('<h4>Prepare Timing</h4>', self, alignment=Qt.AlignCenter) ti_ch = [ PVName(name).substitute(prefix=VACA_PREFIX) for name in self._timing.get_pvnames_by_psnames() ] self.ticonn_led = PyDMLedMultiConn(self, channels=ti_ch) self.save_timing_bt = QPushButton('1. Save Timing Initial State', self) self.save_timing_bt.setToolTip( 'Save timing current state as initial state.') self.save_timing_bt.clicked.connect( _part(self._run_task, 'save_timing')) self.save_timing_bt.clicked.connect(self._set_lastcomm) self.prepare_timing_bt = QPushButton('2. Prepare Timing', self) self.prepare_timing_bt.setToolTip('Prepare EVG, triggers and events') self.prepare_timing_bt.clicked.connect(_part(self._run_task, 'timing')) self.prepare_timing_bt.clicked.connect(self._set_lastcomm) self.prepare_timing_lb = QLabel(self) self.prepare_timing_lb.setPixmap(self._pixmap_not) lb_prep_ps = QLabel('<h4>Prepare PS</h4>', self, alignment=Qt.AlignCenter) self.psconn_led = PyDMLedMultiConn(self) self.set_ps_sofbmode_off_bt = QPushButton('3. Turn off PS SOFBMode', self) self.set_ps_sofbmode_off_bt.setToolTip( 'Turn off power supplies SOFBMode.') self.set_ps_sofbmode_off_bt.clicked.connect( _part(self._run_task, 'ps_sofbmode')) self.set_ps_sofbmode_off_bt.clicked.connect(self._set_lastcomm) self.set_ps_sofbmode_off_lb = QLabel(self) self.set_ps_sofbmode_off_lb.setPixmap(self._pixmap_not) self.set_ps_opmode_slowref_bt = QPushButton( '4. Set PS OpMode to SlowRef', self) self.set_ps_opmode_slowref_bt.setToolTip( 'Set power supplies OpMode to SlowRef.') self.set_ps_opmode_slowref_bt.clicked.connect( _part(self._run_task, 'ps_om_slowref')) self.set_ps_opmode_slowref_bt.clicked.connect(self._set_lastcomm) self.set_ps_opmode_slowref_lb = QLabel(self) self.set_ps_opmode_slowref_lb.setPixmap(self._pixmap_not) self.set_ps_current_zero_bt = QPushButton('5. Set PS current to zero', self) self.set_ps_current_zero_bt.setToolTip( 'Set power supplies current to zero.') self.set_ps_current_zero_bt.clicked.connect( _part(self._run_task, 'ps_current')) self.set_ps_current_zero_bt.clicked.connect(self._set_lastcomm) self.set_ps_current_zero_lb = QLabel(self) self.set_ps_current_zero_lb.setPixmap(self._pixmap_not) self.prepare_ps_params_bt = QPushButton('6. Prepare PS Parameters', self) self.prepare_ps_params_bt.setToolTip( 'Check power supplies OpMode in SlowRef, check\n' 'current is zero and configure cycle parameters.') self.prepare_ps_params_bt.clicked.connect( _part(self._run_task, 'ps_params')) self.prepare_ps_params_bt.clicked.connect(self._set_lastcomm) self.prepare_ps_params_lb = QLabel(self) self.prepare_ps_params_lb.setPixmap(self._pixmap_not) self.prepare_ps_opmode_bt = QPushButton('7. Prepare PS OpMode', self) self.prepare_ps_opmode_bt.setToolTip( 'Set power supplies OpMode to Cycle.') self.prepare_ps_opmode_bt.clicked.connect( _part(self._run_task, 'ps_om_cycle')) self.prepare_ps_opmode_bt.clicked.connect(self._set_lastcomm) self.prepare_ps_opmode_lb = QLabel(self) self.prepare_ps_opmode_lb.setPixmap(self._pixmap_not) lb_cycle = QLabel('<h4>Cycle</h4>', self, alignment=Qt.AlignCenter) self.cycle_trims_bt = QPushButton('8. Cycle Trims', self) self.cycle_trims_bt.setToolTip( 'Cycle trims:\nStep 1) CH, QS and QTrims\nStep 2) CV') self.cycle_trims_bt.clicked.connect(_part(self._run_task, 'trims')) self.cycle_trims_bt.clicked.connect(self._set_lastcomm) self.cycle_trims_bt.setVisible(False) self.cycle_trims_lb = QLabel(self) self.cycle_trims_lb.setPixmap(self._pixmap_check) self.cycle_trims_lb.setVisible(False) self.cycle_bt = QPushButton('8. Cycle', self) self.cycle_bt.setToolTip( 'Check all configurations,\nenable triggers and run cycle.') self.cycle_bt.clicked.connect(_part(self._run_task, 'cycle')) self.cycle_bt.clicked.connect(self._set_lastcomm) self.cycle_bt.setEnabled(False) lb_rest_ti = QLabel('<h4>Restore Timing</h4>', self, alignment=Qt.AlignCenter) self.restore_timing_bt = QPushButton('9. Restore Timing Initial State', self) self.restore_timing_bt.setToolTip('Restore timing initial state.') self.restore_timing_bt.clicked.connect( _part(self._run_task, 'restore_timing')) self.restore_timing_bt.clicked.connect(self._set_lastcomm) self._prepared_labels = { 'timing': self.prepare_timing_lb, 'ps_sofbmode': self.set_ps_sofbmode_off_lb, 'ps_om_slowref': self.set_ps_opmode_slowref_lb, 'ps_current': self.set_ps_current_zero_lb, 'ps_params': self.prepare_ps_params_lb, 'ps_om_cycle': self.prepare_ps_opmode_lb, 'trims': self.cycle_trims_lb } gb_commsts = QGroupBox() gb_commsts.setStyleSheet(""" QPushButton{min-height:1.5em;} QLabel{qproperty-alignment: AlignCenter;}""") lay_commsts = QGridLayout(gb_commsts) lay_commsts.addItem( QSpacerItem(1, 1, QSzPlcy.Ignored, QSzPlcy.Expanding), 0, 0, 1, 2) lay_commsts.addWidget(lb_prep_ti, 1, 0) lay_commsts.addWidget(self.ticonn_led, 1, 1) lay_commsts.addWidget(self.save_timing_bt, 2, 0) lay_commsts.addWidget(self.prepare_timing_bt, 3, 0) lay_commsts.addWidget(self.prepare_timing_lb, 3, 1) lay_commsts.addItem( QSpacerItem(1, 1, QSzPlcy.Ignored, QSzPlcy.Expanding), 4, 0) lay_commsts.addWidget(lb_prep_ps, 5, 0) lay_commsts.addWidget(self.psconn_led, 5, 1) lay_commsts.addWidget(self.set_ps_sofbmode_off_bt, 6, 0) lay_commsts.addWidget(self.set_ps_sofbmode_off_lb, 6, 1) lay_commsts.addWidget(self.set_ps_opmode_slowref_bt, 7, 0) lay_commsts.addWidget(self.set_ps_opmode_slowref_lb, 7, 1) lay_commsts.addWidget(self.set_ps_current_zero_bt, 8, 0) lay_commsts.addWidget(self.set_ps_current_zero_lb, 8, 1) lay_commsts.addWidget(self.prepare_ps_params_bt, 9, 0) lay_commsts.addWidget(self.prepare_ps_params_lb, 9, 1) lay_commsts.addWidget(self.prepare_ps_opmode_bt, 10, 0) lay_commsts.addWidget(self.prepare_ps_opmode_lb, 10, 1) lay_commsts.addItem( QSpacerItem(1, 1, QSzPlcy.Ignored, QSzPlcy.Expanding), 11, 0) lay_commsts.addWidget(lb_cycle, 12, 0) lay_commsts.addWidget(self.cycle_trims_bt, 13, 0) lay_commsts.addWidget(self.cycle_trims_lb, 13, 1) lay_commsts.addWidget(self.cycle_bt, 14, 0) lay_commsts.addItem( QSpacerItem(1, 1, QSzPlcy.Ignored, QSzPlcy.Expanding), 15, 0) lay_commsts.addWidget(lb_rest_ti, 16, 0) lay_commsts.addWidget(self.restore_timing_bt, 17, 0) lay_commsts.addItem( QSpacerItem(1, 1, QSzPlcy.Ignored, QSzPlcy.Expanding), 18, 0) lay_commsts.setColumnStretch(0, 10) lay_commsts.setColumnStretch(1, 1) lay_commsts.setVerticalSpacing(12) lay_commsts.setHorizontalSpacing(6) self.label_lastcomm = QLabel('Last Command: ', self) self.clearhist_bt = QPushButton('Clear', self) self.clearhist_bt.clicked.connect(self._clear_lastcomm) lay_lc = QHBoxLayout() lay_lc.setContentsMargins(0, 0, 0, 0) lay_lc.addWidget(self.label_lastcomm, alignment=Qt.AlignLeft) lay_lc.addWidget(self.clearhist_bt, alignment=Qt.AlignRight) lay_lc.setStretch(0, 10) lay_lc.setStretch(1, 1) self.progress_list = QListWidget(self) self.progress_list.setObjectName('progresslist') self.progress_list.setStyleSheet('#progresslist{min-width:20em;}') self.progress_list.itemDoubleClicked.connect(self._open_ps_detail) self.progress_list.setSelectionMode(QAbstractItemView.MultiSelection) self.progress_list.setToolTip( 'Select rows and press Ctrl+C to copy and Esc to deselect.') self.progress_bar = MyProgressBar(self) lay_log = QVBoxLayout() lay_log.addLayout(lay_lc) lay_log.addWidget(self.progress_list) lay_log.addWidget(self.progress_bar) # connect tree signals self.pwrsupplies_tree.tree.doubleClicked.connect(self._open_ps_detail) self.pwrsupplies_tree.tree.itemChanged.connect( self._handle_checked_items_changed) self.pwrsupplies_tree.check_requested_levels(self._checked_accs) # layout layout = QGridLayout() layout.setVerticalSpacing(10) layout.setHorizontalSpacing(10) layout.addWidget( QLabel('<h3>PS Cycle</h3>', self, alignment=Qt.AlignCenter), 0, 0, 1, 3) layout.addWidget(gb_tree, 1, 0) layout.addWidget(gb_commsts, 1, 1) layout.addLayout(lay_log, 1, 2) layout.setRowStretch(0, 1) layout.setRowStretch(1, 15) layout.setColumnStretch(0, 5) layout.setColumnStretch(1, 4) layout.setColumnStretch(2, 8) self.central_widget.setLayout(layout)