7 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
a332aecd87 v1.4.0 2022-10-06 08:26:50 +02:00
fcf37b60c8 overdue 2022-09-14 15:03:15 +02:00
5 changed files with 817 additions and 143 deletions

132
base.py
View File

@@ -5,10 +5,11 @@ from collections import OrderedDict
from datetime import datetime
import getpass
import h5py
import logging
import inspect
import platform
import re
import os
import re
import sys
import time
@@ -30,6 +31,8 @@ from pyqtacc.bdbase.readjson import ReadJSON
from pyqtacc.bdbase.savehdf import QSaveHDF
from pyqtacc.bdbase.hdf5filemenu import HDF5GroupBox
from pyqtacc.bdbase.sendelog import QSendToELOG
from pyqtacc.bdbase.screenshot import QScreenshot
from pyqtacc.bdbase.guiframe import GUIFrame
@@ -101,32 +104,53 @@ class BaseWindow(QMainWindow):
time_in_seconds=self.time_in_seconds,
reanalysis_time_in_seconds=self.reanalysis_time)
print("date_str", date_str, flush=True)
#print("date_str", date_str, flush=True)
write_message_fired = False
for i, (nfig, name) in enumerate(
zip(self.settings.data["GUI"]["resultsSeq"],
self.settings.data["GUI"]["subResultsTabTitle"])):
canvas = 'Canvas {0}'.format(i+1)
name_base = name.replace(' ', '_').lower()
for idx in range(0, nfig):
if self.all_data['Figure data'][canvas] is not None:
nfig_canvas = len(self.all_data['Figure data'][canvas])
nfig_canvas = min(nfig_canvas, nfig)
else:
nfig_canvas = nfig
for idx in range(0, nfig_canvas):
if self.all_data['Figure data'][canvas] is not None:
name = name_base + "_{0}".format(
idx) if idx > 0 else name_base
save_dest = (folder_name + date_str + '_' + name +
'.png')
print("idx", i, save_dest, flush=True)
if not os.path.exists(save_dest):
if self.all_data['Figure data'][canvas][
idx] is not None:
self.all_data['Figure data'][canvas][
idx].savefig(save_dest)
_dirname = os.path.dirname(save_dest)
if os.access(_dirname, os.W_OK):
self.all_data['Figure data'][canvas][
idx].savefig(save_dest)
elif not write_message_fired:
_mess = ("Do not have write permission " +
"for directory {0} from this " +
"host {1}. Images not saved and " +
"cannot be sent to elog").format(
_dirname, os.uname()[1])
self.parent.trigger_log_message.emit(
MsgSeverity.WARN.name, _pymodule,
_line(), _mess, {})
write_message_fired = True
attach_files.append(save_dest)
if attach_files:
self.parent.attach_files = attach_files
print("All files attached")
print("All files attached", flush=True)
else:
print("No files to attach", flush=True)
time.sleep(0.2) #avoid race condition
@@ -276,12 +300,15 @@ class BaseWindow(QMainWindow):
def run(self):
"""Run thread
"""
all_dict = self.analysis_procedure.measure_and_analyze(
self.input_parameters)
# Emit results
if all_dict is not None:
if all_dict:
self.trigger_thread_event.emit(all_dict)
mess = "Analysis completed"
self.parent.trigger_log_message.emit(
MsgSeverity.INFO.name, _pymodule, _line(), mess, {})
@@ -293,7 +320,7 @@ class BaseWindow(QMainWindow):
def __init__(self, parent=None, pymodule=None, appversion=None, title="",
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)
self.parent = parent
@@ -307,12 +334,18 @@ class BaseWindow(QMainWindow):
self.facility = facility
self.user_mode = user_mode
self.appname, self.appext = self.pymodule.split(".")
print("=============================================")
print("Starting {0} at: {1}".format(self.appname, datetime.now()))
print("User: {0} Host: {1}".format(os.getlogin(), os.uname()[1]))
print("=============================================", flush=True)
self.settings = ReadJSON(self.appname)
#Read out current_logbook
self.cafe = PyCafe.CyCafe()
self.cyca = PyCafe.CyCa()
self.cafe_exception = PyCafe.CafeException
@@ -332,7 +365,7 @@ class BaseWindow(QMainWindow):
self.hdf_dialog = None
self.daq_analysis_completed = False
self.hdf_save_completed = False
self.setObjectName("MainWindow")
self.setWindowTitle(self.appname)
@@ -343,8 +376,7 @@ class BaseWindow(QMainWindow):
self.menu = self.menuBar()
self.settings = ReadJSON(self.appname)
'''
try:
dirname = self.settings.data["stdout"]["destination"]
@@ -364,6 +396,12 @@ class BaseWindow(QMainWindow):
self.stdlog_dest = (self.settings.data["stdlog"]["destination"] +
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.autopost_elog = True
@@ -382,13 +420,16 @@ class BaseWindow(QMainWindow):
self.autopost_epics = self.settings.data["menuFlags"]["hasEpics"]
except KeyError as error:
print("KeyError in base.py, init:", error)
self.autopost_epics = True
self.autopost_epics = False
try:
self.autopost_hdf = self.settings.data["menuFlags"]["hasH5"]
except KeyError as error:
print("KeyError in base.py, init:", error)
self.autopost_hdf = True
self.autopost_hdf = False
self.hdf_save_completed = False if self.autopost_hdf else True
self.all_input_parameters = {} #gui
self.all_input_labels = {} #gui
@@ -463,18 +504,23 @@ class BaseWindow(QMainWindow):
if self.facility == Facility.SwissFEL:
from pyqtacc.sf.guiheader import GUIHeader
from pyqtacc.bdbase.sendelog import QSendToELOG
elif self.facility == Facility.SLS:
from pyqtacc.sls.guiheader import GUIHeader
from pyqtacc.sls.sendelogsls import QSendToELOG
self.gui_header = GUIHeader(self, user_mode=self.user_mode,
extended=extended)
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.hdf_dock_widget = QNoDockWidget(" HDF5", self)
self.init_hdf_analysis_wgt()
if self.autopost_hdf:
self.hdf_dock_widget = QNoDockWidget(" HDF5", self)
self.init_hdf_analysis_wgt()
self.mainwindow_layout.addWidget(self.gui_frame.central_tab_widget)
self.mainwindow.setLayout(self.mainwindow_layout)
@@ -523,7 +569,7 @@ class BaseWindow(QMainWindow):
if self.settings.data["Parameters"][key]["flag"]:
self.input_parameters[key] = val
self.all_input_parameters[key] = val
self.all_input_parameters[key] = val
#print("val=",val, key)
except KeyError as e:
@@ -569,8 +615,8 @@ class BaseWindow(QMainWindow):
if self.settings.data["Expert"][key]["flag"]:
self.expert_parameters[key] = val
self.all_expert_parameters[key] = val
#print("val=",val, key)
self.all_expert_parameters[key] = val
#print("val=",val, key)
except KeyError as e:
print("Key Error in base.py initialization:", e)
@@ -811,7 +857,7 @@ class BaseWindow(QMainWindow):
"""
#Close all dock widgets
#self.removeDockWidget(self.hdf_dock_widget)
self.logger.info("Closing Application")
self.save_application_settings()
QApplication.processEvents()
self.cafe.monitorStopAll()
@@ -1147,6 +1193,7 @@ class BaseWindow(QMainWindow):
#print("filename", self.hdf_filename)
def verify_send_to_elog(self):
if self.analysis_thread is not None:
if self.analysis_thread.isRunning():
_mess = ("Measurement in progress. " +
@@ -1180,6 +1227,9 @@ class BaseWindow(QMainWindow):
def send_to_elog(self):
""" 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.isRunning():
_mess = ("Measurement in progress. " +
@@ -1188,6 +1238,7 @@ class BaseWindow(QMainWindow):
QMessageBox.Ok)
return
'''
#_elog_sf = ElogSwissFEL()
_logbook = None
@@ -1197,6 +1248,7 @@ class BaseWindow(QMainWindow):
_attach_files = []
_message = ""
QSendToELOG(self, logbook=_logbook, categoryIdx=_category_idx,
domainIdx=_domain_idx, sectionIdx=_section_idx,
title=self.title, message=_message,
@@ -1613,7 +1665,7 @@ class BaseWindow(QMainWindow):
@Slot()
def start_analysis_thread(self):
if not self.analysis_procedure:
mess = "Analysis thread not configured for this application"
self.show_log_message(MsgSeverity.ERROR, _pymodule, _line(), mess)
@@ -1636,17 +1688,17 @@ class BaseWindow(QMainWindow):
if not self.verify_analysis_preconditions():
return
self.analysis_thread = self.AnalysisThread(
self, self.analysis_procedure, self.input_parameters)
self.analysis_thread.trigger_thread_event.connect(
self.receive_analysis_results)
self.analysis_thread.started.connect(self.analysis_thread_started)
self.analysis_thread.finished.connect(self.analysis_thread_finished)
#getMachineDatafor hdf
self.analysis_thread.start()
QApplication.processEvents()
@@ -1686,17 +1738,26 @@ class BaseWindow(QMainWindow):
@Slot(dict)
def receive_analysis_results(self, all_dict):
#print("receive analysis results", all_dict)
self.all_data = all_dict
self.gui_frame.canvas_update(all_dict['Figure data'])
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.results_tab_wgt.setCurrentIndex(0)
self.gui_frame.results_tab_wgt.setCurrentIndex(0)
@Slot()
def receive_abort_analysis(self):
"""Instantiate action on abort
"""
print("Aborting")
if self.analysis_procedure.abort:
return
self.gui_frame.in_abort_procedure()
@@ -1719,6 +1780,12 @@ class BaseWindow(QMainWindow):
message="Measurement in progress..."):
'''Receives update of message'''
self.progressbar.setVisible(True)
try:
if self.input_parameters["simulation"] :
self.progressbar_color = self.progressbar_simulation
except KeyError:
pass
if value == PROGRESS_BAR_THREAD_INIT:
self.progressbar.setVisible(False)
self.progressbar.setFormat("")
@@ -1738,6 +1805,8 @@ class BaseWindow(QMainWindow):
prog_val = re.findall(r'\d+', message)
if prog_val:
self.progressbar.setValue(int(prog_val[0]))
else:
self.progressbar.setValue(int(10))
mess = "Aborting measurement procedure"
self.show_log_message(
MsgSeverity.WARN.name, _pymodule, _line(), mess)
@@ -1764,7 +1833,8 @@ class BaseWindow(QMainWindow):
self.progressbar.setValue(value)
self.progressbar.setObjectName(self.progressbar_color)
self.daq_analysis_completed = True
self.hdf_save_completed = False
if self.autopost_hdf:
self.hdf_save_completed = False
QTimer.singleShot(2000, lambda: self.progressbar.setVisible(False))
else:
self.progressbar.setFormat(message)
@@ -1774,7 +1844,7 @@ class BaseWindow(QMainWindow):
self.progressbar.style().polish(self.progressbar)
QApplication.processEvents()
time.sleep(0.0001)
def initialize_application(self, appname=_appname, delay=None,
facility=Facility.SwissFEL):

