1005 lines
40 KiB
Python
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
|