commit 9bdd59a110b19d1814f2612c107fc45cffe57012 Author: chrin Date: Mon Jan 10 13:18:29 2022 +0100 initial commit diff --git a/__pycache__/base.cpython-37.pyc b/__pycache__/base.cpython-37.pyc new file mode 100644 index 0000000..65f78ba Binary files /dev/null and b/__pycache__/base.cpython-37.pyc differ diff --git a/__pycache__/enumkind.cpython-37.pyc b/__pycache__/enumkind.cpython-37.pyc new file mode 100644 index 0000000..cfd3b40 Binary files /dev/null and b/__pycache__/enumkind.cpython-37.pyc differ diff --git a/__pycache__/guiheader.cpython-37.pyc b/__pycache__/guiheader.cpython-37.pyc new file mode 100644 index 0000000..9c00d2a Binary files /dev/null and b/__pycache__/guiheader.cpython-37.pyc differ diff --git a/__pycache__/guiheader.cpython-38.pyc b/__pycache__/guiheader.cpython-38.pyc new file mode 100644 index 0000000..764eff3 Binary files /dev/null and b/__pycache__/guiheader.cpython-38.pyc differ diff --git a/__pycache__/mainwindow.cpython-37.pyc b/__pycache__/mainwindow.cpython-37.pyc new file mode 100644 index 0000000..1995cdc Binary files /dev/null and b/__pycache__/mainwindow.cpython-37.pyc differ diff --git a/__pycache__/mainwindow.cpython-38.pyc b/__pycache__/mainwindow.cpython-38.pyc new file mode 100644 index 0000000..0fa65c9 Binary files /dev/null and b/__pycache__/mainwindow.cpython-38.pyc differ diff --git a/enumkind.py b/enumkind.py new file mode 100644 index 0000000..f96bb4e --- /dev/null +++ b/enumkind.py @@ -0,0 +1,40 @@ + +from enum import IntEnum + +class ElogSwissFEL: + def __init__(self): + self.category = self.Category(0) + self.domain = self.Domain(0) + self.system = self.System(0) + + class Category(IntEnum): + INFO = 0 + MEASUREMENT = 1 + + class Domain(IntEnum): + NONE = 0 + INJECTOR = 1 + LINAC1 = 2 + LINAC2 = 3 + LINAC3 = 4 + ARAMIS = 5 + ARAMIS_BEAMLINES = 6 + ATHOS = 7 + ATHOS_BEAMLINES = 8 + + class System(IntEnum): + NONE = 0 + BEAMDYNAMICS = 1 + CONTROLS = 2 + DIAGNOSTICS = 3 + ELECTRICSUPPLY = 4 + INSERTIONDEVICES = 5 + LASER = 6 + MAGNETPOWERSUPPLIES = 7 + OPERATION = 8 + RF = 9 + SAFETY = 10 + VACUUM = 11 + WATERCOOLING = 11 + OTHER = 12 + UNKNOWN = 13 diff --git a/enumkind.py~ b/enumkind.py~ new file mode 100644 index 0000000..c75ad80 --- /dev/null +++ b/enumkind.py~ @@ -0,0 +1,39 @@ +from enum import IntEnum + +class ElogSwissFEL: + def __init__(self): + self.category = self.Category(0) + self.domain = self.Domain(0) + self.system = self.System(0) + + class Category(IntEnum): + INFO = 0 + MEASUREMENT = 1 + + class Domain(IntEnum): + NONE = 0 + INJECTOR = 1 + LINAC1 = 2 + LINAC2 = 3 + LINAC3 = 4 + ARAMIS = 5 + ARAMIS_BEAMLINES = 6 + ATHOS = 7 + ATHOS_BEAMLINES = 8 + + class System(IntEnum): + NONE = 0 + BEAMDYNAMICS = 1 + CONTROLS = 2 + DIAGNOSTICS = 3 + ELECTRICSUPPLY = 4 + INSERTIONDEVICES = 5 + LASER = 6 + MAGNETPOWERSUPPLIES = 7 + OPERATION = 8 + RF = 9 + SAFETY = 10 + VACUUM = 11 + WATERCOOLING = 11 + OTHER = 12 + UNKNOWN = 13 diff --git a/guiheader.py b/guiheader.py new file mode 100644 index 0000000..c40a5f9 --- /dev/null +++ b/guiheader.py @@ -0,0 +1,438 @@ +""" Gui header for SwissFEL +""" +from datetime import datetime +import random +import time + +from qtpy.QtCore import Qt, QTimer +from qtpy.QtGui import QFont, QIntValidator +from qtpy.QtWidgets import (QApplication, QFrame, QGridLayout, QGroupBox, + QHBoxLayout, QLabel, QLineEdit, QMessageBox, + QPushButton, QRadioButton, QSizePolicy, QSpacerItem, + QSpinBox, QTabWidget, QToolButton, QVBoxLayout, + QWidget) +from caqtwidgets.pvwidgets import (CAQDoubleSpinBox, CAQLabel, CAQLineEdit, + CAQMenu, CAQMessageButton, CAQSpinBox, + CAQTableWidget, CAQTextEntry, QHLine, QVLine, + QResultsWidget) + +from pyqtacc.bdbase.enumkind import MsgSeverity, UserMode + + + +class GUIHeader(QWidget): + """ GUI Header Class + """ + def __init__(self, parent, user_mode=UserMode.OPERATION, extended=True): + super(GUIHeader, self).__init__() + self.parent = parent + self.appname = parent.appname + self.title = parent.title + self.settings = parent.settings + self.user_mode = user_mode + self.current_user_mode = user_mode + self.extended = extended + self.cafe = parent.cafe + self.cyca = parent.cyca + + self.input_parameters = parent.input_parameters + self.input_labels = parent.input_labels + self.expert_parameters = parent.expert_parameters + self.expert_labels = parent.expert_labels + + self.aramis_status = None + self.athos_status = None + self.porthos_status = None + + self.font_gui = QFont("sans serif") + self.font_gui.setPointSize(11) + self.font_pts10 = QFont("sans serif") + self.font_pts10.setPointSize(10) + self.widget_height = self.settings.data["StyleGuide"]["widgetHeight"] + self.extra_height = self.settings.data["StyleGuide"]["extraGroupHeight"] + self.aramis_color = self.settings.data["Aramis"]["color"] + self.athos_color = self.settings.data["Athos"]["color"] + self.porthos_color = self.settings.data["Porthos"]["color"] + + beamline = ["Aramis", "Athos", "Porthos"] + pvlist = [] + for item in beamline: + if item not in self.settings.data: + continue + try: + pvlist.append(self.settings.data[item]["laser"]) + pvlist.append(self.settings.data[item]["freq"]) + pvlist.append(self.settings.data[item]["beamStatus"]) + pvlist.append(self.settings.data[item]["energy"]) + pvlist.append(self.settings.data[item]["charge"]) + pvlist.append(self.settings.data[item]["photonEnergy"]) + except KeyError as error: + print("KeyError in guiheader.py __init__", error) + + for key, pv in self.settings.data["OpMsg"].items(): + pvlist.append(pv) + + print(datetime.now()) + self.cafe.openPrepare() + self.cafe.open(pvlist) + self.cafe.openNowAndWait(0.4) + print(datetime.now()) + self.cafe.printDisconnected() + + + self.station_width = 200 #default + self.station_height = 100 + self.hor_layout = QHBoxLayout() + self.hor_layout.addWidget(self.status_widget()) + self.hor_layout.addWidget(self.aramis_widget()) + self.hor_layout.addWidget(self.athos_widget()) + yr_diff = abs(2030 - datetime.now().year) + show_porthos = False + try: + if self.settings.data["showPorthos"]: + show_porthos = True + else: + if random.randint(1, 10) > yr_diff: + show_porthos = True + except KeyError as error: + print("KeyError in guiheader.py initialization:", error) + if random.randint(1, 10) > yr_diff: + show_porthos = True + if show_porthos: + self.hor_layout.addWidget(self.porthos_widget()) + self.hor_layout.setSpacing(10) + #self.header_layout.addItem(QSpacerItem(0, 20)) + self.hor_layout.setAlignment(Qt.AlignLeft) + self.hor_layout.setContentsMargins(5, 0, 5, 0) #default 11 pixels + #self.top_widget = QLabel("SwissFEL") + + #self.top_layout = QVBoxLayout() + #self.top_layout.addWidget(self.top_widget) + #self.top_layout.addLayout(self.hor_layout) + + self.header_wgt = QGroupBox() + self.header_wgt.setObjectName(self.user_mode.name) + self.header_wgt.setLayout(self.hor_layout) + self.header_wgt.setFixedHeight(110) + title = "SwissFEL {0}".format(self.user_mode.name) + if self.title: + title += ": {0}".format(self.title) + self.header_wgt.setTitle(title) + + self.target_beamline = None + + #self.set_target_beamline("Athos", reset=False) + #QApplication.processEvents() + + self.timer = QTimer() + self.timer.timeout.connect(self.blink_target_beamline) + self.timer.start(500) + self.timer_count = 0 + + def blink_target_beamline(self): + self.timer_count += 1 + if self.timer_count < 2: + return + if self.timer_count % 2 == 0: + self.reset_beamline() + else: + self.set_target_beamline(target=self.target_beamline, reset=False) + if self.timer_count > 4: + self.timer.stop() + QApplication.processEvents() + + def set_target_beamline(self, target, reset = True): + """ Select beamline target and modify color scheme accordinly + """ + if not target: + return + if target == "Aramis": + self.aramis_status.setObjectName("TARGET") + self.aramis_status.setTitle("Target: Aramis") + self.aramis_status.style().polish(self.aramis_status) + elif target == "Athos": + self.athos_status.setObjectName("TARGET") + self.athos_status.setTitle("Target: Athos") + self.athos_status.style().polish(self.athos_status) + elif target == "Porthos" and self.porthos_status: + if self.porthos_status: + self.porthos_status.setObjectName("TARGET") + self.porthos_status.setTitle("Target: Porthos") + self.porthos_status.style().polish(self.porthos_status) + + if reset: + self.reset_beamline() + self.target_beamline = target + + def reset_beamline(self): + """ Reset QGroupBox for previous target to original colors + """ + if self.target_beamline == "Aramis": + self.reset_aramis() + elif self.target_beamline == "Athos": + self.reset_athos() + elif self.target_beamline == "Porthos": + self.reset_porthos() + + def reset_aramis(self): + """ Reset Aramis QGroupBox color + """ + self.aramis_status.setObjectName("ARAMIS") + self.aramis_status.setTitle("Aramis") + self.aramis_status.style().polish(self.aramis_status) + + def reset_athos(self): + """ Reset Athos QGroupBox color + """ + self.athos_status.setObjectName("ATHOS") + self.athos_status.setTitle("Athos") + self.athos_status.style().polish(self.athos_status) + + def reset_porthos(self): + """ Reset Porthos QGroupBox color + """ + if self.porthos_status: + self.porthos_status.setObjectName("PORTHOS") + self.porthos_status.setTitle("Porthos") + self.porthos_status.style().polish(self.porthos_status) + + def reset_operation_mode(self): + """ Reset header colors to application operation mode + """ + self.change_operation_mode(user_mode=self.user_mode) + + def change_operation_mode(self, user_mode=UserMode.OPERATION): + """ Different operation modes have different color schemes + """ + self.header_wgt.setObjectName(user_mode.name) + self.header_wgt.setTitle(self.header_wgt.title().replace( + self.current_user_mode.name, user_mode.name)) + self.header_wgt.style().polish(self.header_wgt) + self.current_user_mode = user_mode + + #self.header_wgt.setStyleSheet("QGroupBox#OPERATION{background-color:#8b1a96; color:white;}" "QGroupBox::title#OPERATION{background-color:#8b1a96;} ") + + + def beamline_widget(self, beamline="Aramis"): + """ QGroupBox template for beamlines + """ + station = QGroupBox() + station.setObjectName(beamline.upper()) + station.setAlignment(Qt.AlignHCenter | Qt.AlignTop) + station.setFlat(False) + station.setTitle(beamline) + laser = CAQLabel(self, pv_name=self.settings.data[beamline]["laser"]) + laser.setFixedHeight(self.widget_height) + freq = CAQLabel(self, pv_name=self.settings.data[beamline]["freq"], + show_units=True) + freq.setAlignment(Qt.AlignRight) + freq.setFixedHeight(self.widget_height) + freq.setFixedWidth(84) + beamstatus = CAQLabel( + self, pv_name=self.settings.data[beamline]["beamStatus"], + color_mode="alarm") + beamstatus.setFixedHeight(self.widget_height) + + grid_layout = QGridLayout() + grid_layout.addWidget(laser, 0, 0, 1, 1, Qt.AlignCenter) + grid_layout.addWidget(freq, 0, 1, 1, 1, Qt.AlignCenter) + grid_layout.addWidget(beamstatus, 1, 0, 1, 2, Qt.AlignCenter) + + if self.extended: + grid_layout.addWidget(QVLine(), 0, 2, 2, 1) + filtered_energy = CAQLabel( + self, pv_name=self.settings.data[beamline]["energy"], + show_units=True) + filtered_energy.setFixedHeight(self.widget_height) + charge = CAQLabel( + self, pv_name=self.settings.data[beamline]["charge"], + show_units=True, notify_freq_hz=2) + charge.setFixedHeight(self.widget_height) + charge.setFixedWidth(78) + photon_energy = CAQLabel( + self, pv_name=self.settings.data[beamline]["photonEnergy"], + show_units=False, suffix='\u00B5J') + photon_energy.setFixedHeight(self.widget_height) + photon_energy.setFixedWidth(66) #So aramis/Athos are the same + + grid_layout.addWidget(filtered_energy, 0, 3, 1, 2, Qt.AlignCenter) + grid_layout.addWidget(charge, 1, 3, 1, 1, Qt.AlignCenter) + grid_layout.addWidget(photon_energy, 1, 4, 1, 1, Qt.AlignCenter) + + grid_layout.setVerticalSpacing(0) + grid_layout.setHorizontalSpacing(0) + grid_layout.setContentsMargins(0, 10, 0, 0) + #print(grid_layout.getContentsMargins()) + + station.setLayout(grid_layout) + self.station_height = laser.height() + freq.height() + self.extra_height + station.setFixedHeight(self.station_height) + self.station_width = laser.width() + freq.width() + 10 + if self.extended: + self.station_width += (charge.width() + photon_energy.width()) + station.setFixedWidth(self.station_width) + station.setAlignment(Qt.AlignCenter) + return station + + def aramis_widget(self): + """ QGroupBox encompassing main Aramis parameters + """ + self.aramis_status = self.beamline_widget(beamline="Aramis") + return self.aramis_status + + def athos_widget(self): + """ QGroupBox encompassing main Athos parameters + """ + self.athos_status = self.beamline_widget(beamline="Athos") + return self.athos_status + + def porthos_widget(self): + """ QGroupBox encompassing main Porthos parameters + """ + #porthos = self.beamline_widget(beamline="Porthos") + station = QGroupBox() + station.setObjectName("Porthos".upper()) + station.setAlignment(Qt.AlignHCenter | Qt.AlignTop) + station.setFlat(False) + station.setTitle("Porthos") + grid_layout = QGridLayout() + text = "Honest and extrovert!" \ + if random.randint(1,10) > 9 else "Arriving 2029" + qlabel = QLabel(text) + qlabel.setFont(self.font_pts10) + qlabel.setAlignment(Qt.AlignCenter) + grid_layout.addWidget(qlabel, 0, 0) + station.setLayout(grid_layout) + station.setFixedWidth(self.station_width) + station.setFixedHeight(self.station_height) + self.porthos_status = station + return self.porthos_status + + def status_widget(self): + """ QGroupBox encompassing machine status info + """ + station = QGroupBox() + station.setObjectName("MACHINE") + station.setAlignment(Qt.AlignHCenter | Qt.AlignTop) + station.setFlat(False) + station.setTitle("Status") + date = CAQLabel(self, pv_name=self.settings.data["OpMsg"]["pvDate1"]) + date.setFixedHeight(self.widget_height) + eventno = CAQLabel(self, pv_name=self.settings.data["OpMsg"]["pvEventNo"], + notify_freq_hz=10) + eventno.setFixedHeight(self.widget_height) + eventno.setAlignment(Qt.AlignCenter) + message = CAQLabel( + self, pv_name=self.settings.data["OpMsg"]["pvMsg1"]) + message.setFixedHeight(self.widget_height) + message.setFixedWidth(eventno.width() + date.width() + 2) + + grid_layout = QGridLayout() + grid_layout.addWidget(date, 0, 0, 1, 1, Qt.AlignCenter) + grid_layout.addWidget(eventno, 0, 1, 1, 1, Qt.AlignCenter) + grid_layout.addWidget(message, 1, 0, 1, 2, Qt.AlignCenter) + grid_layout.setVerticalSpacing(0) + grid_layout.setHorizontalSpacing(0) + grid_layout.setContentsMargins(0, 10, 0, 0) + + station.setLayout(grid_layout) + station.setFixedHeight(eventno.height() + date.height() + + self.extra_height) + station.setFixedWidth(eventno.width() + date.width() + 10) + self.machine_status = station + return self.machine_status + + def operator_group_header(self): + return self.radio_target_beamline() + + def radio_target_beamline(self): + widget = QWidget() + layout = QGridLayout() + layout.setContentsMargins(0, 0, 0, 0) + self.setLayout(layout) + target_list = ["Aramis", "Athos"] + try: + if self.settings.data["showPorthos"]: + target_list.append("Porthos") + except KeyError as error: + print("KeyError in guiheader.py, def radio_target_beamline:", error) + + + color_list = [self.aramis_color, self.athos_color, self.porthos_color] + + self.radiobutton = [QRadioButton("Aramis"), QRadioButton("Athos"), + QRadioButton("Porthos")] + width_list = [70, 64, 84] + #width_list = [80, 74, 92] #pts 11 + layout.addWidget(QHLine(), 0, 0, 1, 3) + + for i, (radio, target, color, width) in enumerate( + zip(self.radiobutton, target_list, color_list, width_list)): + #radio = QRadioButton(target) + radio.setFont(self.font_pts10) + radio.setStyleSheet("color : {0};".format(color)) + radio.target = target + radio.toggled.connect(self.on_target_clicked) + layout.addWidget(radio, 1, i) + radio.setFixedWidth(width) + + try: + target = self.settings.data["Parameters"]["undulator"]["data"]["value"] + except KeyError as error: + print("KeyError in guiheader.py, def radio_target_beamline:", error) + target = target_list[0] + try: + idx = target_list.index(target) + except ValueError as error: + print("ValueError in guiheader.py, def radio_target_beamline:", error) + idx = 0 + + self.radiobutton[idx].setChecked(True) + self.radiobutton[idx].toggled.emit(True) + + ''' + radiobutton = QRadioButton("Aramis") + radiobutton.setFont(self.font_gui) + radiobutton.setStyleSheet("color : {0};".format(self.aramis_color)) + radiobutton.setChecked(True) + radiobutton.target = "Aramis" + radiobutton.toggled.connect(self.on_target_clicked) + layout.addWidget(radiobutton, 0, 0) + + radiobutton = QRadioButton("Athos") + radiobutton.setFont(self.font_gui) + radiobutton.setStyleSheet("color : {0};".format(self.athos_color)) + radiobutton.target = "Athos" + radiobutton.toggled.connect(self.on_target_clicked) + layout.addWidget(radiobutton, 0, 1) + + radiobutton = QRadioButton("Porthos") + radiobutton.setFont(self.font_gui) + radiobutton.setStyleSheet("color : {0};".format(self.porthos_color)) + radiobutton.target = "Porthos" + radiobutton.toggled.connect(self.on_target_clicked) + layout.addWidget(radiobutton, 0, 2) + ''' + + layout.addWidget(QHLine(), 2, 0, 1, 3) + + widget.setLayout(layout) + + return widget + + def on_target_clicked(self): + radio_button = self.sender() + if radio_button.isChecked(): + print("Target is {0}".format(radio_button.target)) + self.set_target_beamline(radio_button.target) + radio_button.setText(radio_button.target.upper()) + self.timer.start(500) + self.timer_count = 0 + #print (self.parent.input_parameters['undulator']) + self.parent.input_parameters['undulator'] = radio_button.target + print (self.parent.input_parameters['undulator']) + + for radio in self.radiobutton: + if not radio.isChecked(): + radio.setText(radio.target) + diff --git a/guiheader.py~ b/guiheader.py~ new file mode 100644 index 0000000..eaf81e4 --- /dev/null +++ b/guiheader.py~ @@ -0,0 +1,438 @@ +""" Gui header for SwissFEL +""" +from datetime import datetime +import random +import time + +from qtpy.QtCore import Qt, QTimer +from qtpy.QtGui import QFont, QIntValidator +from qtpy.QtWidgets import (QApplication, QFrame, QGridLayout, QGroupBox, + QHBoxLayout, QLabel, QLineEdit, QMessageBox, + QPushButton, QRadioButton, QSizePolicy, QSpacerItem, + QSpinBox, QTabWidget, QToolButton, QVBoxLayout, + QWidget) +from caqtwidgets.pvwidgets import (CAQDoubleSpinBox, CAQLabel, CAQLineEdit, + CAQMenu, CAQMessageButton, CAQSpinBox, + CAQTableWidget, CAQTextEntry, QHLine, QVLine, + QResultsWidget) + +from pyqtacc.bdbase.enumkind import MsgSeverity, UserMode + + + +class GUIHeader(QWidget): + """ GUI Header Class + """ + def __init__(self, parent, user_mode=UserMode.OPERATION, extended=True): + super(GUIHeader, self).__init__() + self.parent = parent + self.appname = parent.appname + self.title = parent.title + self.settings = parent.settings + self.user_mode = user_mode + self.current_user_mode = user_mode + self.extended = extended + self.cafe = parent.cafe + self.cyca = parent.cyca + + self.input_parameters = parent.input_parameters + self.input_labels = parent.input_labels + self.expert_parameters = parent.expert_parameters + self.expert_labels = parent.expert_labels + + self.aramis_status = None + self.athos_status = None + self.porthos_status = None + + self.font_gui = QFont("sans serif") + self.font_gui.setPointSize(11) + self.font_pts10 = QFont("sans serif") + self.font_pts10.setPointSize(10) + self.widget_height = self.settings.data["StyleGuide"]["widgetHeight"] + self.extra_height = self.settings.data["StyleGuide"]["extraGroupHeight"] + self.aramis_color = self.settings.data["Aramis"]["color"] + self.athos_color = self.settings.data["Athos"]["color"] + self.porthos_color = self.settings.data["Porthos"]["color"] + + beamline = ["Aramis", "Athos", "Porthos"] + pvlist = [] + for item in beamline: + if item not in self.settings.data: + continue + try: + pvlist.append(self.settings.data[item]["laser"]) + pvlist.append(self.settings.data[item]["freq"]) + pvlist.append(self.settings.data[item]["beamStatus"]) + pvlist.append(self.settings.data[item]["energy"]) + pvlist.append(self.settings.data[item]["charge"]) + pvlist.append(self.settings.data[item]["photonEnergy"]) + except KeyError as error: + print("KeyError in guiheader.py __init__", error) + + for key, pv in self.settings.data["OpMsg"].items(): + pvlist.append(pv) + + print(datetime.now()) + self.cafe.openPrepare() + self.cafe.open(pvlist) + self.cafe.openNowAndWait(0.4) + print(datetime.now()) + self.cafe.printDisconnected() + + + self.station_width = 200 #default + self.station_height = 100 + self.hor_layout = QHBoxLayout() + self.hor_layout.addWidget(self.status_widget()) + self.hor_layout.addWidget(self.aramis_widget()) + self.hor_layout.addWidget(self.athos_widget()) + yr_diff = abs(2030 - datetime.now().year) + show_porthos = False + try: + if self.settings.data["showPorthos"]: + show_porthos = True + else: + if random.randint(1, 10) > yr_diff: + show_porthos = True + except KeyError as error: + print("KeyError in guiheader.py initialization:", error) + if random.randint(1, 10) > yr_diff: + show_porthos = True + if show_porthos: + self.hor_layout.addWidget(self.porthos_widget()) + self.hor_layout.setSpacing(10) + #self.header_layout.addItem(QSpacerItem(0, 20)) + self.hor_layout.setAlignment(Qt.AlignLeft) + self.hor_layout.setContentsMargins(5, 0, 5, 0) #default 11 pixels + #self.top_widget = QLabel("SwissFEL") + + #self.top_layout = QVBoxLayout() + #self.top_layout.addWidget(self.top_widget) + #self.top_layout.addLayout(self.hor_layout) + + self.header_wgt = QGroupBox() + self.header_wgt.setObjectName(self.user_mode.name) + self.header_wgt.setLayout(self.hor_layout) + self.header_wgt.setFixedHeight(110) + title = "SwissFEL {0}".format(self.user_mode.name) + if self.title: + title += ": {0}".format(self.title) + self.header_wgt.setTitle(title) + + self.target_beamline = None + + #self.set_target_beamline("Athos", reset=False) + #QApplication.processEvents() + + self.timer = QTimer() + self.timer.timeout.connect(self.blink_target_beamline) + self.timer.start(500) + self.timer_count = 0 + + def blink_target_beamline(self): + self.timer_count += 1 + if self.timer_count < 2: + return + if self.timer_count % 2 == 0: + self.reset_beamline() + else: + self.set_target_beamline(target=self.target_beamline, reset=False) + if self.timer_count > 4: + self.timer.stop() + QApplication.processEvents() + + def set_target_beamline(self, target, reset = True): + """ Select beamline target and modify color scheme accordinly + """ + if not target: + return + if target == "Aramis": + self.aramis_status.setObjectName("TARGET") + self.aramis_status.setTitle("Target: Aramis") + self.aramis_status.style().polish(self.aramis_status) + elif target == "Athos": + self.athos_status.setObjectName("TARGET") + self.athos_status.setTitle("Target: Athos") + self.athos_status.style().polish(self.athos_status) + elif target == "Porthos" and self.porthos_status: + if self.porthos_status: + self.porthos_status.setObjectName("TARGET") + self.porthos_status.setTitle("Target: Porthos") + self.porthos_status.style().polish(self.porthos_status) + + if reset: + self.reset_beamline() + self.target_beamline = target + + def reset_beamline(self): + """ Reset QGroupBox for previous target to original colors + """ + if self.target_beamline == "Aramis": + self.reset_aramis() + elif self.target_beamline == "Athos": + self.reset_athos() + elif self.target_beamline == "Porthos": + self.reset_porthos() + + def reset_aramis(self): + """ Reset Aramis QGroupBox color + """ + self.aramis_status.setObjectName("ARAMIS") + self.aramis_status.setTitle("Aramis") + self.aramis_status.style().polish(self.aramis_status) + + def reset_athos(self): + """ Reset Athos QGroupBox color + """ + self.athos_status.setObjectName("ATHOS") + self.athos_status.setTitle("Athos") + self.athos_status.style().polish(self.athos_status) + + def reset_porthos(self): + """ Reset Porthos QGroupBox color + """ + if self.porthos_status: + self.porthos_status.setObjectName("PORTHOS") + self.porthos_status.setTitle("Porthos") + self.porthos_status.style().polish(self.porthos_status) + + def reset_operation_mode(self): + """ Reset header colors to application operation mode + """ + self.change_operation_mode(user_mode=self.user_mode) + + def change_operation_mode(self, user_mode=UserMode.OPERATION): + """ Different operation modes have different color schemes + """ + self.header_wgt.setObjectName(user_mode.name) + self.header_wgt.setTitle(self.header_wgt.title().replace( + self.current_user_mode.name, user_mode.name)) + self.header_wgt.style().polish(self.header_wgt) + self.current_user_mode = user_mode + + #self.header_wgt.setStyleSheet("QGroupBox#OPERATION{background-color:#8b1a96; color:white;}" "QGroupBox::title#OPERATION{background-color:#8b1a96;} ") + + + def beamline_widget(self, beamline="Aramis"): + """ QGroupBox template for beamlines + """ + station = QGroupBox() + station.setObjectName(beamline.upper()) + station.setAlignment(Qt.AlignHCenter | Qt.AlignTop) + station.setFlat(False) + station.setTitle(beamline) + laser = CAQLabel(self, pv_name=self.settings.data[beamline]["laser"]) + laser.setFixedHeight(self.widget_height) + freq = CAQLabel(self, pv_name=self.settings.data[beamline]["freq"], + show_units=True) + freq.setAlignment(Qt.AlignRight) + freq.setFixedHeight(self.widget_height) + freq.setFixedWidth(84) + beamstatus = CAQLabel( + self, pv_name=self.settings.data[beamline]["beamStatus"], + color_mode="alarm") + beamstatus.setFixedHeight(self.widget_height) + + grid_layout = QGridLayout() + grid_layout.addWidget(laser, 0, 0, 1, 1, Qt.AlignCenter) + grid_layout.addWidget(freq, 0, 1, 1, 1, Qt.AlignCenter) + grid_layout.addWidget(beamstatus, 1, 0, 1, 2, Qt.AlignCenter) + + if self.extended: + grid_layout.addWidget(QVLine(), 0, 2, 2, 1) + filtered_energy = CAQLabel( + self, pv_name=self.settings.data[beamline]["energy"], + show_units=True) + filtered_energy.setFixedHeight(self.widget_height) + charge = CAQLabel( + self, pv_name=self.settings.data[beamline]["charge"], + show_units=True, notify_freq_hz=2) + charge.setFixedHeight(self.widget_height) + charge.setFixedWidth(78) + photon_energy = CAQLabel( + self, pv_name=self.settings.data[beamline]["photonEnergy"], + show_units=False, suffix='\u00B5J') + photon_energy.setFixedHeight(self.widget_height) + photon_energy.setFixedWidth(66) #So aramis/Athos are the same + + grid_layout.addWidget(filtered_energy, 0, 3, 1, 2, Qt.AlignCenter) + grid_layout.addWidget(charge, 1, 3, 1, 1, Qt.AlignCenter) + grid_layout.addWidget(photon_energy, 1, 4, 1, 1, Qt.AlignCenter) + + grid_layout.setVerticalSpacing(0) + grid_layout.setHorizontalSpacing(0) + grid_layout.setContentsMargins(0, 10, 0, 0) + #print(grid_layout.getContentsMargins()) + + station.setLayout(grid_layout) + self.station_height = laser.height() + freq.height() + self.extra_height + station.setFixedHeight(self.station_height) + self.station_width = laser.width() + freq.width() + 10 + if self.extended: + self.station_width += (charge.width() + photon_energy.width()) + station.setFixedWidth(self.station_width) + station.setAlignment(Qt.AlignCenter) + return station + + def aramis_widget(self): + """ QGroupBox encompassing main Aramis parameters + """ + self.aramis_status = self.beamline_widget(beamline="Aramis") + return self.aramis_status + + def athos_widget(self): + """ QGroupBox encompassing main Athos parameters + """ + self.athos_status = self.beamline_widget(beamline="Athos") + return self.athos_status + + def porthos_widget(self): + """ QGroupBox encompassing main Porthos parameters + """ + #porthos = self.beamline_widget(beamline="Porthos") + station = QGroupBox() + station.setObjectName("Porthos".upper()) + station.setAlignment(Qt.AlignHCenter | Qt.AlignTop) + station.setFlat(False) + station.setTitle("Porthos") + grid_layout = QGridLayout() + text = "Honest and extrovert!" \ + if random.randint(1,10) > 9 else "Arriving 2029" + qlabel = QLabel(text) + qlabel.setFont(self.font_pts10) + qlabel.setAlignment(Qt.AlignCenter) + grid_layout.addWidget(qlabel, 0, 0) + station.setLayout(grid_layout) + station.setFixedWidth(self.station_width) + station.setFixedHeight(self.station_height) + self.porthos_status = station + return self.porthos_status + + def status_widget(self): + """ QGroupBox encompassing machine status info + """ + station = QGroupBox() + station.setObjectName("MACHINE") + station.setAlignment(Qt.AlignHCenter | Qt.AlignTop) + station.setFlat(False) + station.setTitle("Status") + date = CAQLabel(self, pv_name=self.settings.data["OpMsg"]["pvDate1"]) + date.setFixedHeight(self.widget_height) + eventno = CAQLabel(self, pv_name=self.settings.data["OpMsg"]["pvEventNo"], + notify_freq_hz=10) + eventno.setFixedHeight(self.widget_height) + eventno.setAlignment(Qt.AlignCenter) + message = CAQLabel( + self, pv_name=self.settings.data["OpMsg"]["pvMsg1"]) + message.setFixedHeight(self.widget_height) + message.setFixedWidth(eventno.width() + date.width() + 2) + + grid_layout = QGridLayout() + grid_layout.addWidget(date, 0, 0, 1, 1, Qt.AlignCenter) + grid_layout.addWidget(eventno, 0, 1, 1, 1, Qt.AlignCenter) + grid_layout.addWidget(message, 1, 0, 1, 2, Qt.AlignCenter) + grid_layout.setVerticalSpacing(0) + grid_layout.setHorizontalSpacing(0) + grid_layout.setContentsMargins(0, 10, 0, 0) + + station.setLayout(grid_layout) + station.setFixedHeight(eventno.height() + date.height() + + self.extra_height) + station.setFixedWidth(eventno.width() + date.width() + 10) + self.machine_status = station + return self.machine_status + + def operator_group_header(self): + return self.radio_target_beamline() + + def radio_target_beamline(self): + widget = QWidget() + layout = QGridLayout() + layout.setContentsMargins(0, 0, 0, 0) + self.setLayout(layout) + target_list = ["Aramis", "Athos"] + try: + if self.settings.data["showPorthos"]: + target_list.append("Porthos") + except KeyError as error: + print("KeyError in guiheader.py, def radio_target_beamline:", error) + + + color_list = [self.aramis_color, self.athos_color, self.porthos_color] + + self.radiobutton = [QRadioButton("Aramis"), QRadioButton("Athos"), + QRadioButton("Porthos")] + width_list = [80, 74, 92] + + layout.addWidget(QHLine(), 0, 0, 1, 3) + + for i, (radio, target, color, width) in enumerate( + zip(self.radiobutton, target_list, color_list, width_list)): + #radio = QRadioButton(target) + radio.setFont(self.font_gui) + radio.setStyleSheet("color : {0};".format(color)) + radio.target = target + radio.toggled.connect(self.on_target_clicked) + layout.addWidget(radio, 1, i) + radio.setFixedWidth(width) + + try: + target = self.settings.data["Parameters"]["undulator"]["data"]["value"] + except KeyError as error: + print("KeyError in guiheader.py, def radio_target_beamline:", error) + target = target_list[0] + try: + idx = target_list.index(target) + except ValueError as error: + print("ValueError in guiheader.py, def radio_target_beamline:", error) + idx = 0 + + self.radiobutton[idx].setChecked(True) + self.radiobutton[idx].toggled.emit(True) + + ''' + radiobutton = QRadioButton("Aramis") + radiobutton.setFont(self.font_gui) + radiobutton.setStyleSheet("color : {0};".format(self.aramis_color)) + radiobutton.setChecked(True) + radiobutton.target = "Aramis" + radiobutton.toggled.connect(self.on_target_clicked) + layout.addWidget(radiobutton, 0, 0) + + radiobutton = QRadioButton("Athos") + radiobutton.setFont(self.font_gui) + radiobutton.setStyleSheet("color : {0};".format(self.athos_color)) + radiobutton.target = "Athos" + radiobutton.toggled.connect(self.on_target_clicked) + layout.addWidget(radiobutton, 0, 1) + + radiobutton = QRadioButton("Porthos") + radiobutton.setFont(self.font_gui) + radiobutton.setStyleSheet("color : {0};".format(self.porthos_color)) + radiobutton.target = "Porthos" + radiobutton.toggled.connect(self.on_target_clicked) + layout.addWidget(radiobutton, 0, 2) + ''' + + layout.addWidget(QHLine(), 2, 0, 1, 3) + + widget.setLayout(layout) + + return widget + + def on_target_clicked(self): + radio_button = self.sender() + if radio_button.isChecked(): + print("Target is {0}".format(radio_button.target)) + self.set_target_beamline(radio_button.target) + radio_button.setText(radio_button.target.upper()) + self.timer.start(500) + self.timer_count = 0 + #print (self.parent.input_parameters['undulator']) + self.parent.input_parameters['undulator'] = radio_button.target + print (self.parent.input_parameters['undulator']) + + for radio in self.radiobutton: + if not radio.isChecked(): + radio.setText(radio.target) + diff --git a/mainwindow.py b/mainwindow.py new file mode 100644 index 0000000..a40c7a6 --- /dev/null +++ b/mainwindow.py @@ -0,0 +1,62 @@ +import inspect +import os + +# Third-party modules +from qtpy.QtCore import (PYQT_VERSION_STR, Signal, Slot, QFile, QFileInfo, + QIODevice, QMutex, QSettings, QSize, Qt, QTimer, + qVersion) +from qtpy.QtCore import __version__ as QT_VERSION_STR +from qtpy.QtGui import (QColor, QKeySequence, QFont, QIcon, QPainter, QPalette, + QPixmap) +from qtpy.QtPrintSupport import QPrinter, QPrintDialog +from qtpy.QtWidgets import (QAbstractItemView, QAction, QActionGroup, + QApplication, QButtonGroup, QComboBox, QDialog, + QDockWidget, QDoubleSpinBox, QFileDialog, QFrame, + QGridLayout, QGroupBox, QHBoxLayout, QLabel, + QLayout, QLineEdit, QListWidget, QMainWindow, QMenu, + QMenuBar, QMessageBox, QPlainTextEdit, QProgressBar, + QPushButton, QScrollArea, QSizePolicy, QSlider, + QSpinBox, QSplashScreen, QStyle, QStyleOptionSlider, + QToolButton, QVBoxLayout, QWidget) + +from pyqtacc.bdbase.base import BaseWindow +from pyqtacc.bdbase.enumkind import MsgSeverity, UserMode +from pyqtacc.bdbase.guiframe import GUIFrame +from pyqtacc.sf.guiheader import GUIHeader + +_pymodule = os.path.basename(__file__) +_appversion = "1.0.0" + +def _line(): + """Macro to return the current line number. + + The current line number within the file is used when + reporting messages to the message logging window. + + Returns: + int: Current line number. + """ + return inspect.currentframe().f_back.f_lineno + +class MainWindow(BaseWindow): + + def __init__(self, parent=None, pymodule=_pymodule, appversion="", + title="", user_mode=UserMode.OPERATION): + super(MainWindow, self).__init__(parent, pymodule, appversion, title) + self.appname, appext = pymodule.split(".") + self.title = title + self.gui_frame = GUIFrame(self, self.appname) + self.show_log_message = self.gui_frame.show_log_message + self.gui_header = GUIHeader(self, user_mode) + self.mainwindow = QWidget() + self.mainwindow_layout = QVBoxLayout() + #self.mainwindow_layout.addLayout(self.gui_header.top_layout) + self.mainwindow_layout.addWidget(self.gui_header.header_wgt) + self.mainwindow_layout.addWidget(self.gui_frame.central_tab_widget) + self.mainwindow.setLayout(self.mainwindow_layout) + self.mainwindow.setMinimumHeight(400) + self.mainwindow.setMinimumWidth(1100) + + self.setCentralWidget(self.mainwindow) + self.show_log_message(MsgSeverity.INFO, _pymodule, _line(), + "Application started") diff --git a/mainwindow.py~ b/mainwindow.py~ new file mode 100644 index 0000000..711bf2f --- /dev/null +++ b/mainwindow.py~ @@ -0,0 +1,62 @@ +import inspect +import os + +# Third-party modules +from qtpy.QtCore import (PYQT_VERSION_STR, Signal, Slot, QFile, QFileInfo, + QIODevice, QMutex, QSettings, QSize, Qt, QTimer, + qVersion) +from qtpy.QtCore import __version__ as QT_VERSION_STR +from qtpy.QtGui import (QColor, QKeySequence, QFont, QIcon, QPainter, QPalette, + QPixmap) +from qtpy.QtPrintSupport import QPrinter, QPrintDialog +from qtpy.QtWidgets import (QAbstractItemView, QAction, QActionGroup, + QApplication, QButtonGroup, QComboBox, QDialog, + QDockWidget, QDoubleSpinBox, QFileDialog, QFrame, + QGridLayout, QGroupBox, QHBoxLayout, QLabel, + QLayout, QLineEdit, QListWidget, QMainWindow, QMenu, + QMenuBar, QMessageBox, QPlainTextEdit, QProgressBar, + QPushButton, QScrollArea, QSizePolicy, QSlider, + QSpinBox, QSplashScreen, QStyle, QStyleOptionSlider, + QToolButton, QVBoxLayout, QWidget) + +from pyqtacc.bdbase.base import BaseWindow +from pyqtacc.bdbase.enumkind import MsgSeverity +from pyqtacc.bdbase.guiframe import GUIFrame +from pyqtacc.sf.guiheader import GUIHeader + +_pymodule = os.path.basename(__file__) +_appversion = "1.0.0" + +def _line(): + """Macro to return the current line number. + + The current line number within the file is used when + reporting messages to the message logging window. + + Returns: + int: Current line number. + """ + return inspect.currentframe().f_back.f_lineno + +class MainWindow(BaseWindow): + + def __init__(self, parent=None, pymodule=_pymodule, appversion="", title=""): + super(MainWindow, self).__init__(parent, pymodule, appversion, title) + + self.appname, appext = pymodule.split(".") + self.title = title + self.gui_frame = GUIFrame(self, self.appname) + self.show_log_message = self.gui_frame.show_log_message + self.gui_header = GUIHeader(self) + self.mainwindow = QWidget() + self.mainwindow_layout = QVBoxLayout() + #self.mainwindow_layout.addLayout(self.gui_header.top_layout) + self.mainwindow_layout.addWidget(self.gui_header.header_wgt) + self.mainwindow_layout.addWidget(self.gui_frame.central_tab_widget) + self.mainwindow.setLayout(self.mainwindow_layout) + self.mainwindow.setMinimumHeight(400) + self.mainwindow.setMinimumWidth(1100) + + self.setCentralWidget(self.mainwindow) + self.show_log_message(MsgSeverity.INFO, _pymodule, _line(), + "Application started") diff --git a/sf.json b/sf.json new file mode 100644 index 0000000..ba93ee7 --- /dev/null +++ b/sf.json @@ -0,0 +1,153 @@ +{ + "menuFlags":{ + "hasFile": 1, + "loadInitFile": 1, + "hasDaq": 1, + "hasH5" : 1, + "hasEpics" : 1 + }, + "Expt": { + "encoding": "UTF-8", + "beamline": "", + "exptColorBg": "blue", + "exptColorFg": "white", + "operator": "sfop" + }, + "ElogBooks": { + "SwissFEL+commissioning": { + "url": "https://elog-gfa.psi.ch:443/SwissFEL+commissioning", + "destination": "/afs/psi.ch/intranet/Controls/tmp/elog/ePic/SwissFEL+commissioning/" + }, + "SwissFEL+commissioning+data": { + "url": "https://elog-gfa.psi.ch:443/SwissFEL+commissioning+data", + "destination": "/afs/psi.ch/intranet/Controls/tmp/elog/ePic/SwissFEL+commissioning+data/" + }, + "SwissFEL+test": { + "url": "https://elog-gfa.psi.ch:443/SwissFEL+test", + "destination": "/afs/psi.ch/intranet/Controls/tmp/elog/ePic/SwissFEL+test/" + }, + "SwissFEL+test+data": { + "url": "https://elog-gfa.psi.ch:443/SwissFEL+test+data", + "destination": "/afs/psi.ch/intranet/Controls/tmp/elog/ePic/SwissFEL+test+data/" + } + }, + "Elog": { + "useELOGenv" : 0, + "host": "elog-gfa.psi.ch", + "book": "SwissFEL+commissioning+data", + "url": "https://elog-gfa.psi.ch:443/SwissFEL+commissioning+data", + "destination": "/afs/psi.ch/intranet/Controls/tmp/elog/ePic/SwissFEL+commissioning+data/", + "category": ["Info","Measurement"], + "system" : ["","Beamdynamics","Controls", "Diagnostics", "Electric supply", "Insertion-devices", "Laser", + "Magnet Power Supplies", "Operation", "RF", "Safety", "Vacuum", "Water cooling", "Other", "Unknown"], + "domain" : ["","Injector","Linac1","Linac2","Linac3","Aramis","Aramis Beamlines","Athos","Athos Beamlines"], + "section" : [ [""], + ["","SINEG01", "SINBD01", "SINSB01", "SINSB02", "SINLH01", "SINLH02", "SINLH03", "SINSB03", "SINSB04", "SINSB05", "SINXB01", "SINBC01", "SINBC02", "SINDI01", "SINDI02"], + ["","S10CB01", "S10CB02", "S10DI01", "S10BD01", "S10CB03", "S10CB04", "S10CB05", "S10CB06", "S10CB08", "S10CB09", "S10BC01", "S10BC02", "S10MA01"], + ["","S20CB01", "S20CB02", "S20CB03", "S20CB04", "S20SY01", "S20SY02", "S20SY03"], + ["","S30CB01", "S30CB02", "S20CB03", "S30CB04", "S30CB05", "S30CB06", "S30CB07", "S30CB08", "S30CB09", "S30CB10", "S30CB11", "S30CB12", "S30CB13", "S30CB14", "S30CB15", "S30CB16"], + ["","SARCL01", "SARCL02", "SARMA01", "SARMA02", "SARUN01", "SARUN02", "SARUN03", "SARUN04", "SARUN05", "SARUN06", "SARUN07", "SARUN08", "SARUN09", "SARUN10", "SARUN11", "SARUN12", + "SARUN13", "SARUN14", "SARUN15", "SARUN16", "SARUN17", "SARUN18", "SARUN19", "SARUN20", "SARBD01", "SARBD02"], + ["","SARFE10 (Gas detector)", "SAROP11 (ESA / ALVRA)", "SAROP21 (ESB / Bernina)", "SAROP31 (ESC)"], + ["","SATSY01", "SATSY02", "SATSY03", "SATCL01", "SATDI01", "SATCB01", "SATCB02", "SATMA01", "SATUN01", "SATUN02", "SATUN03", "SATUN04", "SATUN05", "SATUN06", "SATUN07", "SATUN08", + "SATUN09", "SATUN10", "SATDI04", "SATUN11", "SATUN12", "SATUN13", "SATUN14", "SATUN15", "SATUN16", "SATUN17", "SATUN18", "SATUN19", "SATUN20", "SATUN21", "SATUN22", "SATBD01", "SATBD02"], + ["","SATFE10", "SATOP1"] + ] + }, + "stdlog": { + "destination": "/afs/psi.ch/intranet/Controls/tmp/bdbase/stdlog/" + }, + "screenshot": { + "destination": "/afs/psi.ch/intranet/Controls/tmp/bdbase/screenshot/" + }, + "url": { + "archiver" : "https://ui-data-api.psi.ch/prepare?channel=sf-archiverappliance/", + "databuffer": "https://ui-data-api.psi.ch/prepare?channel=sf-databuffer/" + }, + "OpMsg":{ + "pvDate1" :"SF-OP:CR-MSG:OP-DATE1", + "pvMsg1" :"SF-OP:CR-MSG:OP-MSG1", + "pvBeamOK":"SFTEST-CVME-TI3-EVR0:BUNCH-1-OK" + }, + "BS":{ + "pvFreqSel":"SWISSFEL-STATUS:Bunch-1-Freq-Sel", + "pvFreqRB" :"SWISSFEL-STATUS:Bunch-1-Appl-Freq-RB", + "modulo": 10, + "offset": 0, + "timeoutMS":1000 + }, + "Aramis":{ + "laser":"SWISSFEL-STATUS:Bunch-1-Las-Appl-RB", + "pvFreqRB":"SIN-TIMAST-TMA:Bunch-1-Appl-Freq-RB", + "beamStatus":"SOP-BEAMSTATUS-AR", + "energy" : "SARBD02-DBPM040:ENERGY-OP", + "charge": "SINEG01-DICT215:B1_CHARGE-OP", + "photonEnergy": "SARFE10-PBPG050:PHOTON-ENERGY-PER-PULSE-AVG" + }, + "Athos":{ + "laser":"SWISSFEL-STATUS:Bunch-2-Las-Appl-RB", + "pvFreqRB":"SIN-TIMAST-TMA:Bunch-2-Appl-Freq-RB", + "beamStatus":"SOP-BEAMSTATUS-AT", + "energy" : "SATBD02-DBPM040:ENERGY-OP", + "charge": "SINEG01-DICT215:B2_CHARGE-OP", + "photonEnergy": "SATFE10-PEPG046:PHOTON-ENERGY-PER-PULSE-AVG" + }, + "Update":{ + "freq": [0.5, 1, 2, 5, 10], + "defaultIdx": 1 + }, + "DAQ":{ + "caWaitSec": 0.09 + }, + "MsgSeverity": { + "fatal": "#ee0011", + "error": "#990033", + "warn": "#cc6600", + "info": "#0040ff", + "debug": "#11aaee" + }, + "StyleGuide":{ + "fgAlarmInvalid": "#ffffff", + "fgAlarmMajor": "#ff0000", + "fgAlarmMinor": "#fbfb04", + "fgAlarmNoAlarm": "#00cd00", + "fgNormalText": "#000000", + "fgCurveHor": "#2a63e4", + "fgCurveVer": "#8b1a96", + "fgCurveLong": "#cd6100", + "bgTitleOperation": "#dadada", + "bgTitleExpert": "#646464", + "bgTitleSimulation":"#8b1a96", + "bgMain": "#ececec", + "bgReadbackAlarm": "#c8c8c8", + "bgReadback" : "#ffffe0", + "bgPVSetBeam": "#d4db9d", + "bgPVSet": "#a0a0a0", + "bgButtonWindow": "#b79d5c", + "bgGroupContainers":"#e1e1e1", + "bgErrorLogFile" : "#f0f0f8", + "aramis_color": "#00b7eb", + "athos_color": "#2e5894", + "aramis_qlingrad": "qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #00b7eb , stop: 1 #ffffff)", + "athos_qlingrad": "qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #2e5894 , stop: 1 #ffffff)" + }, + "h5": { + "groups":["General/Created","General/Author","General/Process","General/UID","General/Filepath", + "Machine/Charge", "Machine/Laser","Machine/RepetitionRate","Machine/BeamDestination","Machine/Energy", + "Method/Method","Method/Sensors","Method/Actuators","Method/TimeRecordLength","Method/Background", + "Data"] + }, + "h5Machine": { + "charge": "SINEG01-DICT215:B1_CHARGE_AVERAGE-OP", + "laser": "SLG-LGEN:WHICH_LASER", + "repRate": "SIN-TIMAST-TMA:Beam-Appl-Freq-RB", + "beamDest": "SF:MODE_AR", + "energy": "SF:ENERGY_AR" + }, + "h5Data": { + "dataSet": ["timestamp2","data2", "pulse_id2", "timestamp_offset2"] + }, + "test":{ + "test": 2 + } +} diff --git a/sf.json~ b/sf.json~ new file mode 100644 index 0000000..1b0523d --- /dev/null +++ b/sf.json~ @@ -0,0 +1,150 @@ +{ + "menuFlags":{ + "hasFile": 1, + "loadInitFile": 1, + "hasDaq": 1, + "hasH5" : 1, + "hasEpics" : 1 + }, + "Expt": { + "encoding": "UTF-8", + "beamline": "", + "exptColorBg": "blue", + "exptColorFg": "white", + "operator": "sfop" + }, + "ElogBooks": { + "SwissFEL+commissioning": { + "url": "https://elog-gfa.psi.ch:443/SwissFEL+commissioning", + "destination": "/afs/psi.ch/intranet/Controls/tmp/elog/ePic/SwissFEL+commissioning/" + }, + "SwissFEL+commissioning+data": { + "url": "https://elog-gfa.psi.ch:443/SwissFEL+commissioning+data", + "destination": "/afs/psi.ch/intranet/Controls/tmp/elog/ePic/SwissFEL+commissioning+data/" + }, + "SwissFEL+test": { + "url": "https://elog-gfa.psi.ch:443/SwissFEL+test", + "destination": "/afs/psi.ch/intranet/Controls/tmp/elog/ePic/SwissFEL+test/" + }, + "SwissFEL+test+data": { + "url": "https://elog-gfa.psi.ch:443/SwissFEL+test+data", + "destination": "/afs/psi.ch/intranet/Controls/tmp/elog/ePic/SwissFEL+test+data/" + } + }, + "Elog": { + "useELOGenv" : 0, + "host": "elog-gfa.psi.ch", + "book": "SwissFEL+commissioning+data", + "url": "https://elog-gfa.psi.ch:443/SwissFEL+commissioning+data", + "destination": "/afs/psi.ch/intranet/Controls/tmp/elog/ePic/SwissFEL+commissioning+data/", + "category": ["Info","Measurement"], + "system" : ["","Beamdynamics","Controls", "Diagnostics", "Electric supply", "Insertion-devices", "Laser", + "Magnet Power Supplies", "Operation", "RF", "Safety", "Vacuum", "Water cooling", "Other", "Unknown"], + "domain" : ["","Injector","Linac1","Linac2","Linac3","Aramis","Aramis Beamlines","Athos","Athos Beamlines"], + "section" : [ [""], + ["","SINEG01", "SINBD01", "SINSB01", "SINSB02", "SINLH01", "SINLH02", "SINLH03", "SINSB03", "SINSB04", "SINSB05", "SINXB01", "SINBC01", "SINBC02", "SINDI01", "SINDI02"], + ["","S10CB01", "S10CB02", "S10DI01", "S10BD01", "S10CB03", "S10CB04", "S10CB05", "S10CB06", "S10CB08", "S10CB09", "S10BC01", "S10BC02", "S10MA01"], + ["","S20CB01", "S20CB02", "S20CB03", "S20CB04", "S20SY01", "S20SY02", "S20SY03"], + ["","S30CB01", "S30CB02", "S20CB03", "S30CB04", "S30CB05", "S30CB06", "S30CB07", "S30CB08", "S30CB09", "S30CB10", "S30CB11", "S30CB12", "S30CB13", "S30CB14", "S30CB15", "S30CB16"], + ["","SARCL01", "SARCL02", "SARMA01", "SARMA02", "SARUN01", "SARUN02", "SARUN03", "SARUN04", "SARUN05", "SARUN06", "SARUN07", "SARUN08", "SARUN09", "SARUN10", "SARUN11", "SARUN12", + "SARUN13", "SARUN14", "SARUN15", "SARUN16", "SARUN17", "SARUN18", "SARUN19", "SARUN20", "SARBD01", "SARBD02"], + ["","SARFE10 (Gas detector)", "SAROP11 (ESA / ALVRA)", "SAROP21 (ESB / Bernina)", "SAROP31 (ESC)"], + ["","SATSY01", "SATSY02", "SATSY03", "SATCL01", "SATDI01", "SATCB01", "SATCB02", "SATMA01", "SATUN01", "SATUN02", "SATUN03", "SATUN04", "SATUN05", "SATUN06", "SATUN07", "SATUN08", + "SATUN09", "SATUN10", "SATDI04", "SATUN11", "SATUN12", "SATUN13", "SATUN14", "SATUN15", "SATUN16", "SATUN17", "SATUN18", "SATUN19", "SATUN20", "SATUN21", "SATUN22", "SATBD01", "SATBD02"], + ["","SATFE10", "SATOP1"] + ] + }, + "stdlog": { + "destination": "/afs/psi.ch/intranet/Controls/tmp/bdbase/stdlog/" + }, + "screenshot": { + "destination": "/afs/psi.ch/intranet/Controls/tmp/bdbase/screenshot/" + }, + "url": { + "archiver" : "https://ui-data-api.psi.ch/prepare?channel=sf-archiverappliance/", + "databuffer": "https://ui-data-api.psi.ch/prepare?channel=sf-databuffer/" + }, + "OpMsg":{ + "pvDate1" :"SF-OP:CR-MSG:OP-DATE1", + "pvMsg1" :"SF-OP:CR-MSG:OP-MSG1", + "pvBeamOK":"SFTEST-CVME-TI3-EVR0:BUNCH-1-OK" + }, + "BS":{ + "pvFreqSel":"SWISSFEL-STATUS:Bunch-1-Freq-Sel", + "pvFreqRB" :"SWISSFEL-STATUS:Bunch-1-Appl-Freq-RB", + "modulo": 10, + "offset": 0, + "timeoutMS":1000 + }, + "Aramis":{ + "laser":"SWISSFEL-STATUS:Bunch-1-Las-Appl-RB", + "pvFreqRB":"SIN-TIMAST-TMA:Bunch-1-Appl-Freq-RB", + "beamStatus":"SOP-BEAMSTATUS-AR", + "energy" : "SARBD02-DBPM040:ENERGY-OP", + "charge": "SINEG01-DICT215:B1_CHARGE-OP", + "photonEnergy": "SARFE10-PBPG050:PHOTON-ENERGY-PER-PULSE-AVG" + }, + "Athos":{ + "laser":"SWISSFEL-STATUS:Bunch-2-Las-Appl-RB", + "pvFreqRB":"SIN-TIMAST-TMA:Bunch-2-Appl-Freq-RB", + "beamStatus":"SOP-BEAMSTATUS-AT", + "energy" : "SATBD02-DBPM040:ENERGY-OP", + "charge": "SINEG01-DICT215:B2_CHARGE-OP", + "photonEnergy": "SATFE10-PEPG046:PHOTON-ENERGY-PER-PULSE-AVG" + }, + "Update":{ + "freq": [0.5, 1, 2, 5, 10], + "defaultIdx": 1 + }, + "DAQ":{ + "caWaitSec": 0.09 + }, + "MsgSeverity": { + "fatal": "#ee0011", + "error": "#990033", + "warn": "#cc6600", + "info": "#0040ff", + "debug": "#11aaee" + }, + "StyleGuide":{ + "fgAlarmInvalid": "#ffffff", + "fgAlarmMajor": "#ff0000", + "fgAlarmMinor": "#fbfb04", + "fgAlarmNoAlarm": "#00cd00", + "fgNormalText": "#000000", + "fgCurveHor": "#2a63e4", + "fgCurveVer": "#8b1a96", + "fgCurveLong": "#cd6100", + "bgTitleOperation": "#dadada", + "bgTitleExpert": "#646464", + "bgTitleSimulation":"#8b1a96", + "bgMain": "#ececec", + "bgReadbackAlarm": "#c8c8c8", + "bgReadback" : "#ffffe0", + "bgPVSetBeam": "#d4db9d", + "bgPVSet": "#a0a0a0", + "bgButtonWindow": "#b79d5c", + "bgGroupContainers":"#e1e1e1", + "bgErrorLogFile" : "#f0f0f8", + "aramis_color": "#00b7eb", + "athos_color": "#2e5894", + "aramis_qlingrad": "qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #00b7eb , stop: 1 #ffffff)", + "athos_qlingrad": "qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #2e5894 , stop: 1 #ffffff)" + }, + "h5": { + "groups":["General/Created","General/Author","General/Process","General/UID","General/Filepath", + "Machine/Charge", "Machine/Laser","Machine/RepetitionRate","Machine/BeamDestination","Machine/Energy", + "Method/Method","Method/Sensors","Method/Actuators","Method/TimeRecordLength","Method/Background", + "Data"] + }, + "h5Machine": { + "charge": "SINEG01-DICT215:B1_CHARGE_AVERAGE-OP", + "laser": "SLG-LGEN:WHICH_LASER", + "repRate": "SIN-TIMAST-TMA:Beam-Appl-Freq-RB", + "beamDest": "SF:MODE_AR", + "energy": "SF:ENERGY_AR" + }, + "h5Data": { + "dataSet": ["timestamp","data", "pulse_id", "timestamp_offset"] + } +}