View File

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

View File

@@ -17,15 +17,15 @@ from qtpy.QtWidgets import (QCheckBox, QComboBox, QDoubleSpinBox, QFrame,
QStackedWidget, QTabBar, QTabWidget, QToolButton,
QVBoxLayout, QWidget)
from caqtwidgets.pvwidgets import (CAQLabel, CAQTableWidget, QMessageWidget,
QHLine)
QHLine, QVLine)
from pyqtacc.bdbase.enumkind import Facility, MsgSeverity, UserMode
_pymodule = os.path.basename(__file__)
_appversion = "1.0.0"
INPUT_PARAMETERS_HEIGHT = 600
EXPERT_PARAMETERS_HEIGHT = 600
INPUT_PARAMETERS_HEIGHT = 200
EXPERT_PARAMETERS_HEIGHT = 200
def _line():
@@ -42,11 +42,12 @@ def _line():
class GUIFrame(QWidget):
""" GUI Class
"""
def __init__(self, parent, has_optics=True):
def __init__(self, parent, has_optics=True, has_procedure=True):
#super(GUIFrame, self).__init__()
super().__init__()
self.parent = parent
self.has_optics = has_optics
self.has_procedure = has_procedure
self.appname = parent.appname
self.facility = parent.facility
self.settings = parent.settings
@@ -61,6 +62,8 @@ class GUIFrame(QWidget):
self.all_expert_parameters = parent.all_expert_parameters
self.all_expert_labels = parent.all_expert_labels
self.results_output_wgt_dict = {}
try:
self.widget_height = self.settings.data["StyleGuide"][
"widgetHeight"]
@@ -75,18 +78,21 @@ class GUIFrame(QWidget):
self.expert_parameters_group = None
self.operator_parameters_group = None
self.output_parameters_wgt = None
self.optics_group = None
self.energy_stacked_widget = None
self.phase_stacked_widget = None
self.table_tab_wgt = None
self.radiobutton = None
self.multiple_figure_dict = None
self.line_sender_dict = {}
self.radio_stack_dict = {}
self.stack_radiolist_dict = {}
self.stacked_wgt_dict = {}
self.current_stacked_wgt_dict = {}
self.msg_severity_qcolor = parent.msg_severity_qcolor
self.msg_severity = MsgSeverity
@@ -102,7 +108,7 @@ class GUIFrame(QWidget):
self.measurement_layout.setAlignment(Qt.AlignLeft | Qt.AlignTop)
self.measurement_layout.setSpacing(50)
self.measurement_tab_wgt = QTabWidget(self.measurement_wgt)
self.measurement_tab_wgt.setFixedWidth(480)
self.measurement_tab_wgt.setMinimumWidth(480)
self.operator_wgt = QWidget(self.measurement_tab_wgt)
self.expert_wgt = QWidget(self.measurement_tab_wgt)
@@ -111,20 +117,6 @@ class GUIFrame(QWidget):
self.results_layout = QHBoxLayout(self.results_wgt)
self.results_tab_wgt = QTabWidget(self.results_wgt)
self.results_tab_wgt_titles = self.settings.data[
"GUI"]["subResultsTabTitle"]
self.sub_results_wgt = [None] * len(self.results_tab_wgt_titles)
self.sub_results_layout = [None] * len(self.results_tab_wgt_titles)
for i in range(0, len(self.results_tab_wgt_titles)):
self.sub_results_wgt[i] = QWidget(self.results_tab_wgt)
self.canvas = [None] * len(self.results_tab_wgt_titles)
self.nav = [None] * len(self.results_tab_wgt_titles)
self.arrow_button_widget = [None] * len(self.results_tab_wgt_titles)
self.canvas_current_idx = [0] * len(self.results_tab_wgt_titles)
self.canvas_fig_dict = {}
self.left_arrow_dict = {}
@@ -136,13 +128,32 @@ class GUIFrame(QWidget):
self.start_wgt_text = "Start"
self.save_all_wgt = QWidget()
self.init_measurement_tab_wgt()
self.init_results_tab_wgt()
if "GUI" in self.settings.data:
self.results_tab_wgt_titles = self.settings.data[
"GUI"]["subResultsTabTitle"]
self.sub_results_wgt = [None] * len(self.results_tab_wgt_titles)
self.sub_results_layout = [None] * len(self.results_tab_wgt_titles)
for i in range(0, len(self.results_tab_wgt_titles)):
self.sub_results_wgt[i] = QWidget(self.results_tab_wgt)
self.canvas = [None] * len(self.results_tab_wgt_titles)
self.nav = [None] * len(self.results_tab_wgt_titles)
self.arrow_button_widget = [None] * len(self.results_tab_wgt_titles)
self.canvas_current_idx = [0] * len(self.results_tab_wgt_titles)
self.init_results_tab_wgt()
self.slice_orientation = "vertical" #horizontal/vertical for SATMA02
self.init_measurement_tab_wgt()
self.log_wgt = QMessageWidget()
self.log_layout = QVBoxLayout(self.log_wgt)
self.show_log_message(MsgSeverity.INFO, _pymodule, _line(),
"Application started")
#self.show_log_message(MsgSeverity.INFO, _pymodule, _line(),
# "Application started")
self.input_wgt_grid = QGridLayout()
self.input_wgt_grid.setHorizontalSpacing(0)
@@ -160,8 +171,9 @@ class GUIFrame(QWidget):
"""
self.central_tab_widget.setFont(self.font_gui)
self.central_tab_widget.addTab(self.measurement_wgt, "Measurement")
self.central_tab_widget.addTab(
self.results_wgt, self.settings.data["GUI"]["resultsTabTitle"])
if "GUI" in self.settings.data:
self.central_tab_widget.addTab(
self.results_wgt, self.settings.data["GUI"]["resultsTabTitle"])
self.central_tab_widget.addTab(self.log_wgt, "Log")
def init_measurement_tab_wgt(self):
@@ -236,7 +248,7 @@ class GUIFrame(QWidget):
hbox.setSpacing(5)
hbox.setAlignment(Qt.AlignTop | Qt.AlignHCenter)
group_box.setMaximumWidth(208)
group_box.setMaximumHeight(220)
group_box.setMinimumHeight(196)
group_box.setFont(self.font_gui)
group_box.setAlignment(Qt.AlignTop | Qt.AlignHCenter)
group_box.setLayout(hbox)
@@ -260,6 +272,76 @@ class GUIFrame(QWidget):
self.optics_group.cycle_quads = None
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"):
""" Generic group box for user supplied input
"""
@@ -301,11 +383,12 @@ class GUIFrame(QWidget):
#print(self.input_parameters)
checkbox = QCheckBox(text)
checkbox.setToolTip(tip)
checkbox.setFont(self.font_gui)
checkbox.stateChanged.connect(on_checkbox_change)
#checkbox.setFixedHeight(30)
#checkbox.setLayoutDirection(Qt.RightToLeft)
checked_value = default_value
if key in self.parent.input_parameters.keys():
if "data" in self.settings.data[top_key][key].keys():
@@ -316,16 +399,18 @@ class GUIFrame(QWidget):
checked_value = Qt.Unchecked
checkbox.setCheckState(checked_value)
checkbox.stateChanged.emit(checked_value)
return checkbox
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
"""
def callback(value):
self.input_parameters[key] = value
self.input_parameters[key] = round(value, digits)
widget_height = 24
suggested = "WWW"
@@ -347,6 +432,7 @@ class GUIFrame(QWidget):
wgt.setMaximumWidth(param_width + 40)
wgt.valueChanged.connect(callback)
wgt.setValue(start_val)
wgt.valueChanged.emit(start_val)
return lab, wgt
@@ -358,6 +444,7 @@ class GUIFrame(QWidget):
def cb(value):
self.input_parameters[key] = value
widget_height = 24
suggested = "WWW"
lab = QLabel(label)
@@ -377,15 +464,17 @@ class GUIFrame(QWidget):
wgt.setMaximumWidth(param_width + 40)
wgt.valueChanged.connect(cb)
wgt.setValue(start_val)
wgt.valueChanged.emit(start_val)
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
"""
def cb(new_text):
self.input_parameters[key] = new_text
print( self.input_parameters)
widget_height = 26
suggested = "WWW"
@@ -402,8 +491,11 @@ class GUIFrame(QWidget):
wgt.setFont(self.font_pts10)
wgt.setContentsMargins(5, 0, 0, 0)
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)
@@ -411,23 +503,33 @@ class GUIFrame(QWidget):
param_width = max(fm.width(str(value_for_width)), fm.width(suggested))
wgt.setFixedWidth(param_width + 50)
return lab, wgt
def image_parameters_group(self):
group_box = QGroupBox("Image Pipeline Parameters")
group_box = QGroupBox("Image Pipeline Expert")
box = QHBoxLayout()
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(
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(
top_key="Expert", key="subtractBackground",
text="Subtract bkgrnd",
tip="Enables background subtraction in pipeline",
default_value=Qt.Checked))
default_value=start_val_sub))
group_box.setAlignment(Qt.AlignCenter)
group_box.setObjectName("INNERCENTER")
@@ -435,10 +537,20 @@ class GUIFrame(QWidget):
good_region = QGroupBox("Good Region")
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(
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(
key="grScale", label="Scale:")
key="grScale", label="Scale:", start_val=start_val_grScale)
layout = QGridLayout()
layout.addWidget(lab_thresh, 0, 0)
layout.addWidget(thresh, 0, 1)
@@ -449,13 +561,28 @@ class GUIFrame(QWidget):
slicing = QGroupBox("Slicing")
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(
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(
key="slicingScale", label="Scale:")
lab_orientation, orientation = self.create_label_qcombobox(
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(
key="orientation", label="Orientation:",
values=["vertical", "horizontal"])
values=["vertical", "horizontal"], start_val=start_val_orientation)
layout = QGridLayout()
@@ -464,7 +591,7 @@ class GUIFrame(QWidget):
layout.addWidget(lab_scale, 1, 0)
layout.addWidget(scale, 1, 1)
layout.addWidget(lab_orientation, 2, 0, 1, 2, Qt.AlignBottom)
layout.addWidget(orientation, 3, 0, 1, 2, Qt.AlignTop | Qt.AlignRight)
layout.addWidget(self.slice_orientation, 3, 0, 1, 2, Qt.AlignTop | Qt.AlignRight)
slicing.setLayout(layout)
layout_top = QGridLayout()
@@ -556,11 +683,19 @@ class GUIFrame(QWidget):
for table in self.table_wgt:
table.init_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):
self.abort_wgt.setEnabled(False)
self.start_wgt.setEnabled(False)
self.start_wgt.setText("Aborting...")
def reset_procedure(self):
self.abort_wgt.setVisible(False)
@@ -576,6 +711,8 @@ class GUIFrame(QWidget):
for table in self.table_wgt:
table.init_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):
self.parent.h5_groupbox.analyze_h5_widget.setEnabled(False)
@@ -739,7 +876,7 @@ class GUIFrame(QWidget):
except KeyError as error:
print(("KeyError in guiframe.py; Unknown key {0} " +
"in def checkbox_wgt: {1}").format(key, error))
text = key
text = key
checkbox = QCheckBox(text)
checkbox.setToolTip(tooltip)
@@ -747,9 +884,12 @@ class GUIFrame(QWidget):
if object_name:
checkbox.setObjectName(object_name)
checkbox.setLayoutDirection(Qt.LeftToRight) #is default
checkbox.stateChanged.connect(on_change)
checked_value = Qt.Unchecked
if "Expert" not in self.settings.data:
return widget
#if key in self.parent.input_parameters.keys():
if key in self.settings.data["Expert"].keys():
if "data" in self.settings.data["Expert"][key].keys():
@@ -921,18 +1061,23 @@ class GUIFrame(QWidget):
def canvas_update(self, fig_data, idx=0):
#place figures in a list
self.parent.clear_screenshot()
self.parent.clear_screenshot()
self.multiple_figure_dict = fig_data
for i, key in enumerate(self.multiple_figure_dict.keys()):
self.canvas_fig_dict[i] = key
for i, (canvas, nav, wgt, layout, key) in enumerate(
zip(self.canvas, self.nav,
self.sub_results_wgt,
self.sub_results_layout,
self.multiple_figure_dict.keys())):
if canvas is not None:
layout.removeWidget(canvas)
@@ -941,10 +1086,13 @@ class GUIFrame(QWidget):
nav.deleteLater()
if self.multiple_figure_dict[key]: #'Figure 1']:
if not isinstance(self.multiple_figure_dict[key], list):
temp_list = []
temp_list.append(self.multiple_figure_dict[key])
self.multiple_figure_dict[key] = temp_list
self.canvas[i] = FigureCanvasQTAgg(
self.multiple_figure_dict[key][idx])
self.sub_results_layout[i].addWidget(self.canvas[i])
@@ -955,10 +1103,10 @@ class GUIFrame(QWidget):
#self.nav[i].setContentsMargins(0, 0, 0, 0)
self.nav[i].setVisible(True)
self.nav[i].setStyleSheet("QToolBar { border: 0px }")
self.parent.add_screenshot(title=self.results_tab_wgt_titles[i],
item=wgt)
else:
self.canvas[i] = None
self.nav[i] = None
@@ -975,16 +1123,22 @@ class GUIFrame(QWidget):
self.cafe.setGetActionWhenMonitorPolicy(
pv, self.cyca.GET_FROM_CACHE)
stack_list = []
for pv, head, val, obj in zip(pvlist, title, default_value,
object_name):
stack, radiobutton_list = self.pv_selector_wgt(
title=head, key=key, pv=pv, manual_value=val)
self.stack_radiolist_dict[stack] = radiobutton_list
stack_list.append(stack)
stack.setObjectName(obj)
stack.style().polish(stack)
stacked_widget.addWidget(stack)
stacked_widget.setMaximumHeight(220)
stacked_widget.setMaximumHeight(320)
self.stacked_wgt_dict[stacked_widget] = stack_list
return stacked_widget
def pv_energy_stacked_wgt(self):
@@ -1033,10 +1187,27 @@ class GUIFrame(QWidget):
radiobutton_title = ["Monitor", "Update", "Manual"]
radiobutton_flag = [monitor, read, manual]
radiobutton_list = [None] * len(radiobutton_title)
pv_local = pv
monitor_pv = None
def cb_pv_selector(value):
value_str = radio_buddy_text_dict[self.sender()].text()
#print("cb_pv_selector", value_str)
#Find which group the radio button belongs to:
#Find which stack the group belongs to:
#Set this to the current stack?
for k, v in self.stack_radiolist_dict.items():
if self.sender() in v:
#get groupbox from key
for k2, v2 in self.stacked_wgt_dict.items():
if k in v2:
self.current_stacked_wgt_dict[k2] = pv_local #self.sender()
#print("Current STACK FOUND")
self.radio_stack_dict[self.sender()] = value
if not value_str:
@@ -1074,6 +1245,7 @@ class GUIFrame(QWidget):
if flag:
grid.addWidget(radio, irow, 0)
if monitor:
ql = QLabel(radiobutton_title[0])
ql.setFont(self.font_pts10)
@@ -1088,8 +1260,18 @@ class GUIFrame(QWidget):
ql.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
grid.addWidget(ql, 2, 1)
def mon_cb(handle, pvname, pvdata):
if monitor_pv is not None:
monitor_pv.py_monitor_callback(handle, pvname, pvdata)
if pvname in self.current_stacked_wgt_dict.values() and \
radiobutton_list[0].isChecked(): #
self.input_parameters[key] = pvdata.value[0]
if monitor:
monitor_pv = CAQLabel(self, pv_name=pv, show_units=True)
monitor_pv = CAQLabel(self, pv_name=pv, monitor_callback=mon_cb,
show_units=True)
monitor_pv.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
monitor_pv.setFont(self.font_pts10)
monitor_pv.setFixedHeight(self.widget_height)
@@ -1161,13 +1343,14 @@ class GUIFrame(QWidget):
ql.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
grid.addWidget(ql, 2, 3)
grid.setContentsMargins(9, 15, 9, 0)
grid.setContentsMargins(5, 10, 5, 0)
#grid.setContentsMargins(9, 15, 9, 0)
grid.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
grid.setVerticalSpacing(2)
grid.setHorizontalSpacing(4)
group_box.setContentsMargins(0, 0, 0, 0)
group_box.setMaximumWidth(280)
group_box.setMaximumHeight(260)
group_box.setMaximumHeight(320)
group_box.setFont(self.font_pts10)
group_box.setAlignment(Qt.AlignTop | Qt.AlignHCenter)
group_box.setLayout(grid)
@@ -1233,11 +1416,19 @@ class GUIFrame(QWidget):
return line
def input_wgt_qradiobutton(self, key, value, irow, wgt_grid):
def on_radiobutton_change(): #new_value):
def on_radiobutton_change(new_value):
radio_button = self.sender()
self.parent.input_parameters[key] = radio_button.target
if 'forwardLink' in self.settings.data['Parameters'][key]['data']:
link = self.settings.data['Parameters'][key]['data'][
if radio_button.isChecked():
self.parent.input_parameters[key] = radio_button.target
#print("KEY================", key, self.parent.input_parameters[key], new_value)
if key in self.settings.data["Expert"].keys():
top_key = "Expert"
elif key in self.settings.data["Parameters"].keys():
top_key = "Parameters"
if 'forwardLink' in self.settings.data[top_key][key]['data']:
link = self.settings.data[top_key][key]['data'][
'forwardLink'][0]
for item in self.settings.data[link][radio_button.target]:
@@ -1245,26 +1436,45 @@ class GUIFrame(QWidget):
item]
if item in self.line_sender_dict:
if self.settings.data['Parameters'][item]['data'][
if self.settings.data[top_key][item]['data'][
'widget'] in 'QComboBox':
self.line_sender_dict[item].clear()
self.line_sender_dict[item].addItems(value_list)
self.line_sender_dict[item].setCurrentIndex(0)
self.line_sender_dict[item].currentTextChanged.emit(
value_list[0])
elif self.settings.data['Parameters'][item]['data'][
elif self.settings.data[top_key][item]['data'][
'widget'] in 'QLineEdit':
self.line_sender_dict[item].setText(str(value_list))
line = self.radio_buttons(value)
line = self.radio_buttons(key=key, options=value)
line.setContentsMargins(0, 0, 0, 0)
rblist = line.findChildren(QRadioButton)
for rb in rblist:
rb.toggled.connect(on_radiobutton_change)
rblist[0].setChecked(True)
rblist[0].toggled.emit(True)
wgt_grid.addWidget(line, irow, 0, 1, 4)
wgt_grid.addWidget(line, irow, 0, 1, 4, Qt.AlignLeft)
_idx=0
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
@@ -1276,10 +1486,26 @@ class GUIFrame(QWidget):
line.setChecked(Qt.Checked if value else Qt.Unchecked)
line.stateChanged.connect(check_cb)
line.setMaximumWidth(320)
line.setMinimumWidth(220)
line.setMinimumWidth(100)
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
@@ -1298,22 +1524,27 @@ class GUIFrame(QWidget):
return line
def input_wgt_qlineread(self, value, label, irow, wgt_grid):
#Read only has no callback
def input_wgt_qlineread(self, key, value, label, irow, wgt_grid):
def line_cb(new_value):
self.parent.input_parameters[key] = new_value
suggested = "WW"
line = QLineEdit()
line.setObjectName("Read")
line.setText(str(value)) #"{0: 3.1f}".format(value))
line.setFixedHeight(24)
line.textChanged.connect(line_cb)
line.setAlignment(Qt.AlignRight | Qt.AlignBottom)
line.setStyleSheet("QLabel{text-align: right}")
fm = QFontMetricsF(line.font())
param_width = max(fm.width(str(value)), fm.width(suggested))
line.setMaximumWidth(param_width + 24)
wgt_grid.addWidget(label, irow, 0, 1, 2, Qt.AlignLeft | Qt.AlignVCenter)
wgt_grid.addWidget(line, irow, 2, 1, 2, Qt.AlignLeft | Qt.AlignVCenter)
extra_width = 22 if len(str(value)) < 16 else 26
line.setFixedWidth(param_width + extra_width)
qframe_buffer = QFrame()
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
def input_wgt_qlineedit(self, key, value, label, irow, wgt_grid):
@@ -1322,13 +1553,15 @@ class GUIFrame(QWidget):
suggested = "WW"
line = QLineEdit()
line.setObjectName("Write")
line.setFixedHeight(24)
line.textEdited.connect(line_cb)
line.setText(str(value))
fm = QFontMetricsF(line.font())
param_width = max(fm.width(str(value)), fm.width(suggested))
line.setMaximumWidth(param_width + 20)
param_width = max(fm.width(str(value)), fm.width(suggested))
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(line, irow, 2, 1, 2, Qt.AlignLeft | Qt.AlignVCenter)
@@ -1395,22 +1628,30 @@ class GUIFrame(QWidget):
return line
def input_wgt_qenergystacked(self, irow, wgt_grid):
qFrame = QFrame()
qFrame.setFixedHeight(10)
line = self.pv_energy_stacked_wgt()
wgt_grid.addWidget(qFrame, irow, 0, 1, 4)
wgt_grid.addWidget(line, irow+1, 0, 1, 4)
qframe_top = QFrame()
qframe_top.setFixedHeight(3)
stacked_wgt = self.pv_energy_stacked_wgt()
qframe_bottom = QFrame()
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):
qFrame = QFrame()
qFrame.setFixedHeight(10)
line = self.pv_phase_stacked_wgt()
wgt_grid.addWidget(qFrame, irow, 0, 1, 4)
wgt_grid.addWidget(line, irow+1, 0, 1, 4)
qframe_top = QFrame()
qframe_top.setFixedHeight(3)
stacked_wgt = self.pv_phase_stacked_wgt()
qframe_bottom = QFrame()
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):
qHLine = QHLine()
@@ -1424,7 +1665,13 @@ class GUIFrame(QWidget):
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:
wgt_grid = self.input_wgt_grid
@@ -1451,7 +1698,7 @@ class GUIFrame(QWidget):
line = self.input_wgt_qlabel(value, irow, wgt_grid)
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():
line = self.input_wgt_qdoublespinbox(key, value, label, irow,
@@ -1517,21 +1764,31 @@ class GUIFrame(QWidget):
except KeyError:
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(),
self.all_input_labels.values()):
buddy = self.settings.data[
"Parameters"][key]["data"]["widget"].upper()
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,
irow=j, wgt_grid=self.input_wgt_grid)
self.operator_parameters_group.layout().addLayout(self.input_wgt_grid)
self.operator_parameters_group.setFixedHeight(INPUT_PARAMETERS_HEIGHT)
self.operator_parameters_group.setMinimumHeight(INPUT_PARAMETERS_HEIGHT)
lo = QGridLayout()
lo.setContentsMargins(9, 19, 9, 9)
lo.addWidget(self.operator_parameters_group, 0, 0, 4, 1)
lo.addWidget(self.operator_parameters_group, 0, 0, 4, 1, alignment=Qt.AlignTop)
#if random.randint(1, 10) > 9:
# lo.addWidget(self.create_analysis_wgt(), 0, 1)
#else:
@@ -1540,8 +1797,11 @@ class GUIFrame(QWidget):
row_count = 1
else:
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
lo.setAlignment(Qt.AlignHCenter | Qt.AlignTop)
lo.setHorizontalSpacing(20)
@@ -1564,6 +1824,11 @@ class GUIFrame(QWidget):
#Add expert parameters to input_parameters
self.input_parameters.update(self.expert_parameters)
#Need to emit radio button here as input_parameters is overwritten by sel.expoert_parameters
#which give a list [Gasusian and FWMH]
if self.radiobutton:
self.radiobutton[0].toggled.emit(True)
if self.expert_wgt_grid:
self.expert_parameters_group.layout().addLayout(
self.expert_wgt_grid)
@@ -1595,7 +1860,7 @@ class GUIFrame(QWidget):
self.expert_parameters_group.layout().addWidget(
self.checkbox_keepImages())
self.expert_parameters_group.layout().addWidget(QHLine())
##self.expert_parameters_group.layout().addWidget(QHLine())
hbox2 = QHBoxLayout()
hbox2.addWidget(self.checkbox_debug(hline="None"))
@@ -1612,21 +1877,23 @@ class GUIFrame(QWidget):
self.expert_parameters_group.layout().addWidget(QHLine())
self.expert_parameters_group.setFixedHeight(EXPERT_PARAMETERS_HEIGHT)
self.expert_parameters_group.setMinimumHeight(EXPERT_PARAMETERS_HEIGHT)
lo = QGridLayout()
lo.setContentsMargins(9, 19, 9, 9)
lo.addWidget(self.expert_parameters_group, 0, 0, 2, 1)
lo.addWidget(self.expert_parameters_group, 0, 0, 1, 1, alignment=Qt.AlignTop)
lo.setAlignment(Qt.AlignHCenter | Qt.AlignTop)
lo.setHorizontalSpacing(20)
self.expert_wgt.setLayout(lo)
#test
def radio_buttons(self, options: list = [], start_idx=0):
def radio_buttons(self, key="", options: list = [], start_idx=0):
widget = QWidget()
layout = QGridLayout()
layout.setContentsMargins(0, 0, 0, 0)
self.setLayout(layout)
layout.setContentsMargins(5, 0, 5, 0)
widget.setMaximumWidth(220)
#self.setLayout(layout)
target_list = options
color_list = ["#894961", "teal", "darkblue"]
@@ -1637,11 +1904,18 @@ class GUIFrame(QWidget):
width_list = [70, 70, 70]
layout.addWidget(QHLine(), 0, 0, 1, 3)
layout.addWidget(QLabel("RF Tranverse Deflector"), 1, 0, 1, 3,
Qt.AlignCenter)
if key in self.settings.data["Expert"].keys():
top_key = "Expert"
elif key in self.settings.data["Parameters"].keys():
top_key = "Parameters"
_fix_width = False
_width = 1
_full_width = _width * len(options) + 1
layout.addWidget(QHLine(), 0, 0, 1, _full_width)
layout.addWidget(QLabel(
self.settings.data[top_key][key]['data']['text']), 1, 0, 1, 1,
Qt.AlignCenter)
for i, (radio, target, color, width) in enumerate(
zip(self.radiobutton, target_list, color_list, width_list)):
@@ -1649,14 +1923,17 @@ class GUIFrame(QWidget):
radio.setFont(self.font_pts10)
radio.setStyleSheet("color : {0};".format(color))
radio.target = target
layout.addWidget(radio, 2, i)
if _fix_width:
radio.setFixedWidth(width)
layout.addWidget(radio, 1, _width*i+1, 1, _width, Qt.AlignCenter)
#_qf = QFrame()
#_qf.setFixedWidth(10)
#layout.addWidget(_qf, 1, layout.columnCount())
self.radiobutton[start_idx].setChecked(True)
self.radiobutton[start_idx].toggled.emit(True)
#self.radiobutton[start_idx].setChecked(True)
#self.radiobutton[start_idx].toggled.emit(True)
layout.addWidget(QHLine(), 3, 0, 1, 3)
layout.addWidget(QHLine(), 2, 0, 1, layout.columnCount())
widget.setLayout(layout)

View File

@@ -34,6 +34,7 @@ class QSendToELOG(QDialog):
attachFile=None, destination_folder=None):
#super(QSendToELOG, self).__init__(parent)
super().__init__()
self.files_text = ''
self.fflag = False
self.parent = parent
@@ -43,7 +44,7 @@ class QSendToELOG(QDialog):
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"])
@@ -51,6 +52,7 @@ class QSendToELOG(QDialog):
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)
@@ -144,7 +146,7 @@ class QSendToELOG(QDialog):
self.files = []
self.attributes = {}
self.layout = QVBoxLayout(self)
self.layout.addLayout(logbook)
self.layout.addLayout(self.applicationbox)
@@ -187,7 +189,7 @@ class QSendToELOG(QDialog):
self.fflag = True
filebox.addWidget(self.filesE)
openCloseVBox = QVBoxLayout()
self.openBtn = QPushButton('Add')
self.openBtn.setAutoDefault(False)
@@ -216,7 +218,7 @@ class QSendToELOG(QDialog):
self.messagelbl.setStyleSheet("QLabel { color : red; }")
self.layout.addWidget(self.messagelbl)
self.layout.addLayout(btnLayout)
self.setMinimumWidth(440)
self.exec()

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