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 _sort_connection_table(chans): dev = 'EVG' for k1, k2 in chans: if k1.dev == dev: dev = k1 break elif k2.dev == dev: dev = k2 break else: raise KeyError('EVG not Found.') entries = LLTimeSearch.get_channel_input( PVName(dev.device_name + ':' + 'UPLINK')) chans_sort = [] for entry in entries: mark = list(range(len(chans))) for i, ks in enumerate(chans): k1, k2 = ks if k1 == entry: entries.extend(LLTimeSearch.get_channel_input(k2)) chans_sort.append((k1, k2)) mark.remove(i) if k2 == entry: entries.extend(LLTimeSearch.get_channel_input(k1)) chans_sort.append((k2, k1)) mark.remove(i) chans = [chans[i] for i in mark] return chans_sort, chans
def setupmenus(self): main_menu = self.menuBar() main_menu.setNativeMenuBar(False) icon = qta.icon('mdi.timer', color=get_appropriate_color('AS')) menu = main_menu.addMenu('&Devices') action = menu.addAction('EVG') evg = SiriusPVName(LLTimeSearch.get_evg_name()) Window = create_window_from_widget(_EVG, title=evg, icon=icon) connect_window(action, Window, None, prefix=self.prefix, device=evg) menu_evr = menu.addMenu('EVRs') for evr in LLTimeSearch.get_device_names(filters={'dev': 'EVR'}): action = menu_evr.addAction(evr) Window = create_window_from_widget(_EVR, title=evr, icon=icon) connect_window(action, Window, None, prefix=self.prefix, device=evr) menu_eve = menu.addMenu('EVEs') for eve in LLTimeSearch.get_device_names(filters={'dev': 'EVE'}): action = menu_eve.addAction(eve) Window = create_window_from_widget(_EVE, title=eve, icon=icon) connect_window(action, Window, None, prefix=self.prefix, device=eve) menu_afc = menu.addMenu('AMCs') for afc in LLTimeSearch.get_device_names( filters={'dev': 'AMCFPGAEVR'}): action = menu_afc.addAction(afc) Window = create_window_from_widget(_AFC, title=afc, icon=icon) connect_window(action, Window, None, prefix=self.prefix, device=afc) menu_fout = menu.addMenu('Fouts') for fout in LLTimeSearch.get_device_names(filters={'dev': 'Fout'}): action = menu_fout.addAction(fout) Window = create_window_from_widget(_FOUT, title=fout, icon=icon) connect_window(action, Window, None, prefix=self.prefix, device=fout) action = main_menu.addAction('&Monitor') connect_newprocess(action, ['sirius-hla-as-ti-control.py', '-t', 'monitor'], parent=self, is_window=True)
def _set_source(self, value): if value is None: return dict() # BUG: I noticed that differently from the EVR and EVE IOCs, # the AMCFPGAEVR do not have a 'Dsbl' as first option of the enums # list. So I have to create this offset to fix this... offset = int(self.channel.dev.startswith('AMCFPGAEVR')) if value >= (len(self._source_enums)-1): return dict() pname = self._source_enums[value] n = _cstime.Const.TrigSrcLL._fields.index('Trigger') if pname.startswith('Dsbl'): dic_ = {'Src': n, 'Evt': _cstime.Const.EvtLL.Evt00} if pname.startswith('Clock'): n = _cstime.Const.TrigSrcLL._fields.index(pname) n -= offset dic_ = {'Src': n} else: n -= offset evt = int(_cstime.Const.EvtHL2LLMap[pname][-2:]) dic_ = {'Src': n, 'Evt': evt} if 'SrcTrig' in self._dict_convert_prop2pv.keys(): intrg = _LLTimeSearch.get_channel_internal_trigger_pvname( self.channel) intrg = int(intrg[-2:]) # get internal trigger number for EVR dic_['SrcTrig'] = intrg return dic_
def __init__(self, channel, prefix): """Initialize the Low Level object. callback is the callable to be called each time a low level PV changes its value. """ super().__init__() self.channel = _PVName(channel) self.prefix = prefix self._dict_functs_for_write = self._define_dict_for_write() self._dict_functs_for_update = self._define_dict_for_update() self._dict_functs_for_read = self._define_dict_for_read() self._dict_convert_prop2pv = self._define_convertion_prop2pv() self._dict_convert_pv2prop = { val: key for key, val in self._dict_convert_prop2pv.items() } self._config_ok_values = dict() self._base_freq = _RFFREQ / _RFDIV self._writepvs = dict() self._readpvs = dict() self._locked = False evg_name = _LLTimeSearch.get_evg_name() self._base_freq_pv = _PV(LL_PREFIX + evg_name + ':FPGAClk-Cte') self._update_base_freq() self._base_freq_pv.add_callback(self._update_base_freq) _log.info(self.channel + ': Creating PVs.') for prop, pvname in self._dict_convert_prop2pv.items(): pvnamerb = pvnamesp = None if not _PVName.is_write_pv(pvname): pvnamerb = pvname pvnamesp = _PVName.from_rb2sp(pvname) elif _PVName.is_cmd_pv(pvname): # -Cmd is different!! self._writepvs[prop] = _PV(pvname) if pvnamerb is not None: self._readpvs[prop] = _PV(pvnamerb) if pvnamesp != pvnamerb and not prop.endswith('DevEnbl'): self._writepvs[prop] = _PV(pvnamesp) self._writepvs[prop]._initialized = False for prop, pv in self._writepvs.items(): if not pv.wait_for_connection(): _log.info(pv.pvname + ' not connected.') for prop, pv in self._readpvs.items(): if not pv.wait_for_connection(): _log.info(pv.pvname + ' not connected.') for prop, pv in self._writepvs.items(): if _PVName.is_cmd_pv(pv.pvname): continue pv.add_callback(self._on_change_writepv) pv.connection_callbacks.append(self._on_connection_writepv) for prop, pv in self._readpvs.items(): pv.add_callback(self._on_change_readpv) pv.connection_callbacks.append(self._on_connection)
def __init__(self, channel, source_enums): fout_chan = _LLTimeSearch.get_fout_channel(channel) self._fout_out = int(fout_chan.propty[3:]) evg_chan = _LLTimeSearch.get_evg_channel(channel) self._evg_out = int(evg_chan.propty[3:]) self._source_enums = source_enums self._duration = None # I keep this for avoid rounding errors prefix = LL_PREFIX + _PVName(channel).device_name + ':' super().__init__(channel, prefix) # self._config_ok_values['DevEnbl'] = 1 # self._config_ok_values['FoutDevEnbl'] = 1 # self._config_ok_values['EVGDevEnbl'] = 1 if self.channel.propty.startswith('OUT'): intrg = _LLTimeSearch.get_channel_internal_trigger_pvname( self.channel) intrg = int(intrg.propty[-2:]) # get internal trigger number self._config_ok_values['SrcTrig'] = intrg # Stop using FineDelay and RF Delay to ease consistency: self._config_ok_values['FineDelay'] = 0 self._config_ok_values['RFDelay'] = 0
def setevents(self): props = {'name', 'ext_trig', 'mode', 'delay_type', 'delay'} evg_pref = LLTimeSearch.get_evg_name() names = list( map(lambda x: evg_pref.substitute(propty=x[1]), sorted(_cstime.Const.EvtLL2HLMap.items()))) names = [x for x in names if not x.endswith(('Dsbl', 'PsMtn'))] evts = _EventList(name='High Level Events', parent=self, prefix=self.prefix, props=props, obj_names=names) return evts
def _define_convertion_prop2pv(self): intlb = _LLTimeSearch.get_channel_internal_trigger_pvname(self.channel) outlb = _LLTimeSearch.get_channel_output_port_pvname(self.channel) intlb = intlb.propty outlb = outlb.propty evg_chan = _LLTimeSearch.get_evg_channel(self.channel) _evg_prefix = LL_PREFIX + evg_chan.device_name + ':' fout_chan = _LLTimeSearch.get_fout_channel(self.channel) _fout_prefix = LL_PREFIX + fout_chan.device_name + ':' map_ = { 'State': self.prefix + intlb + 'State-Sts', 'Evt': self.prefix + intlb + 'Evt-RB', 'Width': self.prefix + intlb + 'WidthRaw-RB', 'Polarity': self.prefix + intlb + 'Polarity-Sts', 'NrPulses': self.prefix + intlb + 'NrPulses-RB', 'Delay': self.prefix + intlb + 'DelayRaw-RB', 'Src': self.prefix + outlb + 'Src-Sts', 'SrcTrig': self.prefix + outlb + 'SrcTrig-RB', 'RFDelay': self.prefix + outlb + 'RFDelayRaw-RB', 'FineDelay': self.prefix + outlb + 'FineDelayRaw-RB', 'RFDelayType': self.prefix + outlb + 'RFDelayType-Sts', # connection status PVs 'DevEnbl': self.prefix + 'DevEnbl-Sts', 'Network': self.prefix + 'Network-Mon', 'Link': self.prefix + 'LinkStatus-Mon', 'Intlk': self.prefix + 'IntlkStatus-Mon', 'Los': self.prefix + 'Los-Mon', 'EVGLos': _evg_prefix + 'Los-Mon', 'FoutLos': _fout_prefix + 'Los-Mon', 'FoutDevEnbl': _fout_prefix + 'DevEnbl-Sts', 'EVGDevEnbl': _evg_prefix + 'DevEnbl-Sts', } for prop in self._REMOVE_PROPS: map_.pop(prop) return map_
def setglobalparameters(self): wid = QWidget(self.centralWidget()) wid.setSizePolicy(QSzPol.Preferred, QSzPol.Maximum) lay = QGridLayout(wid) evg_dev = SiriusPVName(LLTimeSearch.get_evg_name()) evg_pref = evg_dev.substitute(prefix=self.prefix) sp = PyDMPushButton( self, init_channel=evg_pref.substitute(propty='UpdateEvt-Cmd'), pressValue=1) sp.setIcon(qta.icon('fa5s.sync')) sp.setToolTip('Update Events Table') sp.setObjectName('but') sp.setStyleSheet( '#but{min-width:25px; max-width:25px; icon-size:20px;}') rb = PyDMLed( self, init_channel=evg_pref.substitute(propty='EvtSyncStatus-Mon')) rb.setOffColor(rb.Red) rb.setOnColor(rb.LightGreen) lay.addWidget( self._create_prop_widget('<h4>Update Evts</h4>', wid, (sp, rb)), 0, 0) sp = PyDMStateButton( self, init_channel=evg_pref.substitute(propty='ContinuousEvt-Sel')) rb = PyDMLed( self, init_channel=evg_pref.substitute(propty='ContinuousEvt-Sts')) lay.addWidget( self._create_prop_widget('<h4>Continuous</h4>', wid, (sp, rb)), 0, 1) sp = PyDMStateButton( self, init_channel=evg_pref.substitute(propty='InjectionEvt-Sel')) rb = PyDMLed( self, init_channel=evg_pref.substitute(propty='InjectionEvt-Sts')) lay.addWidget( self._create_prop_widget('<h4>Injection</h4>', wid, (sp, rb)), 0, 2) bucketlist_wid = BucketList(self.centralWidget(), evg_dev, self.prefix) bucketlist_wid.setSizePolicy(QSzPol.MinimumExpanding, QSzPol.Preferred) lay.addWidget(bucketlist_wid, 0, 3, 2, 1) hlay = QHBoxLayout() lab = QLabel('Inj Count:', wid) pydmlab = PyDMLabel( wid, init_channel=evg_pref.substitute(propty='InjCount-Mon')) pydmlab.setStyleSheet('min-width:5em;') pydmlab.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) hlay.addStretch() hlay.addWidget(lab) hlay.addWidget(pydmlab) hlay.addStretch() pydmlab = PyDMLabel( wid, init_channel=evg_pref.substitute(propty='STATEMACHINE')) pydmlab.setStyleSheet('min-width:10em;') hlay.addWidget(pydmlab) hlay.addStretch() pydmlab = PyDMLabel( wid, init_channel=evg_pref.substitute(propty='SeqCount-SP')) pydmlab.rules =\ '[{"name": "VisibleRule", "property": "Visible", ' +\ '"expression": "ch[0]==5", "channels": [{"channel": "' +\ evg_pref.substitute(propty_name='STATEMACHINE') +\ '", "trigger": true}]}]' pydmlab.setStyleSheet('min-width:3em;') hlay.addWidget(pydmlab) hlay.addStretch() lay.addItem(hlay, 1, 0, 1, 3) return wid
"""Timing widgets.""" import qtawesome as qta from pydm.widgets import PyDMPushButton from siriuspy.envars import VACA_PREFIX from siriuspy.namesys import SiriusPVName from siriuspy.search import LLTimeSearch as _LLTimeSearch from ..widgets import PyDMStateButton, PyDMLed, SiriusLedAlert EVG_NAME = _LLTimeSearch.get_evg_name() class EVGContinuousLed(PyDMLed): """EVG Continuous Led.""" def __init__(self, parent=None, prefix=VACA_PREFIX): """Init.""" pref_dev = SiriusPVName(EVG_NAME).substitute(prefix=prefix) color_list = 7 * [ self.LightGreen, ] color_list[0] = self.DarkGreen # Initializing color_list[1] = self.DarkGreen # Stopped color_list[4] = self.Yellow # Preparing Continuous color_list[6] = self.Yellow # Restarting Continuous super().__init__( parent=parent, init_channel=pref_dev.substitute(propty_name='STATEMACHINE'), color_list=color_list)
def _process_src_trig(self, src_trig, is_sp): invalid = len(self._source_enums)-1 # Invalid option intrg = _LLTimeSearch.get_channel_internal_trigger_pvname(self.channel) intrg = int(intrg.propty[-2:]) # get internal trigger number for EVR if src_trig != intrg: return {'Src': invalid}
'sec': 'BO', 'dis': 'PS', 'sub': '[0-9]{2}.*', }) pss.extend( PSSearch.get_psnames({ 'sec': 'SI', 'dis': 'PS', 'sub': '[0-9]{2}.*', 'dev': '[QC]' })) trigs = dict() for i, ps in enumerate(pss): chan = ps.substitute(propty_name='BCKPLN') trig = LLTimeSearch.get_trigger_name(chan) if trig in trigs: trigs[trig].add(ps) else: trigs[trig] = { ps, } pvs_ps = list() for ps in sorted(pss): pvs_ps.append( PV( ps.substitute(propty_name='WfmSyncPulseCount', propty_suffix='Mon'))) pvs_trig_sp = dict()
def _setupRawReadings(self): self.label_waveread = QLabel('<h3>Current Raw Readings</h3>', self, alignment=Qt.AlignCenter) self.wavegraph = PyDMWaveformPlot(self) self.wavegraph.setLabels(left='Current [mA]', bottom='Index') channel = 'FAKE:Readings' self.rawreadings_channel = SignalChannel( self.dcct_prefix.substitute(propty='RawReadings-Mon')) self.rawreadings_channel.new_value_signal[np.ndarray].connect( self._updateRawBuffer) self.wavegraph.addChannel(y_channel=channel, name='Current Raw Readings', color='blue', lineWidth=2, lineStyle=Qt.SolidLine) self.wavegraph.autoRangeX = True self.wavegraph.autoRangeY = True self.wavegraph.backgroundColor = QColor(255, 255, 255) self.wavegraph.showLegend = False self.wavegraph.showXGrid = True self.wavegraph.showYGrid = True self.wavegraph.plotItem.showButtons() self.wavecurve = self.wavegraph.curveAtIndex(0) wid = QWidget() lay = QGridLayout(wid) lay.setAlignment(Qt.AlignTop) lay.setRowStretch(0, 1) lay.setRowStretch(1, 9) lay.addWidget(self.label_waveread, 0, 0) lay.addWidget(self.wavegraph, 1, 0) # Smoothing evgname = SiriusPVName(_LLTimeSearch.get_evg_name()) self._evnt_dly = SignalChannel( evgname.substitute(prefix=self.prefix, propty='Dig' + self.device.sec + 'Delay-RB')) self._evnt_dly.new_value_signal[float].connect(self.updateRawXAxis) self._trig_dly = SignalChannel( self.dcct_prefix.substitute(dis='TI', propty='Delay-RB')) self._trig_dly.new_value_signal[float].connect(self.updateRawXAxis) self._smpl_cnt = SignalChannel( self.dcct_prefix.substitute(propty='FastSampleCnt-RB')) self._smpl_cnt.new_value_signal[float].connect(self.updateRawXAxis) self._meas_per = SignalChannel( self.dcct_prefix.substitute(propty='FastMeasPeriod-RB')) self._meas_per.new_value_signal[float].connect(self.updateRawXAxis) self.cb_timeaxis = QCheckBox('Use time axis', self) self.cb_timeaxis.setChecked(True) self.cb_timeaxis.stateChanged.connect(self.updateRawXAxis) self.cb_timeaxis.setLayoutDirection(Qt.RightToLeft) lay.addWidget(self.cb_timeaxis, 2, 0, alignment=Qt.AlignLeft) lay.setRowStretch(2, 1) l_smoothmethod = QLabel('Method: ', self) self.cb_smoothmethod = QComboBox(self) self.cb_smoothmethod.addItems(['Average', 'Median']) self.cb_smoothmethod.currentTextChanged.connect( self.setRawSmoothMethod) l_smoothnracq = QLabel('Nr.Acqs.: ', self) self.sb_smoothnracq = QSpinBoxPlus(self) self.sb_smoothnracq.setValue(1) self.sb_smoothnracq.valueChanged.connect(self.setRawSmoothNrAcq) l_smoothbuff = QLabel('Buffer Size: ', self) l_smoothbuff.setSizePolicy(QSzPly.Minimum, QSzPly.Preferred) self.label_buffsize = QLabel('', self) self.label_buffsize.setStyleSheet('min-width:3em; max-width:3em;') self.pb_resetbuff = QPushButton(qta.icon('mdi.delete-empty'), '', self) self.pb_resetbuff.setToolTip('Reset buffer') self.pb_resetbuff.setObjectName('resetbuff') self.pb_resetbuff.setStyleSheet( "#resetbuff{min-width:25px; max-width:25px; icon-size:20px;}") self.pb_resetbuff.clicked.connect(self.resetRawBuffer) hlay_buff = QHBoxLayout() hlay_buff.addWidget(self.label_buffsize) hlay_buff.addWidget(self.pb_resetbuff) l_down = QLabel('Downsampling: ', self) self.sb_down = QSpinBoxPlus(self) self.sb_down.setValue(1) self.sb_down.valueChanged.connect(self.setRawDownsampling) gbox_smooth = QGroupBox('Smoothing of Readings') glay_smooth = QGridLayout(gbox_smooth) glay_smooth.addWidget(l_smoothmethod, 0, 0) glay_smooth.addWidget(self.cb_smoothmethod, 0, 1) glay_smooth.addWidget(l_smoothnracq, 1, 0) glay_smooth.addWidget(self.sb_smoothnracq, 1, 1) glay_smooth.addWidget(QLabel(''), 0, 2) glay_smooth.addWidget(l_smoothbuff, 0, 3) glay_smooth.addLayout(hlay_buff, 0, 4, 1, 2) glay_smooth.addWidget(l_down, 1, 3) glay_smooth.addWidget(self.sb_down, 1, 4, 1, 2) glay_smooth.setColumnStretch(0, 10) glay_smooth.setColumnStretch(1, 10) glay_smooth.setColumnStretch(2, 2) glay_smooth.setColumnStretch(3, 10) glay_smooth.setColumnStretch(4, 5) glay_smooth.setColumnStretch(5, 5) lay.addWidget(gbox_smooth, 3, 0) lay.setRowStretch(3, 3) gbox_smooth.setStyleSheet(""" .QLabel{ qproperty-alignment: 'AlignVCenter | AlignRight';} QPushButton{ min-width:3em; max-width:3em;}""") return wid