Files
HUSH/src/gui.py
2024-02-20 13:21:05 +01:00

1130 lines
45 KiB
Python

'''The GUI module for Savings Overview and magnet control
'''
import getpass
import os
import random
import time
from datetime import timedelta
from qtpy.QtGui import QColor, QPixmap
from qtpy.QtCore import __version__ as QT_VERSION_STR
from qtpy.QtCore import QEventLoop, Qt, Slot
from qtpy.QtWidgets import (
QApplication, QFrame, QGridLayout, QGroupBox, QHBoxLayout, QLabel,
QMessageBox, QPushButton, QTabBar, QTabWidget, QTableWidgetItem,
QTextEdit, QWidget)
import elog
from apps4ops.bdbase.utils import _line
from apps4ops.bdbase.enumkind import MsgSeverity
from caqtwidgets.pvwidgets import (
CAQLabel, CAQLineEdit, CAQMenu, CAQMessageButton, CAQTableWidget, QHLine)
_pymodule = os.path.basename(__file__)
class AppGui(QWidget):
'''The GUI class
'''
def __init__(self, parent):
#super(AppGui, self).__init__()
super().__init__() # Python 3 style for super()
self.parent = parent
self.cafe = self.parent.cafe
self.cyca = self.parent.cyca
self.check_status = self.parent.check_status
self.check_status_list = self.parent.check_status_list
self.elog_enum = self.parent.elog_enum
# Required for caqtwidgets
self.settings = self.parent.settings
self.show_log_message = self.parent.show_log_message
self.statusbar = self.parent.statusbar
self.gui_frame = self.parent.gui_frame
self.gui_header = self.parent.gui_header
self.font_gui = self.parent.gui_frame.font_gui
self.input_parameters = self.parent.input_parameters
self.input_labels = self.parent.input_labels
self.expert_parameters = self.parent.expert_parameters
self.gui_frame.expert_parameters_group.setFixedWidth(260)
self.gui_frame.expert_parameters_group.setFixedHeight(130)
self.gui_frame.operator_parameters_group.setFixedWidth(260)
if "Controlroom" in self.settings.data["Master"]:
self.gui_frame.operator_parameters_group.setFixedHeight(160)
else:
self.gui_frame.operator_parameters_group.setFixedHeight(130)
self.gui_frame.measurement_tab_wgt.setFixedWidth(440)
self.gui_frame.measurement_tab_wgt.setFixedHeight(240)
# self.gui_frame.operator_wgt.setFixedHeight(240)
# self.gui_frame.expert_wgt.setFixedHeight(240)
self.assigned_master = self.gui_header.assigned_master
self.sec_state_list = ["PG1-HUSH:STATE", "PSH-HUSH:STATE",
"PG2-HUSH:STATE", "PO2-HUSH:STATE",
"PPIF-HUSH:STATE", "PG3-HUSH:STATE"]
# Overwrite default
self.gui_frame.central_tab_widget.tabBar().setTabText(0, "Control")
#self.gui_frame.central_tab_widget.tabBar().setTabText(1, "IOC")
#wgt = self.gui_frame.central_tab_widget.widget(1)
#lay = self.gui_frame.central_tab_widget.widget(1).layout()
if "Controlroom" in self.assigned_master:
shift_type = CAQMenu(self, pv_name="PRO-HUSH:SHIFT-TYPE")
self.gui_frame.operator_parameters_group.layout().insertWidget(
0, QLabel(" Shift Type:"))
self.gui_frame.operator_parameters_group.layout().insertWidget(
1, shift_type)
self.gui_frame.results_wgt.setFixedWidth(1400)
self.gui_frame.results_wgt.setFixedHeight(400)
self.gui_frame.results_wgt.setLayout(self.gui_frame.results_layout)
self.gui_frame.results_layout.addWidget(
self.reset_ioc_sm(), 0, 0, 1, 1)
sec_prefix_list = [
sub[0: sub.index("-")] for sub in self.sec_state_list]
self.gui_frame.results_layout.addWidget(
self.reset_ioc_saving(sec_prefix_list), 0, 1, 1, 1)
label = QLabel()
pixmap = QPixmap(":/Hush.jpg")
pixmap.scaled(180, 180, Qt.KeepAspectRatio)
label.setFixedWidth(180)
label.setFixedHeight(180)
label.setPixmap(pixmap)
label.setScaledContents(True)
self.gui_frame.results_layout.addWidget(label, 0, 2, 1, 1, Qt.AlignTop)
self.gui_frame.results_layout.setContentsMargins(15, 15, 15, 15)
self.expert_labels = self.parent.expert_labels
self.settings = self.parent.settings
self.obj_to_upper = bool(random.randint(1, 10) > 3)
self.table_sol_dict = {}
self.table_pwr_dict = {}
self.offtime_dict = {}
# self.I_min = 0.002 HIPA
self.cafe.openPrepare()
self.cafe.open(["PRO-HUSH:LASTPWR", "PRO-HUSH:TOTPWR",
"PRO:LASTSAVE", "PPO-HUSH:TOTSAVE"])
self.cafe.open(self.sec_state_list)
self.cafe.openNowAndWait(0.1)
self.magnet_tab_wgt = self.group_sector_qtabwidget()
self.gui_frame.measurement_layout.addWidget(
self.magnet_tab_wgt, 0, 2, 6, 20, alignment=Qt.AlignTop)
idx = self.magnet_tab_wgt.count() - 1
for i in range(0, self.magnet_tab_wgt.count()):
tabtext = self.magnet_tab_wgt.tabText(i)
if tabtext == "SH":
idx = i
break
self.magnet_tab_wgt.setCurrentIndex(idx)
status_wgt = self.group_sector_status()
status_wgt.setFixedHeight(340)
self.gui_frame.measurement_layout.addWidget(
status_wgt, 3, 0, 2, 1, alignment=Qt.AlignTop) # | Qt.AlignHCenter)
qf = QFrame()
qf.setFixedHeight(5)
self.gui_frame.measurement_layout.addWidget(
qf, 2, 0, 1, 1, alignment=Qt.AlignTop)
qf1 = QFrame()
qf1.setFixedWidth(10)
self.gui_frame.measurement_layout.addWidget(
qf1, 4, 1, 2, 1, alignment=Qt.AlignTop)
#qf2 = QFrame()
#qf2.setFixedWidth(1)
#self.gui_frame.measurement_layout.addWidget(
# qf2, 0, 22, 1, 1, alignment=Qt.AlignTop)
# Overload from guiheader.py
self.sector_disruptor_dict = {}
self.sector_disruptor_dict["G1"] = "Geschlossen"
self.sector_disruptor_dict["SH"] = "Geschlossen"
self.sector_disruptor_dict["G2"] = "Geschlossen"
self.sector_disruptor_dict["O2"] = "Geschlossen"
self.sector_disruptor_dict["PIF"] = "Geschlossen"
self.sector_disruptor_dict["G3"] = "Geschlossen"
def enable_disable_beamline(sect, sector_line, value):
self.sector_disruptor_dict[sect] = value
#print("sect/value", sect, value)
for sector in sector_line:
if "Geschlossen" not in self.sector_disruptor_dict[
sector] or not self.gui_header.is_master():
#print("sector/value", sector, value)
#print("isMaster", self.gui_header.is_master())
#print("master", self.gui_header.mastership)
#print("assigned master", self.assigned_master)
if self.table_sol_dict[
sector].standby_value_button.isEnabled():
self.table_sol_dict[
sector].standby_value_button.setEnabled(False)
if not self.gui_header.is_master():
if self.table_sol_dict[
sector].restore_value_button.isEnabled():
self.table_sol_dict[
sector].restore_value_button.setEnabled(False)
else:
print("Geschlossen? sector/value/ismaster", sector, value,
self.gui_header.mastership)
if not self.table_sol_dict[
sector].standby_value_button.isEnabled():
self.table_sol_dict[
sector].standby_value_button.setEnabled(True)
if not self.table_sol_dict[
sector].restore_value_button.isEnabled():
self.table_sol_dict[
sector].restore_value_button.setEnabled(True)
# [1:] do not include SH for target specific HLA
idx = 0 if "Controlroom" in self.settings.data["Master"] else 1
def receive_sh_update(value, status, alarm_severity):
enable_disable_beamline("SH", self.gui_header.sh_line, value)
def receive_g1_update(value, status, alarm_severity):
enable_disable_beamline("G1", self.gui_header.g1_line, value)
def receive_g3_update(value, status, alarm_severity):
enable_disable_beamline("G3", self.gui_header.g3_line[idx:], value)
def receive_o2_update(value, status, alarm_severity):
enable_disable_beamline("O2", self.gui_header.o2_line[idx:], value)
def receive_g2_update(value, status, alarm_severity):
enable_disable_beamline("G2", self.gui_header.g2_line[idx:], value)
def receive_pif_update(value, status, alarm_severity):
enable_disable_beamline(
"PIF", self.gui_header.pif_line[idx:], value)
if "G1" in self.settings.data["headerMagnetSector"]:
self.gui_header.beam_current_wgt_dict[
"G1"].trigger_monitor_str.connect(receive_g1_update)
pvd = self.cafe.getPVCache(
self.settings.data["G1"]["status"], dt="str")
receive_g1_update(pvd.value[0], pvd.alarmStatus, pvd.alarmSeverity)
if "SH" in self.settings.data["headerMagnetSector"]:
self.gui_header.beam_current_wgt_dict[
"BMA1"].trigger_monitor_str.connect(receive_sh_update)
pvd = self.cafe.getPVCache(
self.settings.data["SH"]["status"], dt="str")
receive_sh_update(pvd.value[0], pvd.alarmStatus, pvd.alarmSeverity)
if "G2" in self.settings.data["headerMagnetSector"]:
self.gui_header.beam_current_wgt_dict[
"G2"].trigger_monitor_str.connect(receive_g2_update)
pvd = self.cafe.getPVCache(
self.settings.data["G2"]["status"], dt="str")
receive_g2_update(pvd.value[0], pvd.alarmStatus, pvd.alarmSeverity)
if "O2" in self.settings.data["headerMagnetSector"]:
self.gui_header.beam_current_wgt_dict[
"O2"].trigger_monitor_str.connect(receive_o2_update)
pvd = self.cafe.getPVCache(
self.settings.data["O2"]["status"], dt="str")
receive_o2_update(pvd.value[0], pvd.alarmStatus, pvd.alarmSeverity)
if "PIF" in self.settings.data["headerMagnetSector"]:
self.gui_header.beam_current_wgt_dict[
"PIF"].trigger_monitor_str.connect(receive_pif_update)
pvd = self.cafe.getPVCache(
self.settings.data["PIF"]["status"], dt="str")
receive_pif_update(pvd.value[0], pvd.alarmStatus, pvd.alarmSeverity)
if "G3" in self.settings.data["headerMagnetSector"]:
self.gui_header.beam_current_wgt_dict[
"G3"].trigger_monitor_str.connect(receive_g3_update)
pvd = self.cafe.getPVCache(
self.settings.data["G3"]["status"], dt="str")
receive_g3_update(pvd.value[0], pvd.alarmStatus, pvd.alarmSeverity)
def receive_b1b2_update(value, status, alarm_severity):
#Enable Only on shutdown and if there is no current in the machine
comet_I = self.cafe.getCache("MMAC3:STR:2")
if comet_I is None:
comet_I = 0.002
if value != "Shutdown" or comet_I > 0.002 or \
not self.gui_header.is_master():
if self.table_sol_dict["B1B2"].standby_value_button.isEnabled():
self.table_sol_dict[
"B1B2"].standby_value_button.setEnabled(False)
if not self.gui_header.is_master():
if self.table_sol_dict[
"B1B2"].restore_value_button.isEnabled():
self.table_sol_dict[
"B1B2"].restore_value_button.setEnabled(False)
else:
if not self.table_sol_dict[
"B1B2"].standby_value_button.isEnabled():
self.table_sol_dict[
"B1B2"].standby_value_button.setEnabled(True)
if not self.table_sol_dict[
"B1B2"].restore_value_button.isEnabled():
self.table_sol_dict[
"B1B2"].restore_value_button.setEnabled(True)
if "B1B2" in self.settings.data["headerMagnetSector"]:
self.gui_header.shift_type.trigger_monitor_str.connect(
receive_b1b2_update)
#holds shifttype
pvd = self.cafe.getPVCache(
self.settings.data["B1B2"]["status"], dt="str")
receive_b1b2_update(pvd.value[0], pvd.alarmStatus, pvd.alarmSeverity)
# end overload from guiheader.py
@Slot()
def simulation_update(state):
if bool(state):
color = self.gui_header.sim_color
else:
color = self.gui_header.op_color
print("SIM STATE CHANGED", state, color, flush=True)
self.gui_header.pf_off_color = color
###JC CHANGE BACK#
self.gui_header.color_pframe(color)
print("SIM STATE CHANGED//", state, color, flush=True)
self.gui_frame.simulation_checkbox.stateChanged.connect(
simulation_update)
def receive_sec_state(handle, pv, pvdata):
pvsplit = pv.split("-")
sec = pvsplit[0][1:]
if pvdata.status == self.cyca.ICAFE_CA_OP_CONN_DOWN:
return
def already_in_standby():
devices = self.settings.data[sec]["iocDevice"]
pv_list = []
standby_value_list = []
for magnet in devices:
pv_magnet = magnet + ":SOL:2"
pv_list.append(pv_magnet)
# get standby values
idx = self.settings.data[sec]["device"].index(magnet)
standby_value = self.settings.data[sec]["standby"][idx]
standby_value_list.append(standby_value)
print("pvlist===>", pv_list, flush=True)
print("standby ist==>", standby_value_list, flush=True)
QApplication.processEvents()
value_list, status, status_list = self.cafe.getScalarList(
pv_list, cacheFlag=True)
#print("status", status, status_list, flush=True)
print("valuelist==>", pv_list, value_list, flush=True)
if status != self.cyca.ICAFE_NORMAL:
self.check_status_list(_pymodule, "getScalarListCache",
pv_list, status_list, _line())
# check standby values
in_standby = True
for value, standby in zip(value_list, standby_value_list):
if abs(value) < abs(standby) * 0.8 or abs(value) > abs(
standby) * 1.2:
in_standby = False
break
print("is_standby", in_standby, flush=True)
return in_standby
if pvdata.value[0] == "ON" and not already_in_standby():
print("pv, sec-ON", pv, sec, flush=True)
self.table_sol_dict[sec].init_value_button.setEnabled(True)
self.table_pwr_dict[sec].init_value_button.setEnabled(True)
else:
print("pv, sec-OFF", pv, sec, flush=True)
self.table_sol_dict[sec].init_value_button.setEnabled(False)
self.table_pwr_dict[sec].init_value_button.setEnabled(False)
for state in self.sec_state_list:
for sector in self.settings.data["headerMagnetSector"]:
if sector in state:
self.cafe.monitor(state, receive_sec_state)
print("MONITOR======>", sector, state)
break
def group_sector_status(self):
qgrid = QGridLayout()
# Heading
idx = self.settings.data["header"].index("G1")
idx_last = self.settings.data["header"].index("MASTER")
# Sector
'''
qgrid.setContentsMargins(0, 0, 0, 0)
qgrid.setSpacing(0)
container2 = QWidget()
container3 = QWidget()
container4 = QWidget()
container5 = QWidget()
container6 = QWidget()
layout2 = QHBoxLayout(container2)
layout2.setContentsMargins(0, 0, 0, 0)
layout2.setAlignment(Qt.AlignCenter)
layout3 = QHBoxLayout(container3)
layout3.setContentsMargins(0, 0, 0, 0)
layout3.setAlignment(Qt.AlignCenter)
layout4 = QHBoxLayout(container4)
layout4.setContentsMargins(0, 0, 0, 0)
layout4.setAlignment(Qt.AlignCenter)
layout5 = QHBoxLayout(container5)
layout5.setContentsMargins(0, 0, 0, 0)
layout5.setAlignment(Qt.AlignCenter)
layout6 = QHBoxLayout(container6)
layout6.setContentsMargins(0, 0, 0, 0)
layout6.setAlignment(Qt.AlignCenter)
'''
qlp = QLabel("Power \n(kW)")
f = qlp.font()
f.setPixelSize(13)
qlp.setFont(f)
qlp.setAlignment(Qt.AlignCenter)
qli = QLabel("Initial \n(kW)")
f = qli.font()
f.setPixelSize(13)
qli.setFont(f)
qli.setAlignment(Qt.AlignCenter)
# layout2.addWidget(qli)
#qgrid.addWidget(container2, 0, 1, 1, 1)
qgrid.addWidget(qli, 0, 1, 1, 1)
qsa = QLabel("Saving \n(MWh)")
f = qsa.font()
f.setPixelSize(13)
qsa.setFont(f)
qsa.setAlignment(Qt.AlignCenter)
qti = QLabel("Time in \nSaving Mode")
f = qti.font()
f.setPixelSize(13)
qti.setFont(f)
qti.setAlignment(Qt.AlignCenter)
qtotsav = QLabel("Tot Saved \n(MWh)")
f = qtotsav.font()
f.setPixelSize(13)
qtotsav.setFont(f)
qtotsav.setAlignment(Qt.AlignCenter)
'''
layout3.addWidget(qlp)
layout4.addWidget(qsa)
layout5.addWidget(qti)
layout6.addWidget(qtotsav)
qgrid.addWidget(container3, 0, 2, 1, 1)
qgrid.addWidget(container4, 0, 3, 1, 1)
qgrid.addWidget(container5, 0, 5, 1, 1)
qgrid.addWidget(container6, 0, 6, 1, 1)
#q=QFrame()
#q.setFixedWidth(12)
#qgrid.addWidget(q, 0, 7, 1, 1)
'''
qgrid.addWidget(qlp, 0, 2, 1, 1)
qgrid.addWidget(qsa, 0, 3, 1, 1)
qgrid.addWidget(qti, 0, 5, 1, 1)
qgrid.addWidget(qtotsav, 0, 6, 1, 1)
for i, sector in enumerate(self.settings.data["header"][idx:idx_last]):
a, b, c, d, e, f = self.sector_status(sector)
'''
container = QWidget()
layout = QHBoxLayout(container)
layout.setContentsMargins(2, 0, 0, 0)
container.setStyleSheet("background-color: lightblue;")
layout.addWidget(a)
a.setContentsMargins(2, 0, 0, 0)
container2 = QWidget()
container3 = QWidget()
container4 = QWidget()
container5 = QWidget()
container6 = QWidget()
layout2 = QHBoxLayout(container2)
layout2.setContentsMargins(0, 0, 0, 0)
container2.setStyleSheet("background-color: lightblue;")
layout2.addWidget(b)
b.setContentsMargins(0, 0, 0, 0)
layout3 = QHBoxLayout(container3)
layout3.setContentsMargins(0, 0, 0, 0)
container3.setStyleSheet("background-color: lightblue;")
layout3.addWidget(c)
c.setContentsMargins(0, 0, 0, 0)
layout4 = QHBoxLayout(container4)
layout4.setContentsMargins(0, 0, 0, 0)
container4.setStyleSheet("background-color: lightblue;")
layout4.addWidget(d)
d.setContentsMargins(0, 0, 0, 0)
layout5 = QHBoxLayout(container5)
layout5.setContentsMargins(0, 0, 0, 0)
container5.setStyleSheet("background-color: lightblue;")
layout5.addWidget(e)
e.setContentsMargins(0, 0, 0, 0)
layout6 = QHBoxLayout(container6)
layout6.setContentsMargins(0, 0, 0, 0)
container6.setStyleSheet("background-color: lightblue;")
layout6.addWidget(f)
f.setContentsMargins(0, 0, 0, 0)
layout2.setAlignment(Qt.AlignLeft)
layout3.setAlignment(Qt.AlignLeft)
layout4.setAlignment(Qt.AlignLeft)
layout5.setAlignment(Qt.AlignLeft)
layout6.setAlignment(Qt.AlignLeft)
qgrid.addWidget(container, i+1, 0, 1, 1)
qgrid.addWidget(container2, i+1, 1, 1, 1)
qgrid.addWidget(container3, i+1, 2, 1, 1)
qgrid.addWidget(container4, i+1, 3, 1, 1)
qgrid.addWidget(container5, i+1, 5, 1, 1)
qgrid.addWidget(container6, i+1, 6, 1, 1)
'''
qgrid.addWidget(a, i + 1, 0, 1, 1)
qgrid.addWidget(b, i + 1, 1, 1, 1)
qgrid.addWidget(c, i + 1, 2, 1, 1)
qgrid.addWidget(d, i + 1, 3, 1, 1)
qgrid.addWidget(e, i + 1, 5, 1, 1)
qgrid.addWidget(f, i + 1, 6, 1, 1)
line = QHLine()
line.setFixedHeight(10)
row = qgrid.rowCount()
qgrid.addWidget(line, row, 1, 1, 6)
#qgrid.setRowMinimumHeight(_row, 60)
qtot = QLabel("Total:")
fnt = qtot.font()
fnt.setPixelSize(13)
qtot.setFont(fnt)
qgrid.addWidget(qtot, row + 1, 0, 1, 1)
qgrid.addWidget(
CAQLineEdit(self, pv_name="PRO-HUSH:LASTPWR",
show_units=True),
row + 1, 1, 1, 1)
qgrid.addWidget(
CAQLineEdit(self, pv_name="PRO-HUSH:TOTPWR", show_units=True),
row + 1, 2, 1, 1)
qgrid.addWidget(
CAQLineEdit(self, pv_name="PRO-HUSH:LASTSAVE", show_units=True),
row + 1, 3, 1, 2)
qgrid.addWidget(
CAQLineEdit(self, pv_name="PRO-HUSH:TOTSAVE", show_units=True),
row + 1, 6, 1, 2)
qgrid.setContentsMargins(9, 20, 9, 9)
qw = QGroupBox("Savings Overview")
qw.setContentsMargins(9, 9, 9, 9)
qw.setObjectName("OUTER")
qw.setLayout(qgrid)
qw.setFixedWidth(596) # 480
return qw
def sector_status(self, sector):
'''Create each sector line for inclusion into group
'''
device = "P" + sector + "-HUSH"
# Qlabel
qsector = QLabel(sector + ":")
f = qsector.font()
f.setPixelSize(13)
qsector.setFont(f)
color = "black"
try:
color = self.settings.data[sector]["color"]
except KeyError as ex:
print(ex, self.settings.data[sector])
weight = "bold" if sector in self.settings.data[
"headerMagnetSector"] else "medium"
color_str = "color : {0}; font-weight:{1};".format(color, weight)
incolor = "QLabel {" + color_str + "}"
qsector.setStyleSheet(incolor)
# Savings
pv_pwr_tot = device + ":TOTPWR"
pv_pwr_last = device + ":LASTPWR"
pv_pwr_saved = device + ":LASTSAVE"
pv_pwr_timeout = device + ":OFFTIME"
pv_pwr_totsave = device + ":TOTSAVE"
self.cafe.openPrepare()
self.cafe.open([pv_pwr_tot, pv_pwr_last, pv_pwr_saved, pv_pwr_timeout])
self.cafe.openNowAndWait(2.0)
time.sleep(0.1)
#print("device", device, flush=True)
def cb_outtime(handle, pv, pvdata):
try:
delta = "{}".format(str(timedelta(seconds=(pvdata.value[0]))))
if delta == "0:00:00":
delta = "0 s "
self.offtime_dict[pv].setAlignment(Qt.AlignRight)
elif ", " in delta:
le_split = delta.split(", ")
if len(le_split) == 2:
if len(le_split[1]) == len("0:00:00"):
delta = le_split[0] + ", " + le_split[1]
if "days," in delta:
delta = delta.replace("days,", "d")
elif "day," in delta:
delta = delta.replace("day,", "d")
self.offtime_dict[pv].setText(delta)
except KeyError:
pass
qpinit = CAQLineEdit(self, pv_name=pv_pwr_last, show_units=False)
qpnow = CAQLineEdit(self, pv_name=pv_pwr_tot, show_units=False,
notify_freq_hz=1)
qpsave = CAQLineEdit(self, pv_name=pv_pwr_saved, show_units=False)
qptotsave = CAQLineEdit(self, pv_name=pv_pwr_totsave, show_units=False)
qptime = CAQLineEdit(self, pv_name=pv_pwr_timeout,
monitor_callback=cb_outtime, show_units=True)
self.offtime_dict[pv_pwr_timeout] = qptime
# Time to allow cb_outtime to fire
time.sleep(0.2)
qptime.setFixedWidth(104)
return qsector, qpinit, qpnow, qpsave, qptime, qptotsave
def group_sector_qtabwidget(self):
#idx_last = self.settings.data["header"].index("MASTER")
#idx = self.settings.data["header"].index("G1")
# open all PVS
pv = []
# for sector in self.settings.data["header"][idx:idx_last]:
for sector in self.settings.data["headerMagnetSector"]:
device_list = self.settings.data[sector]["device"]
attribute_list = self.settings.data[sector]["attribute"]
for att in attribute_list:
for dev in device_list:
pv.append(dev + ":" + att)
self.cafe.openPrepare()
self.cafe.open(pv)
self.cafe.openNowAndWait(1.0)
# self.cafe.supplementHandles()
self.sector_wgt_dict = {}
# for sector in self.settings.data["header"][idx:idx_last]:
for sector in self.settings.data["headerMagnetSector"]:
self.sector_wgt_dict[sector] = self.ca_table_sector_widget(
sector=sector)
QApplication.processEvents()
sector_tab_widget = QTabWidget()
sector_tab_widget.setFont(self.font_gui)
sector_tab_widget.setStyleSheet("QTabBar {font-size: 12pt;}")
sector_tab_widget.tabBar().setShape(QTabBar.TriangularNorth)
# for i, sector in
# enumerate(self.settings.data["header"][idx:idx_last]):
for i, sector in enumerate(self.settings.data["headerMagnetSector"]):
sector_tab_widget.addTab(self.sector_wgt_dict[sector], sector)
color = self.settings.data[sector]["color"]
sector_tab_widget.tabBar().setTabTextColor(i, QColor(color))
return sector_tab_widget
def on_sector_standby(self):
target = self.sender()
sector = target.sector
table = self.table_sol_dict[sector]
def is_update_enabled():
'''Check if update buttons are enabled
if NOT, then do not allow inital values values to be updated"
'''
'''
if self.table_pwr_dict[sector].init_value_button.isEnabled() \
and table.init_value_button.isEnabled():
return True
else:
return False
'''
return bool(
self.table_pwr_dict[sector].init_value_button.isEnabled(
) and table.init_value_button.isEnabled())
QApplication.processEvents(QEventLoop.AllEvents, 1.0)
# Do NOT do updates if in standby mode!
# Update button is disabled when in standby
# disenable widgets to avoid circular behaviour since
# updates of SOL also update PWR, and vice-versa
# Do not click if already on standby!!
update_enabled = is_update_enabled()
if update_enabled:
self.table_pwr_dict[sector].init_value_button.setEnabled(False)
table.init_value_button.click()
time.sleep(0.05)
self.table_pwr_dict[sector].init_value_button.setEnabled(True)
table.init_value_button.setEnabled(False)
self.table_pwr_dict[sector].init_value_button.click()
time.sleep(0.05)
self.table_sol_dict[sector].init_value_button.setEnabled(True)
QApplication.processEvents(QEventLoop.AllEvents, 1.0)
if not self.input_parameters["simulation"]:
status, status_list, pv_list = table.set_standby_values()
if status != self.cyca.ICAFE_NORMAL:
self.check_status_list(
_pymodule, "setScalarList", pv_list, status_list, _line())
# Seqeuncer ONLY determines when to go into STANDBY mode
# and NOT the HLA
##pv = 'P' + target.sector + "-HUSH:STATE"
##stat = self.cafe.set(pv, 0)
##self.check_status(_pymodule, 'set', pv, stat, _line())
# Disable because _table.set_standby_values() enables it
if not update_enabled:
self.table_pwr_dict[sector].init_value_button.setEnabled(False)
table.init_value_button.setEnabled(False)
def on_sector_restore(self):
target = self.sender()
sector = target.sector
table = self.table_sol_dict[sector]
if not self.input_parameters["simulation"]:
status, status_list, pv_list = table.restore_init_values()
if status != self.cyca.ICAFE_NORMAL:
self.check_status_list(
_pymodule, "setScalarList", pv_list, status_list, _line())
# Seqeuncer ONLY determines when to go into STANDBY mode
# and NOT the HLA
#pv = 'P' + target.sector + "-HUSH:STATE"
#stat = self.cafe.set(pv, 1)
#self.check_status(_pymodule, 'set', pv, stat, _line())
table_pwr = self.table_pwr_dict[sector]
row_pwr_dict = table_pwr.get_init_values()
sum_pwr = sum(list(row_pwr_dict.values()))
pv_last_pwr = "P" + target.sector + "-HUSH:LASTPWR"
stat = self.cafe.set(pv_last_pwr, sum_pwr)
self.check_status(_pymodule, "set", pv_last_pwr, stat, _line())
def ca_table_sector_widget(self, sector: str = ""):
device_list = self.settings.data[sector]["device"]
attribute_list = self.settings.data[sector]["attribute"]
try:
standby_values = self.settings.data[sector]["standby"]
print("Standby Values", sector, standby_values, flush=True)
except KeyError:
print("On Standby values not given for sector {0}".format(sector))
pv_dict = {}
for att in attribute_list:
att_pv = att
att_key = att if att != "PWR:2" else "PWR"
pv_dict[att_key] = [] # [None] * len(device_list)
for dev in device_list:
pv_dict[att_key].append(dev + ":" + att_pv)
try:
delay = self.input_parameters["delayRamp"]
except KeyError:
delay = 0.09
pass
#print(pv_dict['SOL:2'], flush=True)
#print(_standby_values, flush=True)
table_sol = CAQTableWidget(
self, pv_list=pv_dict["SOL:2"], show_units=True, notify_freq_hz=0,
notify_unison=False, scale_factor=1, show_timestamp=False,
init_column=True, pv_list_show=device_list, standby_column=True,
standby_values=standby_values, set_delay=delay)
table_sol.restore_value_button.setToolTip(
("Restore devices to their pre-standby values"))
table_sol.init_value_button.setToolTip(
("Shows initial, pre-standby values. Update is also " +
"executed automatically before the standby procedure."))
table_sol.standby_value_button.sector = sector
table_sol.standby_value_button.clicked.disconnect()
table_sol.standby_value_button.clicked.connect(self.on_sector_standby)
table_sol.restore_value_button.sector = sector
table_sol.restore_value_button.clicked.disconnect()
table_sol.restore_value_button.clicked.connect(self.on_sector_restore)
self.table_sol_dict[sector] = table_sol
table_ist = CAQTableWidget(
self, pv_list=pv_dict["IST:2"], show_units=True, notify_freq_hz=1,
notify_unison=True, scale_factor=1, show_timestamp=False,
init_column=False, pv_list_show=[False])
table_pwr = CAQTableWidget(
self, pv_list=pv_dict["PWR"], show_units=False, notify_freq_hz=1,
suffix="kW",
notify_unison=True, scale_factor=0.001, show_timestamp=False,
init_column=True, init_list=pv_dict["PWR"], pv_list_show=[False])
table_pwr.init_value_button.setToolTip(
("Shows initial, pre-standby values. Update is also " +
"executed automatically before the standby procedure."))
self.table_pwr_dict[sector] = table_pwr
header_item = QTableWidgetItem()
header_init = QTableWidgetItem()
header_standby = QTableWidgetItem()
header_value = QTableWidgetItem()
f = header_value.font()
f.setPixelSize(13)
header_item.setFont(f)
header_item.setText("Device")
header_init.setFont(f)
header_init.setText("Init. Value")
header_standby.setFont(f)
header_standby.setText("Standby")
header_value.setFont(f)
header_value.setText("SOL:2")
table_sol.setContentsMargins(15, 0, 15, 10)
table_sol.setHorizontalHeaderItem(0, header_item)
table_sol.setHorizontalHeaderItem(1, header_init)
table_sol.setHorizontalHeaderItem(2, header_standby)
table_sol.setHorizontalHeaderItem(3, header_value)
table_sol.setColumnWidth(0, 80)
table_sol.setColumnWidth(1, 88)
table_sol.setColumnWidth(2, 80)
table_sol.setColumnWidth(3, 88)
table_sol.setFixedWidth(386)
ioc_magnets = []
for i, device in enumerate(device_list):
if device in self.settings.data[sector]["iocDevice"]:
ioc_magnets.append(i)
header_value = QTableWidgetItem()
f = header_value.font()
f.setPixelSize(13)
header_value.setFont(f)
header_value.setText("IST:2")
table_ist.setContentsMargins(15, 0, 15, 10)
table_ist.setHorizontalHeaderItem(0, header_value)
table_ist.setColumnWidth(0, 90)
table_ist.setFixedWidth(140)
header_init = QTableWidgetItem()
f = header_init.font()
header_init.setFont(f)
header_init.setText("Init. Value")
header_value = QTableWidgetItem()
f = header_value.font()
f.setPixelSize(13)
header_value.setFont(f)
header_value.setText("PWR")
table_pwr.setContentsMargins(15, 0, 15, 10)
table_pwr.setHorizontalHeaderItem(0, header_init)
table_pwr.setHorizontalHeaderItem(1, header_value)
table_pwr.setColumnWidth(0, 88)
table_pwr.setColumnWidth(1, 88)
table_pwr.setFixedWidth(226)
if "Controlroom" in self.assigned_master and "B1B2" not in sector:
for i in ioc_magnets:
table_sol.paint_rows(row_range=[i, i + 1], reset=False,
columns=[0, 1])
table_ist.paint_rows(row_range=[i, i + 1], reset=False)
table_pwr.paint_rows(row_range=[i, i + 1], reset=False)
pv_status = self.settings.data[sector]["status"]
beamline_status = self.cafe.getCache(pv_status)
if beamline_status is not None:
# in HIPA this was I < self.I_min:
if "Geschlossen" in beamline_status:
try:
values = self.settings.data[sector]["ref"]
table_sol.set_init_values(values)
except KeyError:
pass
try:
pwr_values = self.settings.data[sector]["pwrref"]
table_pwr.set_init_values(pwr_values)
except KeyError:
pass
def on_sol_update():
table_sol.init_value_button.setEnabled(False)
table_pwr.init_value_button.click()
time.sleep(0.1)
table_sol.init_value_button.setEnabled(True)
pv = "P" + table_pwr.init_value_button.sector + "-HUSH:LASTPWR"
init_sum = sum(table_pwr.get_init_values().values())
print("SUM up all the values", pv, init_sum, flush=True)
#B1B2 is not is not in state machine
if "B1B2" in table_pwr.init_value_button.sector:
retrun
stat = self.cafe.set(pv, init_sum)
self.check_status(_pymodule, "set", pv, stat, _line())
def on_init_update():
table_pwr.init_value_button.setEnabled(False)
table_sol.init_value_button.click()
time.sleep(0.1)
table_pwr.init_value_button.setEnabled(True)
table_sol.init_value_button.sector = sector
table_sol.init_value_button.clicked.connect(on_sol_update)
table_pwr.init_value_button.sector = sector
table_pwr.init_value_button.clicked.connect(on_init_update)
hbox = QHBoxLayout()
hbox.addWidget(table_sol)
hbox.addWidget(table_ist)
hbox.addWidget(table_pwr)
hbox.setSpacing(10)
hbox.setAlignment(Qt.AlignTop)
qw = QWidget()
qw.setLayout(hbox)
obj_name = self.settings.data[sector]["colorObj"]
if self.obj_to_upper:
obj_name = obj_name.upper()
qw.setObjectName(obj_name)
return qw
def clear_saving(self, sector_prefix_list: list = None):
if not sector_prefix_list:
return
qm = QMessageBox()
mess = ("This action will reset the energy saving account to zero. \n" +
"This is typically undertaken at the end of the calendar " +
"year. \n\n" +
"Present accounting figures will be entered in the elogbook\n" +
"Are you sure you wish to continue with the reset?")
reply = qm.warning(self, "Reset Accounting", mess,
QMessageBox.Yes | QMessageBox.No)
if reply == QMessageBox.No:
return
self.parent.prepare_elog_message()
print("message", self.parent.message)
print("logbook", self.parent.logbook, flush=True)
url = self.settings.data["ElogBooks"][self.parent.logbook]["url"]
print("url", url, flush=True)
logbook = elog.open(url, user="robot", password="robot")
# QApplication.processEvents()
attributes = {}
attributes["Autor"] = getpass.getuser()
attributes["Author"] = getpass.getuser()
attributes["Application"] = self.parent.appname
attributes["Titel"] = self.parent.title
attributes["Title"] = self.parent.title
attributes["When"] = str(time.time())
attributes["Wann"] = str(time.time())
if "Sandkasten" in self.parent.logbook:
attributes["Eintrag"] = "Anregung"
else:
attributes["Eintrag"] = self.elog_enum.eintrag.INFO.name
attributes["Effekt"] = self.elog_enum.effekt.NONE.name #"keiner"
log_mess = self.parent.message.replace("<br>", "\n")
try:
logbook.post(log_mess, attributes=attributes)
self.show_log_message(MsgSeverity.INFO, _pymodule, _line(),
log_mess)
self.statusbar.showMessage("Reset Savings Account." +
"Last values sent to elog")
except Exception as ex:
print("Exception in sendelog.py", str(ex))
mess = "Failed to write last saving values to elog:" + str(ex)
self.show_log_message(
MsgSeverity.ERROR, _pymodule, _line(), mess)
self.statusbar.showMessage(mess)
for sector in sector_prefix_list:
self.sector_sm_off(sector)
for sector in sector_prefix_list:
self.clear_sector_saving(sector)
def sector_sm_off(self, sector_prefix: str = None):
if not sector_prefix:
return
pv1 = sector_prefix + "-HUSH:SEQ-ONOFF"
stat = self.cafe.set(pv1, 0)
self.check_status(_pymodule, "set", pv1, stat, _line())
time.sleep(0.05)
QApplication.processEvents()
return
def clear_sector_saving(self, sector_prefix: str = None):
if not sector_prefix:
return
pv1 = sector_prefix + "-HUSH:SEQ-ONOFF"
pv2 = sector_prefix + "-HUSH:TOTSAVE"
pv3 = sector_prefix + "-HUSH:OFFTIME"
stat = self.cafe.set(pv1, 0)
self.check_status(_pymodule, "set", pv1, stat, _line())
off_time = self.cafe.get(pv3)
self.check_status(_pymodule, "get", pv3, None, _line())
iloop = 0
if off_time is not None:
while off_time > 0 and iloop < 100:
time.sleep(0.1)
off_time_tmp = self.cafe.get(pv3)
off_time = off_time_tmp if off_time_tmp is not None else 0
iloop += 1
QApplication.processEvents()
else:
time.sleep(0.1)
print("SECTOR ILOOP", sector_prefix, iloop)
stat = self.cafe.set(pv1, 1)
self.check_status(_pymodule, "set", pv1, stat, _line())
stat = self.cafe.set(pv2, 0)
self.check_status(_pymodule, "set", pv2, stat, _line())
return
def reset_ioc_saving(self, sector_prefix_list: list = None):
if not sector_prefix_list:
return
qpb = QPushButton("Reset Account")
qpb.setObjectName("WriteData")
qpb.clicked.connect(lambda: self.clear_saving(sector_prefix_list))
qpb.setFixedHeight(40) # self.gui_frame.widget_height)
qpb.setFixedWidth(160)
qtext = QTextEdit()
qtext.setText("""<br>&nbsp;&nbsp;The Reset Account Button resets Total Power Saved (MWh) to zero. <br>
&nbsp;&nbsp;This is typically executed at the end of the calendar year.<br>
&nbsp;&nbsp;The present energy saving figures will be entered into the elogbook.<br>
&nbsp;&nbsp;The button prompts the user for confirmation before proceeding.<br>
""")
qtext.setReadOnly(True)
qtext.setStyleSheet("background-color: QColor(0, 0, 50, 10);")
qtext.setFixedHeight(104)
qtext.setFixedWidth(440)
qgrid = QGridLayout()
qgrid.setSpacing(0)
qgrid.addWidget(qtext, 0, 0, 1, 1, Qt.AlignHCenter)
qgrid.addWidget(qpb, 1, 0, 1, 1, Qt.AlignHCenter)
qw = QGroupBox("HUSH! Accounting")
qw.setContentsMargins(2, 10, 2, 0)
qw.setAlignment(Qt.AlignTop)
qw.setObjectName("OUTER")
qw.setLayout(qgrid)
qw.setFixedWidth(460)
qw.setFixedHeight(280)
return qw
def reset_ioc_sm(self):
msg_button = [None] * len(self.sec_state_list)
monitor_seq_onoff = [None] * len(self.sec_state_list)
monitor_seq_state = [None] * len(self.sec_state_list)
monitor_standby_state = [None] * len(self.sec_state_list)
qgrid = QGridLayout()
qreset = QLabel("Reset")
qreset.setAlignment(Qt.AlignBottom | Qt.AlignHCenter)
qsm = QLabel("SM ")
qsm.setAlignment(Qt.AlignBottom | Qt.AlignHCenter)
qss = QLabel("Sequencer State ")
qss.setAlignment(Qt.AlignBottom | Qt.AlignHCenter)
qstandby = QLabel("ON or \nStandby")
qstandby.setAlignment(Qt.AlignBottom | Qt.AlignHCenter)
qgrid.addWidget(qreset, 0, 0, 1, 1)
qgrid.addWidget(qsm, 0, 1, 1, 1)
qgrid.addWidget(qss, 0, 2, 1, 1)
qgrid.addWidget(qstandby, 0, 3, 1, 1)
for i, pv in enumerate(self.sec_state_list):
pvsplit = pv.split("-")
sec = pvsplit[0][1:]
pv_seq_onoff = pv.replace("STATE", "SEQ-ONOFF")
pv_seq_state = pv.replace("STATE", "SEQ-STATE")
msg_button[i] = CAQMessageButton(
self, pv_name=pv_seq_onoff, msg_label=sec,
msg_press_value="Off", msg_release_value="On")
monitor_seq_onoff[i] = CAQLabel(self, pv_name=pv_seq_onoff)
monitor_seq_state[i] = CAQLabel(self, pv_name=pv_seq_state)
monitor_standby_state[i] = CAQLabel(self, pv_name=pv)
qgrid.addWidget(msg_button[i], i + 1, 0, 1, 1, Qt.AlignLeft)
qgrid.addWidget(monitor_seq_onoff[i], i + 1, 1, 1, 1, Qt.AlignLeft)
qgrid.addWidget(monitor_seq_state[i], i + 1, 2, 1, 1, Qt.AlignLeft)
qgrid.addWidget(
monitor_standby_state[i],
i + 1,
3,
1,
1,
Qt.AlignLeft)
qgrid.setContentsMargins(9, 9, 9, 9)
qgrid.setSpacing(10)
qw = QGroupBox("State Machine")
qw.setContentsMargins(5, 10, 5, 0)
qw.setAlignment(Qt.AlignTop)
qw.setObjectName("OUTER")
qw.setLayout(qgrid)
qw.setFixedWidth(460)
qw.setFixedHeight(280)
return qw