5 Commits

Author SHA1 Message Date
71bcf8c7df merge 2023-02-21 14:55:46 +01:00
6994394da4 update from pyacc 2023-02-21 14:43:41 +01:00
64ce267c84 qradiobutton now excepts default value 2022-10-28 11:05:25 +02:00
cd289303a6 qradiobutton now excepts default value 2022-10-28 10:59:28 +02:00
87def4961c sendelogsls.py uses bdbase.sendelogframe.py 2022-10-24 08:12:47 +02:00
4 changed files with 613 additions and 64 deletions

52
base.py
View File

@@ -5,6 +5,7 @@ from collections import OrderedDict
from datetime import datetime from datetime import datetime
import getpass import getpass
import h5py import h5py
import logging
import inspect import inspect
import platform import platform
import os import os
@@ -30,6 +31,8 @@ from pyqtacc.bdbase.readjson import ReadJSON
from pyqtacc.bdbase.savehdf import QSaveHDF from pyqtacc.bdbase.savehdf import QSaveHDF
from pyqtacc.bdbase.hdf5filemenu import HDF5GroupBox from pyqtacc.bdbase.hdf5filemenu import HDF5GroupBox
from pyqtacc.bdbase.sendelog import QSendToELOG from pyqtacc.bdbase.sendelog import QSendToELOG
from pyqtacc.bdbase.screenshot import QScreenshot from pyqtacc.bdbase.screenshot import QScreenshot
from pyqtacc.bdbase.guiframe import GUIFrame from pyqtacc.bdbase.guiframe import GUIFrame
@@ -317,7 +320,7 @@ class BaseWindow(QMainWindow):
def __init__(self, parent=None, pymodule=None, appversion=None, title="", def __init__(self, parent=None, pymodule=None, appversion=None, title="",
user_mode=UserMode.OPERATION, facility=Facility.SwissFEL, user_mode=UserMode.OPERATION, facility=Facility.SwissFEL,
extended=True, has_optics=True): extended=True, has_optics=True, has_procedure=True):
super(BaseWindow, self).__init__(parent) super(BaseWindow, self).__init__(parent)
self.parent = parent self.parent = parent
@@ -331,7 +334,8 @@ class BaseWindow(QMainWindow):
self.facility = facility self.facility = facility
self.user_mode = user_mode self.user_mode = user_mode
self.appname, self.appext = self.pymodule.split(".") self.appname, self.appext = self.pymodule.split(".")
print("=============================================") print("=============================================")
print("Starting {0} at: {1}".format(self.appname, datetime.now())) print("Starting {0} at: {1}".format(self.appname, datetime.now()))
print("User: {0} Host: {1}".format(os.getlogin(), os.uname()[1])) print("User: {0} Host: {1}".format(os.getlogin(), os.uname()[1]))
@@ -340,6 +344,8 @@ class BaseWindow(QMainWindow):
self.settings = ReadJSON(self.appname) self.settings = ReadJSON(self.appname)
#Read out current_logbook
self.cafe = PyCafe.CyCafe() self.cafe = PyCafe.CyCafe()
self.cyca = PyCafe.CyCa() self.cyca = PyCafe.CyCa()
self.cafe_exception = PyCafe.CafeException self.cafe_exception = PyCafe.CafeException
@@ -390,6 +396,12 @@ class BaseWindow(QMainWindow):
self.stdlog_dest = (self.settings.data["stdlog"]["destination"] + self.stdlog_dest = (self.settings.data["stdlog"]["destination"] +
self.appname + "-" + os.getlogin() + ".log") self.appname + "-" + os.getlogin() + ".log")
self.logging = logging
#self.logging.basicConfig(filename=self.stdlog_dest, level=logging.DEBUG)
self.logging.basicConfig(level=logging.DEBUG)
self.logger = self.logging.getLogger(__name__)
self.logger.info("Logging activated")
self.date_str = None self.date_str = None
self.autopost_elog = True self.autopost_elog = True
@@ -492,14 +504,18 @@ class BaseWindow(QMainWindow):
if self.facility == Facility.SwissFEL: if self.facility == Facility.SwissFEL:
from pyqtacc.sf.guiheader import GUIHeader from pyqtacc.sf.guiheader import GUIHeader
from pyqtacc.bdbase.sendelog import QSendToELOG
elif self.facility == Facility.SLS: elif self.facility == Facility.SLS:
from pyqtacc.sls.guiheader import GUIHeader from pyqtacc.sls.guiheader import GUIHeader
from pyqtacc.sls.sendelogsls import QSendToELOG
self.gui_header = GUIHeader(self, user_mode=self.user_mode, self.gui_header = GUIHeader(self, user_mode=self.user_mode,
extended=extended) extended=extended)
self.mainwindow_layout.addWidget(self.gui_header.header_wgt) self.mainwindow_layout.addWidget(self.gui_header.header_wgt)
self.gui_frame = GUIFrame(self, has_optics=self.has_optics) self.gui_frame = GUIFrame(self, has_optics=self.has_optics,
has_procedure=has_procedure)
self.show_log_message = self.gui_frame.show_log_message self.show_log_message = self.gui_frame.show_log_message
if self.autopost_hdf: if self.autopost_hdf:
@@ -553,7 +569,7 @@ class BaseWindow(QMainWindow):
if self.settings.data["Parameters"][key]["flag"]: if self.settings.data["Parameters"][key]["flag"]:
self.input_parameters[key] = val self.input_parameters[key] = val
self.all_input_parameters[key] = val self.all_input_parameters[key] = val
#print("val=",val, key) #print("val=",val, key)
except KeyError as e: except KeyError as e:
@@ -599,8 +615,8 @@ class BaseWindow(QMainWindow):
if self.settings.data["Expert"][key]["flag"]: if self.settings.data["Expert"][key]["flag"]:
self.expert_parameters[key] = val self.expert_parameters[key] = val
self.all_expert_parameters[key] = val self.all_expert_parameters[key] = val
#print("val=",val, key) #print("val=",val, key)
except KeyError as e: except KeyError as e:
print("Key Error in base.py initialization:", e) print("Key Error in base.py initialization:", e)
@@ -841,7 +857,7 @@ class BaseWindow(QMainWindow):
""" """
#Close all dock widgets #Close all dock widgets
#self.removeDockWidget(self.hdf_dock_widget) #self.removeDockWidget(self.hdf_dock_widget)
self.logger.info("Closing Application")
self.save_application_settings() self.save_application_settings()
QApplication.processEvents() QApplication.processEvents()
self.cafe.monitorStopAll() self.cafe.monitorStopAll()
@@ -1177,6 +1193,7 @@ class BaseWindow(QMainWindow):
#print("filename", self.hdf_filename) #print("filename", self.hdf_filename)
def verify_send_to_elog(self): def verify_send_to_elog(self):
if self.analysis_thread is not None: if self.analysis_thread is not None:
if self.analysis_thread.isRunning(): if self.analysis_thread.isRunning():
_mess = ("Measurement in progress. " + _mess = ("Measurement in progress. " +
@@ -1210,6 +1227,9 @@ class BaseWindow(QMainWindow):
def send_to_elog(self): def send_to_elog(self):
""" Response to elog_action; normally overwritten """ Response to elog_action; normally overwritten
""" """
if not self.verify_send_to_elog():
return
'''
if self.analysis_thread is not None: if self.analysis_thread is not None:
if self.analysis_thread.isRunning(): if self.analysis_thread.isRunning():
_mess = ("Measurement in progress. " + _mess = ("Measurement in progress. " +
@@ -1218,6 +1238,7 @@ class BaseWindow(QMainWindow):
QMessageBox.Ok) QMessageBox.Ok)
return return
'''
#_elog_sf = ElogSwissFEL() #_elog_sf = ElogSwissFEL()
_logbook = None _logbook = None
@@ -1227,6 +1248,7 @@ class BaseWindow(QMainWindow):
_attach_files = [] _attach_files = []
_message = "" _message = ""
QSendToELOG(self, logbook=_logbook, categoryIdx=_category_idx, QSendToELOG(self, logbook=_logbook, categoryIdx=_category_idx,
domainIdx=_domain_idx, sectionIdx=_section_idx, domainIdx=_domain_idx, sectionIdx=_section_idx,
title=self.title, message=_message, title=self.title, message=_message,
@@ -1716,18 +1738,26 @@ class BaseWindow(QMainWindow):
@Slot(dict) @Slot(dict)
def receive_analysis_results(self, all_dict): def receive_analysis_results(self, all_dict):
print("receive analysis results===>")
self.all_data = all_dict self.all_data = all_dict
self.gui_frame.canvas_update(all_dict['Figure data']) self.gui_frame.canvas_update(all_dict['Figure data'])
print("here")
if self.gui_frame.results_output_wgt_dict:
#all_dict['Processed data']['Results']={}
#all_dict['Processed data']['Results']['mean'] = 123.23
#all_dict['Processed data']['Results']['SD'] = 0.23
try:
results_data = all_dict['Processed data']['Results']
self.gui_frame.send_to_results_output_wgt(results_data)
except:
pass
self.gui_frame.central_tab_widget.setCurrentIndex(1) self.gui_frame.central_tab_widget.setCurrentIndex(1)
self.gui_frame.results_tab_wgt.setCurrentIndex(0) self.gui_frame.results_tab_wgt.setCurrentIndex(0)
@Slot() @Slot()
def receive_abort_analysis(self): def receive_abort_analysis(self):
"""Instantiate action on abort """Instantiate action on abort
""" """
print("Aborting", flush=True)
if self.analysis_procedure.abort: if self.analysis_procedure.abort:
return return
self.gui_frame.in_abort_procedure() self.gui_frame.in_abort_procedure()

View File

@@ -18,6 +18,7 @@ class Facility(IntEnum):
PSI = 0 PSI = 0
SwissFEL = 1 SwissFEL = 1
SLS = 2 SLS = 2
HIPA = 3
class MsgSeverity(IntEnum): class MsgSeverity(IntEnum):
""" For use with message logger """ For use with message logger

View File

@@ -17,7 +17,7 @@ from qtpy.QtWidgets import (QCheckBox, QComboBox, QDoubleSpinBox, QFrame,
QStackedWidget, QTabBar, QTabWidget, QToolButton, QStackedWidget, QTabBar, QTabWidget, QToolButton,
QVBoxLayout, QWidget) QVBoxLayout, QWidget)
from caqtwidgets.pvwidgets import (CAQLabel, CAQTableWidget, QMessageWidget, from caqtwidgets.pvwidgets import (CAQLabel, CAQTableWidget, QMessageWidget,
QHLine) QHLine, QVLine)
from pyqtacc.bdbase.enumkind import Facility, MsgSeverity, UserMode from pyqtacc.bdbase.enumkind import Facility, MsgSeverity, UserMode
@@ -42,11 +42,12 @@ def _line():
class GUIFrame(QWidget): class GUIFrame(QWidget):
""" GUI Class """ GUI Class
""" """
def __init__(self, parent, has_optics=True): def __init__(self, parent, has_optics=True, has_procedure=True):
#super(GUIFrame, self).__init__() #super(GUIFrame, self).__init__()
super().__init__() super().__init__()
self.parent = parent self.parent = parent
self.has_optics = has_optics self.has_optics = has_optics
self.has_procedure = has_procedure
self.appname = parent.appname self.appname = parent.appname
self.facility = parent.facility self.facility = parent.facility
self.settings = parent.settings self.settings = parent.settings
@@ -61,6 +62,8 @@ class GUIFrame(QWidget):
self.all_expert_parameters = parent.all_expert_parameters self.all_expert_parameters = parent.all_expert_parameters
self.all_expert_labels = parent.all_expert_labels self.all_expert_labels = parent.all_expert_labels
self.results_output_wgt_dict = {}
try: try:
self.widget_height = self.settings.data["StyleGuide"][ self.widget_height = self.settings.data["StyleGuide"][
"widgetHeight"] "widgetHeight"]
@@ -75,6 +78,7 @@ class GUIFrame(QWidget):
self.expert_parameters_group = None self.expert_parameters_group = None
self.operator_parameters_group = None self.operator_parameters_group = None
self.output_parameters_wgt = None
self.optics_group = None self.optics_group = None
self.energy_stacked_widget = None self.energy_stacked_widget = None
@@ -268,6 +272,76 @@ class GUIFrame(QWidget):
self.optics_group.cycle_quads = None self.optics_group.cycle_quads = None
return self.optics_group return self.optics_group
def output_parameters_group(self, title="Results Output"):
""" Generic group box for user supplied input
"""
self.output_parameters_wgt = QWidget()
qtop = QVBoxLayout()
self.output_parameters_group_box = QGroupBox(title)
self.output_parameters_group_box.setObjectName("OUTER")
vbox = QVBoxLayout()
vbox.setContentsMargins(9, 19, 9, 9)
vbox.setAlignment(Qt.AlignTop | Qt.AlignHCenter)
keys = self.settings.data["Results"].keys()
max_str_len = 4
for key in keys:
if len(key) > max_str_len:
max_str_len = len(key)
for key in keys:
ikey = self.settings.data["Results"][key]
if ikey['flag']:
_widget = ikey["data"]["widget"].upper()
_text = ikey["data"]["text"]
_value = str(ikey["data"]["value"])
_width = int(ikey["data"]["width"])
if _widget == "QLINEEDIT":
ql = QLabel(str(_text))
_label_width = (ql.fontMetrics().averageCharWidth() *
max_str_len+2)
ql.setMinimumWidth(_label_width)
ql.setFixedHeight(self.widget_height)
ql.setFont(self.font_pts10)
wgt = QLineEdit()
wgt.setFixedWidth(_width)
wgt.setObjectName("ReadRight")
wgt.setFixedHeight(self.widget_height)
wgt.setFont(self.font_pts10)
wgt.setAlignment(Qt.AlignRight)
self.results_output_wgt_dict[key] = wgt
if "NONE" not in _value.upper():
self.results_output_wgt_dict[key].setText(_value)
hbox = QHBoxLayout()
hbox.setContentsMargins(0, 0, 0, 0)
hbox.addWidget(ql)
hbox.addWidget(wgt)
hbox.setAlignment(Qt.AlignLeft)
vbox.addLayout(hbox)
self.output_parameters_group_box.setContentsMargins(9, 19, 9, 9)
self.output_parameters_group_box.setMinimumWidth(140)
self.output_parameters_group_box.setMaximumWidth(300)
#self.output_parameters_group_box.setMaximumHeight(400)
self.output_parameters_group_box.setFont(self.font_gui)
self.output_parameters_group_box.setAlignment(Qt.AlignTop |
Qt.AlignHCenter)
qf = QFrame()
qf.setFixedHeight(35)
self.output_parameters_group_box.setLayout(vbox)
qtop.addWidget(qf)
qtop.addWidget(self.output_parameters_group_box)
self.output_parameters_wgt.setLayout(qtop)
return self.output_parameters_wgt
def send_to_results_output_wgt(self, results_data):
for key, value in results_data.items():
self.results_output_wgt_dict[key].setText(str(value))
def input_parameters_group(self, title="Input Parameters"): def input_parameters_group(self, title="Input Parameters"):
""" Generic group box for user supplied input """ Generic group box for user supplied input
""" """
@@ -309,11 +383,12 @@ class GUIFrame(QWidget):
#print(self.input_parameters) #print(self.input_parameters)
checkbox = QCheckBox(text) checkbox = QCheckBox(text)
checkbox.setToolTip(tip) checkbox.setToolTip(tip)
checkbox.setFont(self.font_gui) checkbox.setFont(self.font_gui)
checkbox.stateChanged.connect(on_checkbox_change) checkbox.stateChanged.connect(on_checkbox_change)
#checkbox.setFixedHeight(30) #checkbox.setFixedHeight(30)
#checkbox.setLayoutDirection(Qt.RightToLeft)
checked_value = default_value checked_value = default_value
if key in self.parent.input_parameters.keys(): if key in self.parent.input_parameters.keys():
if "data" in self.settings.data[top_key][key].keys(): if "data" in self.settings.data[top_key][key].keys():
@@ -324,16 +399,18 @@ class GUIFrame(QWidget):
checked_value = Qt.Unchecked checked_value = Qt.Unchecked
checkbox.setCheckState(checked_value) checkbox.setCheckState(checked_value)
checkbox.stateChanged.emit(checked_value)
return checkbox return checkbox
def create_label_qdoublespinbox(self, key, label="", min_val=0, max_val=1, def create_label_qdoublespinbox(self, key, label="", min_val=0, max_val=1,
step=0.1, start_val=0.5): step=0.1, start_val=0.5, digits=1):
""" Generic QDoubleSpinbox with buddy label """ Generic QDoubleSpinbox with buddy label
""" """
def callback(value): def callback(value):
self.input_parameters[key] = value self.input_parameters[key] = round(value, digits)
widget_height = 24 widget_height = 24
suggested = "WWW" suggested = "WWW"
@@ -355,6 +432,7 @@ class GUIFrame(QWidget):
wgt.setMaximumWidth(param_width + 40) wgt.setMaximumWidth(param_width + 40)
wgt.valueChanged.connect(callback) wgt.valueChanged.connect(callback)
wgt.setValue(start_val) wgt.setValue(start_val)
wgt.valueChanged.emit(start_val)
return lab, wgt return lab, wgt
@@ -366,6 +444,7 @@ class GUIFrame(QWidget):
def cb(value): def cb(value):
self.input_parameters[key] = value self.input_parameters[key] = value
widget_height = 24 widget_height = 24
suggested = "WWW" suggested = "WWW"
lab = QLabel(label) lab = QLabel(label)
@@ -385,15 +464,17 @@ class GUIFrame(QWidget):
wgt.setMaximumWidth(param_width + 40) wgt.setMaximumWidth(param_width + 40)
wgt.valueChanged.connect(cb) wgt.valueChanged.connect(cb)
wgt.setValue(start_val) wgt.setValue(start_val)
wgt.valueChanged.emit(start_val)
return lab, wgt return lab, wgt
def create_label_qcombobox(self, key, label="", values: list = []): def create_label_qcombobox(self, key, label="", values: list = [], start_val: str =""):
""" Generic QCombobox with buddy label """ Generic QCombobox with buddy label
""" """
def cb(new_text): def cb(new_text):
self.input_parameters[key] = new_text self.input_parameters[key] = new_text
print( self.input_parameters)
widget_height = 26 widget_height = 26
suggested = "WWW" suggested = "WWW"
@@ -410,8 +491,11 @@ class GUIFrame(QWidget):
wgt.setFont(self.font_pts10) wgt.setFont(self.font_pts10)
wgt.setContentsMargins(5, 0, 0, 0) wgt.setContentsMargins(5, 0, 0, 0)
wgt.currentTextChanged.connect(cb) wgt.currentTextChanged.connect(cb)
wgt.setCurrentIndex(0)
wgt.currentTextChanged.emit(values[0]) start_idx = wgt.findText(start_val)
start_idx = start_idx if start_idx > 0 else 0
wgt.setCurrentIndex(start_idx)
wgt.currentTextChanged.emit(values[start_idx])
value_for_width = max(values, key=len) value_for_width = max(values, key=len)
@@ -419,23 +503,33 @@ class GUIFrame(QWidget):
param_width = max(fm.width(str(value_for_width)), fm.width(suggested)) param_width = max(fm.width(str(value_for_width)), fm.width(suggested))
wgt.setFixedWidth(param_width + 50) wgt.setFixedWidth(param_width + 50)
return lab, wgt return lab, wgt
def image_parameters_group(self): def image_parameters_group(self):
group_box = QGroupBox("Image Pipeline Parameters") group_box = QGroupBox("Image Pipeline Expert")
box = QHBoxLayout() box = QHBoxLayout()
box.setSpacing(10) box.setSpacing(10)
try:
start_val_gr = self.settings.data["Expert"]["pipeline"]["data"]["goodRegion"]
start_val_gr = Qt.Checked if start_val_gr else Qt.Unchecked
except KeyError as ex:
start_val_gr = Qt.Unchecked
box.addWidget(self.create_checkbox( box.addWidget(self.create_checkbox(
top_key="Expert", key="goodRegion", text="Good region", top_key="Expert", key="goodRegion", text="Good region",
tip="Enables good region in pipeline", default_value=Qt.Checked)) tip="Enables good region in pipeline", default_value=start_val_gr))
try:
start_val_sub = self.settings.data["Expert"]["pipeline"]["data"]["subtractBackground"]
start_val_sub = Qt.Checked if start_val_sub else Qt.Unchecked
except KeyError as ex:
start_val_sub = Qt.Unchecked
box.addWidget(self.create_checkbox( box.addWidget(self.create_checkbox(
top_key="Expert", key="subtractBackground", top_key="Expert", key="subtractBackground",
text="Subtract bkgrnd", text="Subtract bkgrnd",
tip="Enables background subtraction in pipeline", tip="Enables background subtraction in pipeline",
default_value=Qt.Checked)) default_value=start_val_sub))
group_box.setAlignment(Qt.AlignCenter) group_box.setAlignment(Qt.AlignCenter)
group_box.setObjectName("INNERCENTER") group_box.setObjectName("INNERCENTER")
@@ -443,10 +537,20 @@ class GUIFrame(QWidget):
good_region = QGroupBox("Good Region") good_region = QGroupBox("Good Region")
good_region.setObjectName("INNER") good_region.setObjectName("INNER")
try:
start_val_grThreshold = self.settings.data["Expert"]["pipeline"]["data"]["grThreshold"]
except KeyError as ex:
start_val_grThreshold = 21
lab_thresh, thresh = self.create_label_qdoublespinbox( lab_thresh, thresh = self.create_label_qdoublespinbox(
key="grThreshold", label="Threshold:") key="grThreshold", label="Threshold:", start_val=start_val_grThreshold)
try:
start_val_grScale = self.settings.data["Expert"]["pipeline"]["data"]["grScale"]
except KeyError as ex:
start_val_grScale = 6
lab_gfscale, gfscale = self.create_label_qspinbox( lab_gfscale, gfscale = self.create_label_qspinbox(
key="grScale", label="Scale:") key="grScale", label="Scale:", start_val=start_val_grScale)
layout = QGridLayout() layout = QGridLayout()
layout.addWidget(lab_thresh, 0, 0) layout.addWidget(lab_thresh, 0, 0)
layout.addWidget(thresh, 0, 1) layout.addWidget(thresh, 0, 1)
@@ -457,13 +561,28 @@ class GUIFrame(QWidget):
slicing = QGroupBox("Slicing") slicing = QGroupBox("Slicing")
slicing.setObjectName("INNER") slicing.setObjectName("INNER")
try:
start_val_nslices = self.settings.data["Expert"]["pipeline"]["data"]["slices"]
except KeyError as ex:
start_val_nslices = 21
lab_slices, slices = self.create_label_qspinbox( lab_slices, slices = self.create_label_qspinbox(
key="slices", label="No. Slices:", start_val=21) key="slices", label="No. Slices:", start_val=start_val_nslices)
try:
start_val_slicing_scale = self.settings.data["Expert"]["pipeline"]["data"]["slicingScale"]
except KeyError as ex:
start_val_slicing_scale = 5
lab_scale, scale = self.create_label_qspinbox( lab_scale, scale = self.create_label_qspinbox(
key="slicingScale", label="Scale:") key="slicingScale", label="Scale:", start_val=start_val_slicing_scale)
try:
start_val_orientation = self.settings.data["Expert"]["pipeline"]["data"]["orientation"]
except KeyError as ex:
start_val_orientation = "vertical"
lab_orientation, self.slice_orientation = self.create_label_qcombobox( lab_orientation, self.slice_orientation = self.create_label_qcombobox(
key="orientation", label="Orientation:", key="orientation", label="Orientation:",
values=["vertical", "horizontal"]) values=["vertical", "horizontal"], start_val=start_val_orientation)
layout = QGridLayout() layout = QGridLayout()
@@ -564,6 +683,13 @@ class GUIFrame(QWidget):
for table in self.table_wgt: for table in self.table_wgt:
table.init_value_button.setEnabled(False) table.init_value_button.setEnabled(False)
table.restore_value_button.setEnabled(False) table.restore_value_button.setEnabled(False)
if self.output_parameters_wgt is not None:
for wgt in self.results_output_wgt_dict.values():
wgt.setText("")
#self.output_parameters_wg.setEnabled(False)
def in_abort_procedure(self): def in_abort_procedure(self):
self.abort_wgt.setEnabled(False) self.abort_wgt.setEnabled(False)
@@ -585,6 +711,8 @@ class GUIFrame(QWidget):
for table in self.table_wgt: for table in self.table_wgt:
table.init_value_button.setEnabled(True) table.init_value_button.setEnabled(True)
table.restore_value_button.setEnabled(True) table.restore_value_button.setEnabled(True)
#if self.output_parameters_wgt is not None:
# self.output_parameters_wgt.setEnabled(True)
def in_hdf_measurement_procedure(self): def in_hdf_measurement_procedure(self):
self.parent.h5_groupbox.analyze_h5_widget.setEnabled(False) self.parent.h5_groupbox.analyze_h5_widget.setEnabled(False)
@@ -748,7 +876,7 @@ class GUIFrame(QWidget):
except KeyError as error: except KeyError as error:
print(("KeyError in guiframe.py; Unknown key {0} " + print(("KeyError in guiframe.py; Unknown key {0} " +
"in def checkbox_wgt: {1}").format(key, error)) "in def checkbox_wgt: {1}").format(key, error))
text = key text = key
checkbox = QCheckBox(text) checkbox = QCheckBox(text)
checkbox.setToolTip(tooltip) checkbox.setToolTip(tooltip)
@@ -756,6 +884,7 @@ class GUIFrame(QWidget):
if object_name: if object_name:
checkbox.setObjectName(object_name) checkbox.setObjectName(object_name)
checkbox.setLayoutDirection(Qt.LeftToRight) #is default
checkbox.stateChanged.connect(on_change) checkbox.stateChanged.connect(on_change)
checked_value = Qt.Unchecked checked_value = Qt.Unchecked
@@ -1007,7 +1136,7 @@ class GUIFrame(QWidget):
stack.style().polish(stack) stack.style().polish(stack)
stacked_widget.addWidget(stack) stacked_widget.addWidget(stack)
stacked_widget.setMaximumHeight(320) stacked_widget.setMaximumHeight(320)
self.stacked_wgt_dict[stacked_widget] = stack_list self.stacked_wgt_dict[stacked_widget] = stack_list
return stacked_widget return stacked_widget
@@ -1291,7 +1420,7 @@ class GUIFrame(QWidget):
radio_button = self.sender() radio_button = self.sender()
if radio_button.isChecked(): if radio_button.isChecked():
self.parent.input_parameters[key] = radio_button.target self.parent.input_parameters[key] = radio_button.target
print("KEY================", key, self.parent.input_parameters[key], new_value) #print("KEY================", key, self.parent.input_parameters[key], new_value)
if key in self.settings.data["Expert"].keys(): if key in self.settings.data["Expert"].keys():
top_key = "Expert" top_key = "Expert"
@@ -1319,6 +1448,8 @@ class GUIFrame(QWidget):
self.line_sender_dict[item].setText(str(value_list)) self.line_sender_dict[item].setText(str(value_list))
line = self.radio_buttons(key=key, options=value) line = self.radio_buttons(key=key, options=value)
line.setContentsMargins(0, 0, 0, 0)
rblist = line.findChildren(QRadioButton) rblist = line.findChildren(QRadioButton)
for rb in rblist: for rb in rblist:
@@ -1326,9 +1457,24 @@ class GUIFrame(QWidget):
wgt_grid.addWidget(line, irow, 0, 1, 4, Qt.AlignLeft) wgt_grid.addWidget(line, irow, 0, 1, 4, Qt.AlignLeft)
rblist[0].setChecked(True) _idx=0
rblist[0].toggled.emit(True)
try:
if key in self.settings.data["Expert"].keys():
top_key = "Expert"
elif key in self.settings.data["Parameters"].keys():
top_key = "Parameters"
_choice =self.settings.data[top_key][key]['data']['default']
_values = self.settings.data[top_key][key]['data']['value']
if isinstance(_choice, (str, bytes)):
_idx = _values.index(_choice)
elif isinstance(_choice, int):
_idx = _choice if _choice < len(_values) else 0
except KeyError:
pass
rblist[_idx].setChecked(True)
rblist[_idx].toggled.emit(True)
return line return line
@@ -1340,10 +1486,26 @@ class GUIFrame(QWidget):
line.setChecked(Qt.Checked if value else Qt.Unchecked) line.setChecked(Qt.Checked if value else Qt.Unchecked)
line.stateChanged.connect(check_cb) line.stateChanged.connect(check_cb)
line.setMaximumWidth(320) line.setMaximumWidth(320)
line.setMinimumWidth(220) line.setMinimumWidth(100)
line.setFixedHeight(28) line.setFixedHeight(28)
if key in self.settings.data["Expert"].keys():
top_key = "Expert"
elif key in self.settings.data["Parameters"].keys():
top_key = "Parameters"
wgt_grid.addWidget(line, irow, 0, 1, 4, Qt.AlignLeft | Qt.AlignVCenter) col_wdt = 4
try:
orientation = self.settings.data[top_key][key]["data"]["orientation"]
orientation = Qt.RightToLeft if "RightToLeft" in orientation \
else Qt.LeftToRight
line.setLayoutDirection(orientation)
col_wdt=3
except KeyError:
pass
wgt_grid.addWidget(line, irow, 0, 1, col_wdt, Qt.AlignLeft | Qt.AlignVCenter)
return line return line
@@ -1362,22 +1524,27 @@ class GUIFrame(QWidget):
return line return line
def input_wgt_qlineread(self, value, label, irow, wgt_grid): def input_wgt_qlineread(self, key, value, label, irow, wgt_grid):
#Read only has no callback def line_cb(new_value):
self.parent.input_parameters[key] = new_value
suggested = "WW" suggested = "WW"
line = QLineEdit() line = QLineEdit()
line.setObjectName("Read") line.setObjectName("Read")
line.setText(str(value)) #"{0: 3.1f}".format(value)) line.setText(str(value)) #"{0: 3.1f}".format(value))
line.setFixedHeight(24) line.setFixedHeight(24)
line.textChanged.connect(line_cb)
line.setAlignment(Qt.AlignRight | Qt.AlignBottom) line.setAlignment(Qt.AlignRight | Qt.AlignBottom)
line.setStyleSheet("QLabel{text-align: right}") line.setStyleSheet("QLabel{text-align: right}")
fm = QFontMetricsF(line.font()) fm = QFontMetricsF(line.font())
param_width = max(fm.width(str(value)), fm.width(suggested)) param_width = max(fm.width(str(value)), fm.width(suggested))
line.setMaximumWidth(param_width + 24) extra_width = 22 if len(str(value)) < 16 else 26
line.setFixedWidth(param_width + extra_width)
wgt_grid.addWidget(label, irow, 0, 1, 2, Qt.AlignLeft | Qt.AlignVCenter) qframe_buffer = QFrame()
wgt_grid.addWidget(line, irow, 2, 1, 2, Qt.AlignLeft | Qt.AlignVCenter) qframe_buffer.setFixedWidth(3)
wgt_grid.addWidget(label, irow, 0, 1, 1, Qt.AlignLeft | Qt.AlignVCenter)
wgt_grid.addWidget(qframe_buffer, irow, 1, 1, 1, Qt.AlignLeft | Qt.AlignVCenter)
wgt_grid.addWidget(line, irow, 2, 1, 1, Qt.AlignLeft | Qt.AlignVCenter)
return line return line
def input_wgt_qlineedit(self, key, value, label, irow, wgt_grid): def input_wgt_qlineedit(self, key, value, label, irow, wgt_grid):
@@ -1386,13 +1553,15 @@ class GUIFrame(QWidget):
suggested = "WW" suggested = "WW"
line = QLineEdit() line = QLineEdit()
line.setObjectName("Write") line.setObjectName("Write")
line.setFixedHeight(24) line.setFixedHeight(24)
line.textEdited.connect(line_cb) line.textEdited.connect(line_cb)
line.setText(str(value)) line.setText(str(value))
fm = QFontMetricsF(line.font()) fm = QFontMetricsF(line.font())
param_width = max(fm.width(str(value)), fm.width(suggested)) param_width = max(fm.width(str(value)), fm.width(suggested))
line.setMaximumWidth(param_width + 20) extra_width = 22 if len(str(value)) < 16 else 26
line.setFixedWidth(param_width + extra_width)
wgt_grid.addWidget(label, irow, 0, 1, 2, Qt.AlignLeft | Qt.AlignVCenter) wgt_grid.addWidget(label, irow, 0, 1, 2, Qt.AlignLeft | Qt.AlignVCenter)
wgt_grid.addWidget(line, irow, 2, 1, 2, Qt.AlignLeft | Qt.AlignVCenter) wgt_grid.addWidget(line, irow, 2, 1, 2, Qt.AlignLeft | Qt.AlignVCenter)
@@ -1459,22 +1628,30 @@ class GUIFrame(QWidget):
return line return line
def input_wgt_qenergystacked(self, irow, wgt_grid): def input_wgt_qenergystacked(self, irow, wgt_grid):
qFrame = QFrame() qframe_top = QFrame()
qFrame.setFixedHeight(10) qframe_top.setFixedHeight(3)
line = self.pv_energy_stacked_wgt() stacked_wgt = self.pv_energy_stacked_wgt()
wgt_grid.addWidget(qFrame, irow, 0, 1, 4) qframe_bottom = QFrame()
wgt_grid.addWidget(line, irow+1, 0, 1, 4) qframe_bottom.setFixedHeight(3)
return line wgt_grid.addWidget(qframe_top, irow, 0, 1, 4)
wgt_grid.addWidget(stacked_wgt, irow+1, 0, 1, 4)
wgt_grid.addWidget(qframe_bottom, irow+2, 0, 1, 4)
return stacked_wgt
def input_wgt_qphasestacked(self, irow, wgt_grid): def input_wgt_qphasestacked(self, irow, wgt_grid):
qFrame = QFrame() qframe_top = QFrame()
qFrame.setFixedHeight(10) qframe_top.setFixedHeight(3)
line = self.pv_phase_stacked_wgt() stacked_wgt = self.pv_phase_stacked_wgt()
wgt_grid.addWidget(qFrame, irow, 0, 1, 4) qframe_bottom = QFrame()
wgt_grid.addWidget(line, irow+1, 0, 1, 4) qframe_bottom.setFixedHeight(3)
return line wgt_grid.addWidget(qframe_top, irow, 0, 1, 4)
wgt_grid.addWidget(stacked_wgt, irow+1, 0, 1, 4)
wgt_grid.addWidget(qframe_bottom, irow+2, 0, 1, 4)
return stacked_wgt
def input_wgt_qhline(self, irow, wgt_grid): def input_wgt_qhline(self, irow, wgt_grid):
qHLine = QHLine() qHLine = QHLine()
@@ -1488,7 +1665,13 @@ class GUIFrame(QWidget):
wgt_grid.addWidget(qFrame, irow, 0, 1, 4) wgt_grid.addWidget(qFrame, irow, 0, 1, 4)
def input_wgt(self, buddy, label, key, value, irow=0, wgt_grid=None): def input_wgt(self, buddy, label, key, value, irow=0, wgt_grid=None,):
if "QVLINE" in buddy:
print("QVLine", label, key, value)
if "QVLINE" in buddy:
print("QVLine", label, key, value)
if wgt_grid is None: if wgt_grid is None:
wgt_grid = self.input_wgt_grid wgt_grid = self.input_wgt_grid
@@ -1515,7 +1698,7 @@ class GUIFrame(QWidget):
line = self.input_wgt_qlabel(value, irow, wgt_grid) line = self.input_wgt_qlabel(value, irow, wgt_grid)
elif buddy == "QLineRead".upper(): elif buddy == "QLineRead".upper():
line = self.input_wgt_qlineread(value, label, irow, wgt_grid) line = self.input_wgt_qlineread(key, value, label, irow, wgt_grid)
elif buddy == "QDoubleSpinBox".upper(): elif buddy == "QDoubleSpinBox".upper():
line = self.input_wgt_qdoublespinbox(key, value, label, irow, line = self.input_wgt_qdoublespinbox(key, value, label, irow,
@@ -1581,12 +1764,21 @@ class GUIFrame(QWidget):
except KeyError: except KeyError:
pass pass
def draw_widget(buddy):
flag = self.settings.data["Parameters"][key]["flag"]
if buddy == "NONE":
return False
elif buddy not in ["QHLINE", "QFRAME"] and not flag:
return False
return True
for (key, val), label in zip(self.all_input_parameters.items(), for (key, val), label in zip(self.all_input_parameters.items(),
self.all_input_labels.values()): self.all_input_labels.values()):
buddy = self.settings.data[ buddy = self.settings.data[
"Parameters"][key]["data"]["widget"].upper() "Parameters"][key]["data"]["widget"].upper()
j = self.input_wgt_grid.rowCount() j = self.input_wgt_grid.rowCount()
if buddy != "NONE": #if buddy != "NONE":
if draw_widget(buddy):
self.input_wgt(buddy=buddy, label=label, key=key, value=val, self.input_wgt(buddy=buddy, label=label, key=key, value=val,
irow=j, wgt_grid=self.input_wgt_grid) irow=j, wgt_grid=self.input_wgt_grid)
@@ -1605,7 +1797,9 @@ class GUIFrame(QWidget):
row_count = 1 row_count = 1
else: else:
row_count = 0 row_count = 0
lo.addWidget(self.analysis_procedure_group(), row_count, 1)
if self.has_procedure:
lo.addWidget(self.analysis_procedure_group(), row_count, 1)
#Centers input parameters group box #Centers input parameters group box
@@ -1666,7 +1860,7 @@ class GUIFrame(QWidget):
self.expert_parameters_group.layout().addWidget( self.expert_parameters_group.layout().addWidget(
self.checkbox_keepImages()) self.checkbox_keepImages())
self.expert_parameters_group.layout().addWidget(QHLine()) ##self.expert_parameters_group.layout().addWidget(QHLine())
hbox2 = QHBoxLayout() hbox2 = QHBoxLayout()
hbox2.addWidget(self.checkbox_debug(hline="None")) hbox2.addWidget(self.checkbox_debug(hline="None"))
@@ -1697,7 +1891,7 @@ class GUIFrame(QWidget):
widget = QWidget() widget = QWidget()
layout = QGridLayout() layout = QGridLayout()
layout.setContentsMargins(5, 0, 5, 0) layout.setContentsMargins(5, 0, 5, 0)
widget.setFixedWidth(220) widget.setMaximumWidth(220)
#self.setLayout(layout) #self.setLayout(layout)
target_list = options target_list = options
@@ -1715,7 +1909,7 @@ class GUIFrame(QWidget):
elif key in self.settings.data["Parameters"].keys(): elif key in self.settings.data["Parameters"].keys():
top_key = "Parameters" top_key = "Parameters"
_width = 1 _width = 1
_full_width = _width * len(options) + 1 _full_width = _width * len(options) + 1
layout.addWidget(QHLine(), 0, 0, 1, _full_width) layout.addWidget(QHLine(), 0, 0, 1, _full_width)

324
sendelogframe.py Normal file
View File

@@ -0,0 +1,324 @@
import getpass
import inspect
import os
import time
from qtpy.QtCore import Qt
from qtpy.QtWidgets import (QComboBox, QDialog, QFileDialog, QHBoxLayout,
QLabel, QLineEdit, QPushButton, QTextEdit,
QVBoxLayout)
import elog # https://github.com/paulscherrerinstitute/py_elog
from pyqtacc.bdbase.enumkind import MsgSeverity
_version = "1.0.0"
_pymodule = os.path.basename(__file__)
_appname, _appext = _pymodule.split(".")
def _line():
"""Macro to return the current line number.
The current line number within the file is used when
reporting messages to the message logging window.
Returns:
int: Current line number.
"""
return inspect.currentframe().f_back.f_lineno
class QSendToELOGFrame(QDialog):
""" Graphical interface to elog
"""
def __init__(self, parent, logbook=None, title=None, message=None,
attachFile=None, destination_folder=None):
super().__init__()
self.files_text = ''
self.fflag = False
self.parent = parent
if destination_folder is None:
self.destination = self.parent.elog_dest + " / " + self.parent.appname
else:
self.destination = destination_folder
self.window_title = self.parent.appname + ": " + _appname
self.pymodule = _pymodule
self.setWindowTitle(self.window_title)
elog_books = list(self.parent.settings.data["ElogBooks"])
self.elog_items = QComboBox()
self.elog_items.addItems(elog_books)
self.elog_items.currentIndexChanged.connect(self.on_elog_change)
idx = 0
if logbook is not None:
try:
idx = elog_books.index(logbook)
except Exception:
mess = "Index not found for logbook {0}".format(logbook)
self.parent.show_log_message(MsgSeverity.WARN, self.pymodule,
_line(), mess)
else:
logbook = self.parent.settings.data["Elog"]["book"]
try:
idx = elog_books.index(logbook)
except Exception:
mess = "Index not found for logbook {0}".format(logbook)
self.parent.show_log_message(MsgSeverity.WARN, self.pymodule,
_line(), mess)
self.logbook = logbook
self.elog_items.setCurrentIndex(idx)
self.elog_items.currentIndexChanged.emit(idx)
self.elog_items.setObjectName("Elog")
self.title_items = QHBoxLayout()
self.title_items.addWidget(QLabel('Title: '))
self.titleline = QLineEdit()
self.titleline.setObjectName('Elog')
#self.titleline.setStatusTip('elog')
if title is None:
title = self.parent.appname
self.titleline.setText(str(title))
self.titleline.setFixedWidth(300)
self.titleline.setAlignment(Qt.AlignCenter)
self.title_items.addWidget(self.titleline)
self.applicationbox = QHBoxLayout()
self.applicationbox.addWidget(QLabel('Application:'))
self.applicationlabel = QLabel(self.parent.pymodule)
self.applicationlabel.setObjectName("Elog")
# self.applicationbox.addStretch()
self.applicationbox.addWidget(self.applicationlabel)
logbook = QHBoxLayout()
logbook.addWidget(QLabel('Logbook: '))
logbook.addWidget(self.elog_items)
authorbox = QHBoxLayout()
authorbox.addWidget(QLabel('Author: '))
self.author = QLineEdit()
self.author.setObjectName('Elog')
self.author.setFixedWidth(195)
self.author.setStatusTip('elog')
self.author.setText(getpass.getuser())
authorbox.addWidget(self.author)
self.files = []
self.attributes = {}
self.layout = QVBoxLayout(self)
self.layout.addLayout(logbook)
self.layout.addLayout(self.applicationbox)
self.layout.addLayout(authorbox)
self.layout.addLayout(self.title_items)
report = QLabel('Report: ')
self.layout.addWidget(report)
self.message = QTextEdit(message)
self.layout.addWidget(self.message)
filebox = QHBoxLayout()
qlfile = QLabel('Attach:')
qlfile.setAlignment(Qt.AlignTop)
filebox.addWidget(qlfile)
self.filesE = QTextEdit()
self.filesE.setAlignment(Qt.AlignTop)
self.filesE.setFixedHeight(80)
self.filesE.setReadOnly(True)
self.attachFile = attachFile
if self.attachFile is not None:
_attachFile = []
if isinstance(self.attachFile, str):
_attachFile.append(self.attachFile)
elif isinstance(self.attachFile, list):
_attachFile = self.attachFile
for i, file in enumerate(_attachFile):
_attach_base = os.path.basename(file)
if i > 0:
self.files_text += "\n"
self.files_text += str(_attach_base)
self.filesE.setText(self.files_text)
self.fflag = True
filebox.addWidget(self.filesE)
openCloseVBox = QVBoxLayout()
self.openBtn = QPushButton('Add')
self.openBtn.setAutoDefault(False)
self.openBtn.clicked.connect(self.openFiles)
openCloseVBox.addWidget(self.openBtn)
closeBtn = QPushButton('Clear')
closeBtn.setAutoDefault(False)
closeBtn.clicked.connect(self.clearFiles)
openCloseVBox.addWidget(closeBtn)
filebox.addLayout(openCloseVBox)
self.layout.addLayout(filebox)
btnLayout = QHBoxLayout()
self.okBtn = QPushButton('Send')
self.okBtn.setAutoDefault(False)
self.okBtn.clicked.connect(self.ok)
self.cancelBtn = QPushButton('Cancel')
self.cancelBtn.setAutoDefault(False)
self.cancelBtn.clicked.connect(self.close)
btnLayout.addWidget(self.okBtn)
btnLayout.addWidget(self.cancelBtn)
self.messagelbl = QLabel('')
self.messagelbl.setStyleSheet("QLabel { color : red; }")
self.layout.addWidget(self.messagelbl)
self.layout.addLayout(btnLayout)
self.setMinimumWidth(440)
#self.exec()
def on_elog_change(self, elog_change_val):
if "test" in self.elog_items.currentText():
_bgcolor = "QComboBox {background: plum; color : black;}"
else:
_bgcolor = "QComboBox {background: lightblue; color : black;}"
self.elog_items.setStyleSheet(_bgcolor)
def ok(self):
message = self.message.document().toPlainText()
if not message:
self.messagelbl.setText('Please enter a brief Report')
return
title = self.titleline.text()
if not title:
self.messagelbl.setText('Titel attribute is required')
return
author = self.author.text()
application = self.applicationlabel.text()
self.attributes['Autor'] = author
self.attributes['Author'] = author
self.attributes['Application'] = application
self.attributes['Titel'] = title
self.attributes['Title'] = title
self.attributes['When'] = str(time.time())
self.attributes['Wann'] = str(time.time())
if self.attachFile is not None:
_attachFile = []
if isinstance(self.attachFile, str):
_attachFile.append(self.attachFile)
elif isinstance(self.attachFile, list):
_attachFile = self.attachFile
for i in range(0, len(_attachFile)):
if "/tmp" in _attachFile[i]:
self.files.append(str(_attachFile[i]))
elif "/afs/psi.ch" in _attachFile[i]:
self.files.append(str(_attachFile[i]))
elif "/sls/bd/data/" in _attachFile[i]:
self.files.append(str(_attachFile[i]))
else:
self.files.append(self.destination + str(_attachFile[i]))
el = self.elog_items.currentText()
url = self.parent.settings.data["ElogBooks"][el]["url"]
self.logbook = elog.open(url, user='robot', password='robot')
try:
if self.files:
self.logbook.post(message, attributes=self.attributes,
attachments=self.files)
else:
self.logbook.post(message, attributes=self.attributes)
#self.trigger_elog_entry.emit(True, url, "OK")
self.receive_elog_notification(True, url, "OK")
except Exception as ex:
#self.trigger_elog_entry.emit(False, url, str(ex))
print("Exception in sendelog.py", str(ex))
self.receive_elog_notification(False, url, str(ex))
#for file in self.files:
# if os.path.exists(file):
# os.remove(file)
self.close()
def clearFiles(self):
self.attachFile = []
self.filesE.clear()
self.files = []
self.files_text = ''
self.fflag = False
def openFiles(self):
# Notethat openFiles also gets called when qDialog cacnel is clicked!
qFileDialog = QFileDialog()
extensions = ("Images (*.bmp *.eps *.gif *.jpeg *.jpg *.pdf *.png " +
"*.ps *.tiff *.xpm);;Text files (*.txt *.text);;" +
"JSON/XML files (*.json *.xml)")
flocal = qFileDialog.getOpenFileNames(
self, 'Open File', self.destination, extensions)[0]
if not flocal:
return
self.files.append(flocal[0])
if self.fflag:
self.files_text += '\n'
self.files_text += str(flocal[0].split('/')[-1])
self.fflag = True
self.filesE.setText(self.files_text)
def receive_elog_notification(self, is_accepted, logbook_url, elog_message):
'''Receive notification from ELOG, and report to log window'''
yes_no = "made" if is_accepted else "failed"
mess = "Entry into ELOG: {0} {1}".format(logbook_url, yes_no)
if is_accepted:
self.parent.show_log_message(MsgSeverity.INFO, self.pymodule,
_line(), mess)
else:
mess += ".\n" + elog_message
self.parent.show_log_message(MsgSeverity.WARN, self.pymodule,
_line(), mess)
self.parent.statusbar.showMessage(mess)
def get_logbook_specific_items(self, logbook):
'''Retrieve logbook specific options'''
#First check what is the logbook being requested?
#find layout items
layout_items = []
layout_items_optional = []
try:
layout_items = list(self.parent.settings.data[
"ElogBooks"][logbook]['Required'].keys())
except KeyError:
pass
try:
layout_items_optional = list(self.parent.settings.data[
"ElogBooks"][logbook]['Optional'].keys())
except KeyError:
pass
layout_items.extend(layout_items_optional)
return layout_items