11 Commits

Author SHA1 Message Date
bdad077350 logging levels modified; log interface for hipa added 2023-05-16 12:23:19 +02:00
051e361c9f base and guiframe 2023-05-01 09:48:14 +02:00
7cac3da421 overdue update 2023-04-05 14:17:18 +02:00
cb7a74d189 qtab composite widget update 2023-02-24 07:26:49 +01:00
9c2c5d7d37 qtab composite widget update 2023-02-23 08:33:44 +01:00
3640082b59 qtab composite widget added 2023-02-23 08:09:14 +01:00
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 1608 additions and 161 deletions

65
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.NOTSET)
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
@@ -441,7 +453,8 @@ class BaseWindow(QMainWindow):
from src.analysis import AnalysisProcedure from src.analysis import AnalysisProcedure
self.analysis_procedure = AnalysisProcedure(self) self.analysis_procedure = AnalysisProcedure(self)
except ImportError as e: except ImportError as e:
print("Import Error:", e) print(("Base class without user supplied AnalysisProcedure class."
+ " mport Error:"), e)
##self.trigger_elog_entry.connect(self.receive_elog_notification) ##self.trigger_elog_entry.connect(self.receive_elog_notification)
##self.trigger_hdf_save.connect(self.save_to_hdf) ##self.trigger_hdf_save.connect(self.save_to_hdf)
@@ -492,14 +505,20 @@ 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
elif self.facility == Facility.HIPA:
from pyqtacc.hipa.guiheader import GUIHeader
from pyqtacc.hipa.sendeloghipa 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:
@@ -517,7 +536,7 @@ class BaseWindow(QMainWindow):
self.mainwindow.setMinimumWidth(SLS_CENTRAL_WIDGET_MINIMUM_WIDTH) self.mainwindow.setMinimumWidth(SLS_CENTRAL_WIDGET_MINIMUM_WIDTH)
self.setCentralWidget(self.mainwindow) self.setCentralWidget(self.mainwindow)
self.show_log_message(MsgSeverity.INFO, _pymodule, _line(), self.show_log_message(MsgSeverity.INFO.name, _pymodule, _line(),
"Application configured") "Application configured")
@@ -553,7 +572,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 +618,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 +860,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 +1196,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 +1230,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 +1241,7 @@ class BaseWindow(QMainWindow):
QMessageBox.Ok) QMessageBox.Ok)
return return
'''
#_elog_sf = ElogSwissFEL() #_elog_sf = ElogSwissFEL()
_logbook = None _logbook = None
@@ -1227,6 +1251,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 +1741,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()
@@ -1834,6 +1867,9 @@ class BaseWindow(QMainWindow):
elif facility == Facility.SLS: elif facility == Facility.SLS:
from pyqtacc.qrc_resources.facility.sls.pyrcc5 import qrc_resources from pyqtacc.qrc_resources.facility.sls.pyrcc5 import qrc_resources
print("FACILITY SLS") print("FACILITY SLS")
elif facility == Facility.HIPA:
from pyqtacc.qrc_resources.facility.hipa.pyrcc5 import qrc_resources
print("FACILITY HIPA")
else: else:
print("Unknown Facility; assuming SLS") print("Unknown Facility; assuming SLS")
from pyqtacc.qrc_resources.facility.sls.pyrcc5 import qrc_resources from pyqtacc.qrc_resources.facility.sls.pyrcc5 import qrc_resources
@@ -1920,7 +1956,8 @@ class BaseWindow(QMainWindow):
int_seconds_remaining = int(delay - (now-start1)) int_seconds_remaining = int(delay - (now-start1))
seconds_remaining = '{:2d}'.format(int_seconds_remaining) seconds_remaining = '{:2d}'.format(int_seconds_remaining)
self.splash_progressbar.setValue(val) self.splash_progressbar.setValue(val)
self.processEvents() #self.processEvents()
self.flush()
sec_str = "s" if abs(int_seconds_remaining) != 1 else "" sec_str = "s" if abs(int_seconds_remaining) != 1 else ""
mess = """ mess = """
<br><p style='color:black; font-weight:bold; <br><p style='color:black; font-weight:bold;

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
@@ -35,6 +36,7 @@ class UserMode(IntEnum):
OPERATION = 1 OPERATION = 1
EXPERT = 2 EXPERT = 2
SIMULATION = 3 SIMULATION = 3

File diff suppressed because it is too large Load Diff

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