Files
HUSH/src/gui.py
T
2024-02-06 16:48:44 +01:00

1005 lines
40 KiB
Python

import getpass
import inspect
import os
import platform
import random
import sys
import time
from datetime import timedelta
from qtpy import QtCore, QtGui
from qtpy.QtGui import QColor, QFont, QIcon
from qtpy.QtCore import __version__ as QT_VERSION_STR
from qtpy.QtCore import (
PYQT_VERSION_STR, QDate, QDateTime, QEventLoop, Qt, Signal, Slot)
from qtpy.QtWidgets import (
QApplication, QDockWidget, QFrame, QGridLayout, QGroupBox, QHBoxLayout,
QLabel, QMainWindow, QMessageBox, QProgressBar, QPushButton, QSizePolicy,
QSpacerItem, QStackedWidget, QTabBar, QTabWidget, QTableWidget,
QTableWidgetItem, QVBoxLayout, QWidget)
import elog
from apps4ops.bdbase.base import BaseWindow
from apps4ops.bdbase.enumkind import MsgSeverity, UserMode, Facility
from caqtwidgets.pvwidgets import (
CAQLabel, CAQLineEdit, CAQMessageButton, CAQTableWidget, QHLine)
_pymodule = os.path.basename(__file__)
def _line():
"""Macro to return the current line number.688
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 AppGui(QWidget):
def __init__(self, parent):
super(AppGui, self).__init__()
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
#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.operator_parameters_group.setFixedWidth(260)
#self.gui_frame.operator_parameters_group.setFixedHeight(260)
self.gui_frame.measurement_tab_wgt.setMinimumWidth(440)
self.gui_frame.measurement_tab_wgt.setFixedHeight(280)
#self.gui_frame.operator_wgt.setFixedHeight(240)
#self.gui_frame.expert_wgt.setFixedHeight(240)
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")
#self.gui_frame.results_wgt is the IOC tab widget
#wgt = self.gui_frame.results_wgt.layout().widget()
#self.gui_frame.results_wgt.layout().removeWidget(wgt)
#wgt.deleteLater()
#wgt = None
#self.gui_frame.central_tab_widget.widget(1).setLayout(self.reset_ioc_sm())
wgt = self.gui_frame.central_tab_widget.widget(1)
#print(dir(wgt))
lay = self.gui_frame.central_tab_widget.widget(1).layout()
#print(dir(lay))
'''
def deleteItemsOfLayout(layout):
if layout is not None:
while layout.count():
item = layout.takeAt(0)
widget = item.widget()
if widget is not None:
widget.setParent(None)
else:
deleteItemsOfLayout(item.layout())
vlayout = self.gui_frame.central_tab_widget.widget(1).layout()
if vlayout is not None:
for i in range(vlayout.count()):
layout_item = vlayout.itemAt(i)
#if layout_item.layout() == box:
deleteItemsOfLayout(layout_item.layout())
vlayout.removeItem(layout_item)
layout_item = None
break
vlayout = None
'''
self.gui_frame.results_wgt.setFixedWidth(1200)
self.gui_frame.results_wgt.setFixedHeight(400)
#wgt2 = self.gui_frame.results_tab_wgt.layout().widget()
#self.gui_frame.central_tab_widget.widget(1).layout().replaceWidget(wgt2, self.reset_ioc_sm())
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)
self.gui_frame.results_layout.setContentsMargins(40, 40, 40, 40)
#self.gui_frame.results_wgt.insertWidget(0, self.reset_ioc_sm())
#self.gui_frame.results_wgt.setLayout(self.reset_ioc_sm().layout())
self.expert_labels = self.parent.expert_labels
self.settings = self.parent.settings
self.obj_to_upper = True if random.randint(1, 10) > 3 else False
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)
wgt = self.group_sector_qtabwidget()
self.gui_frame.measurement_layout.addWidget(
wgt, 0, 1, 6, 3, alignment=Qt.AlignTop)
status_wgt = self.group_sector_status()
self.gui_frame.measurement_layout.addWidget(
status_wgt, 2, 0, 2, 1, alignment=Qt.AlignTop) # | Qt.AlignHCenter)
qf = QFrame()
qf.setFixedHeight(6)
self.gui_frame.measurement_layout.addWidget(
qf, 4, 0, 1, 1, alignment=Qt.AlignTop)
self.sectorI_dict = {}
self.sectorI_dict['G1'] = "Geschlossen"
self.sectorI_dict['SH'] = "Geschlossen"
self.sectorI_dict['G2'] = "Geschlossen"
self.sectorI_dict['O2'] = "Geschlossen"
self.sectorI_dict['PIF'] = "Geschlossen"
self.sectorI_dict['G3'] = "Geschlossen"
g3_line = ["SH", "PIF", "G3"]
pif_line = ["SH", "PIF"]
o2_line = ["SH", "O2"]
g2_line = ["SH", "G2"]
g1_line = ["SH", "G1"]
sh_line = ["SH"]
try:
pv_master = self.settings.data["MASTER"]["status"]
self.mastership = self.cafe.getCache(pv_master)
self.check_status(_pymodule, 'get', pv_master, None, _line())
except KeyError as ex:
print("KeyError: {0}".format(str(ex)))
def is_master():
return True if "Control" in self.mastership else False
#defined in guiheader.py
#master_to_wgt = {"Gantry 1": "G1", "Gantry 2": "G2",
# "Gantry 3": "G3", "OPTIS2": "O2"}
def receive_master_update(value, status, alarm_severity):
print("value", value, flush=True)
self.mastership = value
for key, wgt_val in self.gui_header.master_to_wgt.items():
master = self.gui_header.beam_current_wgt_group[wgt_val]
#print(key, wgt_val, "present object name", master.objectName(), flush=True)
#print(value)
if value in key:
master.setObjectName("ARAMIS")
master.style().polish(master)
self.gui_header.target_beamline = wgt_val
self.gui_header.timer.start(750)
self.gui_header.timer_count = 0
#print("NEW object name", master.objectName(), flush=True)
else:
if "BEAMLINE" not in master.objectName():
master.setObjectName("BEAMLINE")
master.style().polish(master)
#print("NEW object name", master.objectName(), flush=True)
self.gui_header.beam_current_wgt_dict[
wgt_val].trigger_monitor_str.emit(
self.sectorI_dict[wgt_val], 1, 0)
def enable_disable_beamline(sect, sector_line, value):
self.sectorI_dict[sect] = value
#print("sect/value", sect, value)
for sector in sector_line:
if "Geschlossen" not in self.sectorI_dict[
sector] or not is_master():
#print("sector/value", sector, value)
if self.table_sol_dict[
sector].standby_value_button.isEnabled():
self.table_sol_dict[
sector].standby_value_button.setEnabled(False)
print("DISABLE", sector)
if not 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.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)
def receive_sh_update(value, status, alarm_severity):
enable_disable_beamline('SH', sh_line, value)
def receive_g1_update(value, status, alarm_severity):
enable_disable_beamline('G1', g1_line, value)
def receive_g3_update(value, status, alarm_severity):
enable_disable_beamline('G3', g3_line, value)
def receive_o2_update(value, status, alarm_severity):
enable_disable_beamline('O2', o2_line, value)
def receive_g2_update(value, status, alarm_severity):
enable_disable_beamline('G2', g2_line, value)
def receive_pif_update(value, status, alarm_severity):
enable_disable_beamline('PIF', pif_line, value)
self.gui_header.beam_current_wgt_dict[
"G3"].trigger_monitor_str.connect(receive_g3_update)
self.gui_header.beam_current_wgt_dict[
"O2"].trigger_monitor_str.connect(receive_o2_update)
self.gui_header.beam_current_wgt_dict[
"G2"].trigger_monitor_str.connect(receive_g2_update)
self.gui_header.beam_current_wgt_dict[
"PIF"].trigger_monitor_str.connect(receive_pif_update)
self.gui_header.beam_current_wgt_dict[
"SH"].trigger_monitor_str.connect(receive_sh_update)
self.gui_header.beam_current_wgt_dict[
"G1"].trigger_monitor_str.connect(receive_g1_update)
self.gui_header.beam_current_wgt_dict[
"MASTER"].trigger_monitor_str.connect(receive_master_update)
pvd=self.cafe.getPVCache(self.settings.data["G3"]["status"], dt='str')
receive_g3_update(pvd.value[0], pvd.alarmStatus, pvd.alarmSeverity)
pvd=self.cafe.getPVCache(self.settings.data["PIF"]["status"], dt='str')
receive_pif_update(pvd.value[0], pvd.alarmStatus, pvd.alarmSeverity)
pvd=self.cafe.getPVCache(self.settings.data["G2"]["status"], dt='str')
receive_g2_update(pvd.value[0], pvd.alarmStatus, pvd.alarmSeverity)
pvd=self.cafe.getPVCache(self.settings.data["O2"]["status"], dt='str')
receive_o2_update(pvd.value[0], pvd.alarmStatus, pvd.alarmSeverity)
pvd=self.cafe.getPVCache(self.settings.data["SH"]["status"], dt='str')
receive_sh_update(pvd.value[0], pvd.alarmStatus, pvd.alarmSeverity)
pvd=self.cafe.getPVCache(self.settings.data["G1"]["status"], dt='str')
receive_g1_update(pvd.value[0], pvd.alarmStatus, pvd.alarmSeverity)
pvd=self.cafe.getPVCache(self.settings.data["MASTER"]["status"], dt='str')
receive_master_update(pvd.value[0], pvd.alarmStatus, pvd.alarmSeverity)
def receive_sec_state(handle, pv, pvdata):
pvsplit = pv.split("-")
#secsplit = pvsplit[0].split("P")
#sec = secsplit[1]
sec=pvsplit[0][1:]
if pvdata.value[0] == 'ON':
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)
#print("sec", secsplit[1], flush=True)
for state in self.sec_state_list:
self.cafe.monitor(state, receive_sec_state)
def group_sector_status(self):
qgrid = QGridLayout()
#Connect all channels
#Heading
idx = self.settings.data["header"].index("G1")
idx_last = self.settings.data["header"].index("MASTER")
#Sector
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)
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)
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)
a.setContentsMargins(2, 0, 0, 0)
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
#for column_no in range(0, 5):
# qgrid.itemAtPosition(1, column_no).widget().setStyleSheet("QWidget { background: lightblue; }") #addStyleName(
#item = qgrid.itemAt(2) #.widget().setStyleSheet("QLabel { background-color: green }")
#item.widget().setStyleSheet("background-color: green") #widgets on grid from left to right starting at top rtow
return qw
def sector_status(self, sector):
'''Create each sector line for inclusion into group
'''
#device = "SEC-" + sector
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])
_color_str = "color : {0};".format(_color)
_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"
elif ", " in _delta:
_split = _delta.split(", ")
if len(_split) == 2:
if len(_split[1]) == len("0:00:00"):
_delta = _split[0] + ", " + _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
now = QDateTime.currentDateTime()
xdate = QDate(now.date().year(), 1, 15)
xstart = QDateTime(xdate)
qpinit = CAQLineEdit(self, pv_name=pv_pwr_last, show_units=False)
qpnow = CAQLineEdit(self, pv_name=pv_pwr_tot, show_units=False)
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)
#qtdis = QBasicTimer()
#qpnow.setAlignment(Qt.AlignRight)
#qpnow.style().polish(qpnow)
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]:
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()
sector_wgt_dict = {}
for sector in self.settings.data["header"][idx:idx_last]:
sector_wgt_dict[sector] = self.ca_table_sector_widget(sector=sector)
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]):
sector_tab_widget.addTab(sector_wgt_dict[sector], sector)
color = self.settings.data[sector]["color"]
sector_tab_widget.tabBar().setTabTextColor(i, QColor(color))
#sector_tab_widget.addTab(sector_wgt_dict["INJ2"], "RF")
#color = self.settings.data["INJ2"]["color"]
#sector_tab_widget.tabBar().setTabTextColor(
# len(self.settings.data["header"][idx:]), QColor(color))
return sector_tab_widget
'''
def check_status_list(self, pv_list, status_list, line):
_brk = ("------------------------------------------------------" +
"------------------------------------------------------")
self.parent.trigger_log_message.emit(
MsgSeverity.INFO.name, _pymodule, line, _brk, {})
_options = {}
for pv, stat in zip(pv_list, status_list):
if stat != self.cyca.ICAFE_NORMAL:
_mess = ("Error in 'set' for " + pv + " ")
_options['statusCode'] = (
str(stat) + " " +
self.cafe.getStatusCodeAsString(stat))
_options['statusInfo'] = self.cafe.getStatusInfo(stat)
self.parent.trigger_log_message.emit(
MsgSeverity.WARN.name, _pymodule, line, _mess, _options)
self.parent.trigger_log_message.emit(
MsgSeverity.INFO.name, _pymodule, line, _brk, {})
_mess = ("The following devices reported an error " +
"in 'set' operation:")
self.parent.trigger_log_message.emit(
MsgSeverity.INFO.name, _pymodule, line, _mess, {})
def check_status(self, pv, stat, line):
if stat != self.cyca.ICAFE_NORMAL:
_mess = ("Error in 'set' for " + pv + ".")
_options = {}
_options['statusCode'] = (
str(stat) + " " +
self.cafe.getStatusCodeAsString(stat))
_options['statusInfo'] = self.cafe.getStatusInfo(
stat)
self.parent.trigger_log_message.emit(
MsgSeverity.WARN.name, _pymodule, line,
_mess, _options)
'''
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
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!!
if is_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())
pv = 'P' + target.sector + "-HUSH:STATE"
stat = self.cafe.set(pv, 0)
self.check_status(_pymodule, 'set', pv, stat, _line())
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())
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="", color: str="MACHINE"):
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 as ex:
print("On Standby values not given for sector {0}".format(sector))
pv_dict = {}
for att in attribute_list:
pv_dict[att] = [] #[None] * len(device_list)
for dev in device_list:
pv_dict[att].append(dev + ":" + att)
_table_height = 700
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=2,
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=0,
suffix = "kW",
notify_unison=False, 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)
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)
pvStatus = self.settings.data[sector]['status']
beamline_status = self.cafe.getCache(pvStatus)
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"
_sum = sum(table_pwr.get_init_values().values())
print("SUM up all the values", pv, _sum, flush=True)
stat = self.cafe.set(pv, _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" +
"Please be sure that the present accounting figures are entered \n" +
"into the log book before initiating this action. \n\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'] = "Info"
attributes['Effekt'] = '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)
qgrid = QGridLayout()
qgrid.addWidget(qpb, 0, 0, 1, 1)
qw = QGroupBox("HUSH! Accounting")
qw.setContentsMargins(5, 10, 5, 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_state = [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 = QWidget()
qw.setLayout(qgrid)
qw.setFixedHeight(260)
qw.setFixedWidth(400)
'''
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