Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3c408ebcbd | |||
| 420f82563f | |||
| b2ad43abb0 | |||
| 75dc1e5e51 | |||
| d9167d044f | |||
| 4c151a8cd0 | |||
| 7f1981aac7 | |||
| d9f098582f | |||
| d865b9eba7 |
10
.gitignore
vendored
10
.gitignore
vendored
@@ -1,5 +1,7 @@
|
||||
# Temporary editor files #
|
||||
##########################
|
||||
*~
|
||||
|
||||
*.-*
|
||||
*.*:*
|
||||
*.*-
|
||||
*.*-*
|
||||
*.-*
|
||||
__pycache__
|
||||
__pycache__/*.*
|
||||
|
||||
Binary file not shown.
Binary file not shown.
61
pvgateway.py
61
pvgateway.py
@@ -96,6 +96,7 @@ class PVGateway(QWidget):
|
||||
notify_unison: bool = False, precision: int = 0,
|
||||
monitor_dbr_time: bool = False):
|
||||
|
||||
|
||||
super().__init__()
|
||||
|
||||
if parent is None:
|
||||
@@ -120,6 +121,8 @@ class PVGateway(QWidget):
|
||||
|
||||
self.color_mode = None
|
||||
|
||||
self.check_rtyp = False
|
||||
|
||||
if color_mode is not None:
|
||||
if color_mode in (self.ACT_ON_BEAM,
|
||||
self.NOT_ACT_ON_BEAM,
|
||||
@@ -129,6 +132,10 @@ class PVGateway(QWidget):
|
||||
|
||||
self.color_mode_requested = self.color_mode
|
||||
|
||||
#if 'READ' in self.pv_name:
|
||||
#print('color mode',self.pv_name, self.color_mode,
|
||||
#self.color_mode_requested )
|
||||
|
||||
if monitor_callback is not None:
|
||||
self.monitor_callback = monitor_callback
|
||||
else:
|
||||
@@ -143,9 +150,13 @@ class PVGateway(QWidget):
|
||||
self.cafe = self.parent.cafe
|
||||
self.cyca = self.parent.cyca
|
||||
|
||||
self.url_archiver = None
|
||||
self.url_databuffer = None
|
||||
|
||||
if self.parent.settings is not None:
|
||||
self.url_archiver = self.parent.settings.data["url"]["archiver"]
|
||||
self.url_databuffer = self.parent.settings.data["url"]["databuffer"]
|
||||
if "databuffer" in self.parent.settings.data["url"]:
|
||||
self.url_databuffer = self.parent.settings.data["url"]["databuffer"]
|
||||
self.bg_readback = self.parent.settings.data["StyleGuide"][
|
||||
"bgReadback"]
|
||||
self.fg_alarm_major = self.parent.settings.data["StyleGuide"][
|
||||
@@ -158,10 +169,10 @@ class PVGateway(QWidget):
|
||||
"fgAlarmNoAlarm"]
|
||||
else:
|
||||
#self.settings = ReadJSON(self.parent.appname)
|
||||
self.url_archiver = ("https://ui-data-api.psi.ch/prepare?channel=" +
|
||||
self.url_archiver = ("https://data-ui.psi.ch/preselect?c1=" +
|
||||
"sf-archiverappliance/")
|
||||
self.url_databuffer \
|
||||
= "https://ui-data-api.psi.ch/prepare?channel=sf-databuffer/"
|
||||
= "https://data-ui.psi.ch/preselect?c1=sf-databuffer/"
|
||||
|
||||
self.daq_group_name = self._DAQ_CAFE_SG_NAME
|
||||
self.desc = None
|
||||
@@ -176,6 +187,7 @@ class PVGateway(QWidget):
|
||||
self.monitor_id = None
|
||||
self.monitor_dbr_time = monitor_dbr_time
|
||||
self.mutex_post_display = QMutex()
|
||||
self.mutex = QMutex()
|
||||
|
||||
self.precision_user = precision
|
||||
self.has_precision_user = bool(precision)
|
||||
@@ -266,23 +278,20 @@ class PVGateway(QWidget):
|
||||
|
||||
action1 = QAction("Text Info", self)
|
||||
action1.triggered.connect(self.pv_status_text)
|
||||
|
||||
self.context_menu.addAction(action1)
|
||||
action2 = QAction("Lookup in Archiver", self)
|
||||
action2.triggered.connect(self.lookup_archiver)
|
||||
|
||||
action3 = QAction("Lookup in Databuffer", self)
|
||||
action3.triggered.connect(self.lookup_databuffer)
|
||||
|
||||
self.context_menu.addAction(action2)
|
||||
if self.url_databuffer is not None:
|
||||
action3 = QAction("Lookup in Databuffer", self)
|
||||
action3.triggered.connect(self.lookup_databuffer)
|
||||
self.context_menu.addAction(action3)
|
||||
action4 = QAction("Strip Chart (PShell)", self)
|
||||
action4.triggered.connect(self.strip_chart)
|
||||
|
||||
self.context_menu.addAction(action4)
|
||||
action6 = QAction("Configure Display Parameters", self)
|
||||
action6.triggered.connect(self.display_parameters)
|
||||
|
||||
self.context_menu.addAction(action1)
|
||||
self.context_menu.addAction(action2)
|
||||
self.context_menu.addAction(action3)
|
||||
self.context_menu.addAction(action4)
|
||||
|
||||
action5 = QAction("Reconnect: {0}".format(self.pv_name), self)
|
||||
action5.triggered.connect(self.reconnect_channel)
|
||||
@@ -310,6 +319,7 @@ class PVGateway(QWidget):
|
||||
#The __init__ method of a class is used to initialize new objects,
|
||||
#not create them. As such, it should not return any value.
|
||||
|
||||
|
||||
return #self # used by pvgateway in CAQStripChart
|
||||
|
||||
|
||||
@@ -378,7 +388,7 @@ class PVGateway(QWidget):
|
||||
|
||||
if self.pv_info is None:
|
||||
self.pv_info = self.cafe.getChannelInfo(self.pv_name)
|
||||
if "Not Supported" in self.pv_info.className:
|
||||
if "Not Supported" in self.pv_info.className and self.check_rtyp:
|
||||
_rtype = self.cafe.get(self.pv_name.split(".")[0] + ".RTYP")
|
||||
self.record_type = _rtype if _rtype is not None else \
|
||||
self.pv_info.className
|
||||
@@ -411,8 +421,9 @@ class PVGateway(QWidget):
|
||||
_max_control_abs = 0
|
||||
|
||||
if self.pv_ctrl is not None:
|
||||
_lower_control_abs = abs(int(self.pv_ctrl.lowerControlLimit))
|
||||
_upper_control_abs = abs(int(self.pv_ctrl.upperControlLimit))
|
||||
#DisplayLimit preferred over ControlLimit as latter n/a for ao
|
||||
_lower_control_abs = abs(int(self.pv_ctrl.lowerDisplayLimit))
|
||||
_upper_control_abs = abs(int(self.pv_ctrl.upperDisplayLimit))
|
||||
_max_control_abs = max(_lower_control_abs, _upper_control_abs)
|
||||
if _max_control_abs is None:
|
||||
_max_control_abs = 0
|
||||
@@ -487,7 +498,7 @@ class PVGateway(QWidget):
|
||||
time.sleep(0.01)
|
||||
self.initialize_meta_data()
|
||||
icount += 1
|
||||
if icount > 50:
|
||||
if icount > 5: #50
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -576,7 +587,7 @@ class PVGateway(QWidget):
|
||||
self.pv_ctrl = self.cafe.getCtrlCache(self.handle)
|
||||
self.pv_info = self.cafe.getChannelInfo(self.handle)
|
||||
if self.pv_info is not None and self.record_type is None:
|
||||
if "Not Supported" in self.pv_info.className:
|
||||
if "Not Supported" in self.pv_info.className and self.check_rtyp:
|
||||
_rtype = self.cafe.get(self.pv_name.split(".")[0] + ".RTYP")
|
||||
self.record_type = _rtype if _rtype is not None else \
|
||||
self.pv_info.className
|
||||
@@ -754,6 +765,7 @@ class PVGateway(QWidget):
|
||||
'''Callback function to be invoked on change of pv value.
|
||||
cafe.getCache and cafe.set operations permitted within callback.
|
||||
'''
|
||||
self.mutex.lock()
|
||||
|
||||
pv_name = pvname
|
||||
pvd = pvdata
|
||||
@@ -785,8 +797,8 @@ class PVGateway(QWidget):
|
||||
else:
|
||||
self.trigger_monitor_float.emit(float(pvd.value[0]), pvd.status,
|
||||
_alarm_severity)
|
||||
|
||||
|
||||
self.mutex.unlock()
|
||||
|
||||
def monitor_start(self):
|
||||
'''Initiate monitor on pv.'''
|
||||
if self.handle > 0:
|
||||
@@ -942,6 +954,8 @@ class PVGateway(QWidget):
|
||||
elif self.qt_object_name == self.PV_DAQ_BS:
|
||||
self.color_mode = self.READBACK_STATIC
|
||||
|
||||
#if 'READ' in self.pv_name:
|
||||
# print('color mode',self.pv_name, self.color_mode)
|
||||
self._qt_dynamic_property_set(self.color_mode)
|
||||
|
||||
else:
|
||||
@@ -1332,7 +1346,7 @@ class PVGateway(QWidget):
|
||||
if self.pv_info is None:
|
||||
self.pv_info = self.cafe.getChannelInfo(self.handle)
|
||||
if self.pv_info is not None and self.record_type is None:
|
||||
if "Not Supported" in self.pv_info.className:
|
||||
if "Not Supported" in self.pv_info.className and self.check_rtyp:
|
||||
_rtype = self.cafe.get(self.pv_name.split(".")[0] + ".RTYP")
|
||||
self.record_type = _rtype if _rtype is not None else \
|
||||
self.pv_info.className
|
||||
@@ -1376,7 +1390,7 @@ class PVGateway(QWidget):
|
||||
if self.pv_info is None:
|
||||
self.pv_info = self.cafe.getChannelInfo(self.handle)
|
||||
if self.pv_info is not None and self.record_type is None:
|
||||
if "Not Supported" in self.pv_info.className:
|
||||
if "Not Supported" in self.pv_info.className and self.check_rtyp:
|
||||
_rtype = self.cafe.get(self.pv_name.split(".")[0] + ".RTYP")
|
||||
self.record_type = _rtype if _rtype is not None else \
|
||||
self.pv_info.className
|
||||
@@ -1481,8 +1495,7 @@ class PVGateway(QWidget):
|
||||
self.pv_status_text_display_limits())
|
||||
|
||||
self.pv_message_in_a_box.setText(
|
||||
self.pv_status_text_header(source=_source) + _text_data
|
||||
)
|
||||
self.pv_status_text_header(source=_source) + _text_data)
|
||||
QApplication.processEvents()
|
||||
self.pv_message_in_a_box.exec()
|
||||
|
||||
|
||||
@@ -96,14 +96,17 @@ class PVGateway(QWidget):
|
||||
notify_unison: bool = False, precision: int = 0,
|
||||
monitor_dbr_time: bool = False):
|
||||
|
||||
|
||||
super().__init__()
|
||||
|
||||
|
||||
if parent is None:
|
||||
return
|
||||
|
||||
if not pv_name:
|
||||
return
|
||||
|
||||
|
||||
self.connect_callback = connect_callback
|
||||
self.notify_freq_hz = abs(notify_freq_hz)
|
||||
self.notify_freq_hz_default = self.notify_freq_hz
|
||||
@@ -307,8 +310,11 @@ class PVGateway(QWidget):
|
||||
self.pv_message_in_a_box.setDefaultButton(QMessageBox.Close)
|
||||
|
||||
self.initialize()
|
||||
|
||||
#return self - previously used by pvgateway
|
||||
#The __init__ method of a class is used to initialize new objects,
|
||||
#not create them. As such, it should not return any value.
|
||||
|
||||
|
||||
return #self # used by pvgateway in CAQStripChart
|
||||
|
||||
|
||||
def initialize(self):
|
||||
|
||||
1910
pvgateway.py:2.9
Normal file
1910
pvgateway.py:2.9
Normal file
File diff suppressed because it is too large
Load Diff
546
pvwidgets.py
546
pvwidgets.py
@@ -1,26 +1,28 @@
|
||||
''' Module with channel access enabled QtWidgets.'''
|
||||
__author__ = 'Jan T. M. Chrin'
|
||||
|
||||
import collections
|
||||
import numpy as np
|
||||
import re
|
||||
from threading import Lock
|
||||
import time
|
||||
|
||||
import collections
|
||||
import numpy as np
|
||||
|
||||
from sklearn.linear_model import LinearRegression
|
||||
from distutils.version import LooseVersion
|
||||
from functools import reduce as func_reduce
|
||||
|
||||
from qtpy.QtCore import QEventLoop, QPoint, Qt, QThread, QTimer, Signal, Slot
|
||||
from qtpy.QtGui import (QCloseEvent, QColor, QCursor, QFont, QFontMetricsF,
|
||||
QIcon, QKeySequence)
|
||||
from qtpy.QtCore import (
|
||||
QEventLoop, QMutex, QPoint, Qt, QThread, QTimer, Signal, Slot)
|
||||
from qtpy.QtGui import (
|
||||
QCloseEvent, QColor, QCursor, QFont, QFontMetricsF, QIcon, QKeySequence)
|
||||
from qtpy.QtCore import __version__ as QT_VERSION_STR
|
||||
from qtpy.QtWidgets import (QAbstractItemView, QAbstractSpinBox, QAction,
|
||||
QApplication, QBoxLayout, QCheckBox, QComboBox,
|
||||
QDialog, QDockWidget, QDoubleSpinBox, QFrame,
|
||||
QGroupBox, QHBoxLayout, QLabel, QLineEdit,
|
||||
QListWidget, QMenu, QMessageBox, QPushButton,
|
||||
QSpinBox, QStyle, QStyleOptionSpinBox, QTableWidget,
|
||||
QTableWidgetItem, QVBoxLayout, QWidget)
|
||||
from qtpy.QtWidgets import (
|
||||
QAbstractItemView, QAbstractSpinBox, QAction, QApplication, QBoxLayout,
|
||||
QCheckBox, QComboBox, QDialog, QDockWidget, QDoubleSpinBox, QFrame,
|
||||
QGroupBox, QHBoxLayout, QLabel, QLineEdit, QListWidget, QMenu, QMessageBox,
|
||||
QPushButton, QSpinBox, QStyle, QStyleOptionSpinBox, QTableWidget,
|
||||
QTableWidgetItem, QVBoxLayout, QWidget)
|
||||
|
||||
import pyqtgraph as pg
|
||||
from pyqtgraph import PlotWidget
|
||||
@@ -129,6 +131,7 @@ class CAQLineEdit(QLineEdit, PVGateway):
|
||||
_width_scaling_factor = 1.15
|
||||
self.setFixedHeight((fm.lineSpacing()*1.8))
|
||||
self.setFixedWidth(((qrect.width()) * _width_scaling_factor))
|
||||
|
||||
|
||||
if self.pv_within_daq_group:
|
||||
self.qt_property_initial_values(qt_object_name=self.PV_DAQ_CA)
|
||||
@@ -284,7 +287,6 @@ class CAQMenu(QComboBox, PVGateway):
|
||||
|
||||
def post_display_value(self, value):
|
||||
|
||||
|
||||
'''Convert value to index'''
|
||||
if "setCurrentIndex" in dir(self):
|
||||
|
||||
@@ -294,7 +296,6 @@ class CAQMenu(QComboBox, PVGateway):
|
||||
if isinstance(value, str):
|
||||
self.setCurrentIndex(self.cafe.getEnumFromString(self.handle,
|
||||
value))
|
||||
|
||||
elif isinstance(value, int):
|
||||
self.setCurrentIndex(value)
|
||||
#Should not happen
|
||||
@@ -462,13 +463,13 @@ class CAQMessageButton(QPushButton, PVGateway):
|
||||
self.setFocusPolicy(Qt.StrongFocus)
|
||||
self.setCheckable(True) #Recognizes press and release states
|
||||
|
||||
fm = QFontMetricsF(QFont("Sans Serif", 12))
|
||||
fm = QFontMetricsF(QFont("Sans Serif", 10))
|
||||
qrect = fm.boundingRect(self.suggested_text)
|
||||
|
||||
_width_scaling_factor = 1.0
|
||||
|
||||
self.setText(self.msg_label)
|
||||
self.setFixedHeight((fm.lineSpacing()*2.0))
|
||||
self.setFixedHeight((fm.lineSpacing()*1.8))
|
||||
self.setFixedWidth((qrect.width() * _width_scaling_factor))
|
||||
|
||||
self.qt_property_initial_values(qt_object_name=self.PV_CONTROLLER)
|
||||
@@ -987,6 +988,8 @@ class CAQDoubleSpinBox(QDoubleSpinBox, PVGateway):
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
self.clearFocus()
|
||||
self.lineEdit().clearFocus()
|
||||
|
||||
|
||||
def setValue(self, value):
|
||||
self.currentValue = self.value()
|
||||
@@ -1044,14 +1047,18 @@ class CAQDoubleSpinBox(QDoubleSpinBox, PVGateway):
|
||||
self.qt_style_polish()
|
||||
|
||||
self.clearFocus()
|
||||
self.lineEdit().clearFocus()
|
||||
self.lineEdit().setFocusPolicy(Qt.NoFocus)
|
||||
self.setFocusPolicy(Qt.NoFocus)
|
||||
del event
|
||||
|
||||
def keyPressEvent(self, event):
|
||||
|
||||
if event.key() in (Qt.Key_Return, Qt.Key_Enter):
|
||||
QDoubleSpinBox.keyPressEvent(self, event)
|
||||
self.clearFocus()
|
||||
self.lineEdit().clearFocus()
|
||||
self.lineEdit().setFocusPolicy(Qt.NoFocus)
|
||||
self.setFocusPolicy(Qt.NoFocus)
|
||||
elif event.key() in (Qt.Key_Up, Qt.Key_Down):
|
||||
QDoubleSpinBox.keyPressEvent(self, event)
|
||||
else:
|
||||
@@ -1098,16 +1105,29 @@ class reconnectQPushButton(QPushButton, QThread):
|
||||
def reconnect(self):
|
||||
QApplication.processEvents()
|
||||
|
||||
print("Reconnect")
|
||||
self.isdirty = True
|
||||
if self._handles_to_reconnect:
|
||||
print("handles to reconnect", self._handles_to_reconnect, flush=True)
|
||||
self.parent.cafe.reconnect(self._handles_to_reconnect)
|
||||
print("handles reconnected", self._handles_to_reconnect, flush=True)
|
||||
self.isdirty = False
|
||||
#Uncheck reconnected channels
|
||||
for i in range(0, len(self.parent.pv_gateway)):
|
||||
#print(i, len(self.parent.pv_gateway), flush=True)
|
||||
#print( "ischecked", self.parent.item(
|
||||
# i, self.parent.no_columns-1).checkState(), Qt.Checked )
|
||||
#print("Connected", self.parent.cafe.isConnected(
|
||||
# self.parent.pv_gateway[i].handle), flush=True)
|
||||
if self.parent.item(
|
||||
i, self.parent.no_columns-1).checkState() == Qt.Checked:
|
||||
if self.parent.cafe.isConnected(
|
||||
self.parent.pv_gateway[i].handle):
|
||||
#print("isConnected", flush=True)
|
||||
self.parent.item(
|
||||
i, self.parent.no_columns-1).setCheckState(False)
|
||||
else:
|
||||
#Even if not connected - uncheck box as action is complete
|
||||
self.parent.item(
|
||||
i, self.parent.no_columns-1).setCheckState(False)
|
||||
|
||||
@@ -1194,9 +1214,10 @@ class CAQTableWidget(QTableWidget):
|
||||
def widget_update(self):
|
||||
|
||||
for _row, pvgate in enumerate(self.pv_gateway):
|
||||
#for _row in range(0, len(self.pv_gateway)):
|
||||
|
||||
if not pvgate.notify_unison:
|
||||
continue
|
||||
|
||||
_handle = pvgate.handle
|
||||
_pvd = pvgate.cafe.getPVCache(_handle)
|
||||
|
||||
@@ -1216,10 +1237,14 @@ class CAQTableWidget(QTableWidget):
|
||||
f.setPointSize(8)
|
||||
qtwi.setFont(f)
|
||||
|
||||
self.setItem(_row, self.no_columns-3,
|
||||
val_col_no = self.columns_dict['Value']
|
||||
if self.show_timestamp:
|
||||
ts_col_no = self.columns_dict['Timestamp']
|
||||
|
||||
self.setItem(_row, val_col_no,
|
||||
QTableWidgetItem(qtwi))
|
||||
self.item(_row, self.no_columns-3).setTextAlignment(Qt.AlignRight |
|
||||
Qt.AlignVCenter)
|
||||
self.item(_row, val_col_no).setTextAlignment(Qt.AlignRight |
|
||||
Qt.AlignVCenter)
|
||||
|
||||
_ts_date = _pvd.tsDateAsString
|
||||
_ts_str_len = len(_ts_date)
|
||||
@@ -1245,8 +1270,9 @@ class CAQTableWidget(QTableWidget):
|
||||
f.setPointSize(8)
|
||||
qtwi.setFont(f)
|
||||
|
||||
self.setItem(_row, self.no_columns-2, QTableWidgetItem(qtwi))
|
||||
self.item(_row, self.no_columns-2).setTextAlignment(Qt.AlignCenter)
|
||||
if self.show_timestamp:
|
||||
self.setItem(_row, ts_col_no, QTableWidgetItem(qtwi))
|
||||
self.item(_row, ts_col_no).setTextAlignment(Qt.AlignCenter)
|
||||
|
||||
_prop = pvgate.qt_dynamic_property_get()
|
||||
|
||||
@@ -1268,31 +1294,29 @@ class CAQTableWidget(QTableWidget):
|
||||
_fgcolor = "black"
|
||||
|
||||
#Colors for bg/fg reversed as is the old norm
|
||||
self.item(_row, self.no_columns-3).setBackground(
|
||||
QColor(_bgcolor))
|
||||
self.item(_row, self.no_columns-2).setBackground(
|
||||
QColor(_bgcolor))
|
||||
self.item(_row, self.no_columns-3).setForeground(
|
||||
QColor(_fgcolor))
|
||||
self.item(_row, self.no_columns-2).setForeground(
|
||||
QColor(_fgcolor))
|
||||
self.item(_row, val_col_no).setBackground(QColor(_bgcolor))
|
||||
self.item(_row, val_col_no).setForeground(QColor(_fgcolor))
|
||||
|
||||
if self.show_timestamp:
|
||||
self.item(_row, ts_col_no).setBackground(QColor(_bgcolor))
|
||||
self.item(_row, ts_col_no).setForeground(QColor(_fgcolor))
|
||||
|
||||
elif _prop == pvgate.READBACK_STATIC:
|
||||
|
||||
self.item(_row, self.no_columns-3).setBackground(
|
||||
QColor(pvgate.bg_readback))
|
||||
self.item(_row, self.no_columns-2).setBackground(
|
||||
self.item(_row, val_col_no).setBackground(
|
||||
QColor(pvgate.bg_readback))
|
||||
if self.show_timestamp:
|
||||
self.item(_row, ts_col_no).setBackground(
|
||||
QColor(pvgate.bg_readback))
|
||||
|
||||
elif _prop == pvgate.DISCONNECTED:
|
||||
self.item(_row, self.no_columns-3).setBackground(
|
||||
self.item(_row, val_col_no).setBackground(
|
||||
QColor("#ffffff"))
|
||||
self.item(_row, self.no_columns-2).setBackground(
|
||||
QColor("#ffffff"))
|
||||
self.item(_row, self.no_columns-3).setForeground(
|
||||
QColor("#777777"))
|
||||
self.item(_row, self.no_columns-2).setForeground(
|
||||
self.item(_row, val_col_no).setForeground(
|
||||
QColor("#777777"))
|
||||
if self.show_timestamp:
|
||||
self.item(_row, ts_col_no).setBackground(QColor("#ffffff"))
|
||||
self.item(_row, ts_col_no).setForeground(QColor("#777777"))
|
||||
|
||||
else:
|
||||
print(_prop, "widget_update unknown in element/row", _row,
|
||||
@@ -1305,6 +1329,8 @@ class CAQTableWidget(QTableWidget):
|
||||
color_mode=None, show_units: bool = True, prefix: str = "",
|
||||
suffix: str = "", ts_res: str = "milli",
|
||||
init_column: bool = False, init_list: list = [],
|
||||
standby_column: bool = False, standby_list: list = [],
|
||||
standby_values: list = [], set_delay: float = 0.0,
|
||||
notify_freq_hz: int = 0, notify_unison: bool = True,
|
||||
precision: int = 0, scale_factor: float = 1,
|
||||
show_timestamp: bool = True, pv_list_show: list = None):
|
||||
@@ -1312,27 +1338,47 @@ class CAQTableWidget(QTableWidget):
|
||||
super().__init__()
|
||||
self.columns_dict = {}
|
||||
_column_dict_value = 0
|
||||
self.columns_dict['PV'] = _column_dict_value
|
||||
if init_column:
|
||||
|
||||
if pv_list_show is not None:
|
||||
if pv_list_show[0]:
|
||||
self.columns_dict['PV'] = _column_dict_value
|
||||
_column_dict_value += 1
|
||||
else:
|
||||
self.columns_dict['PV'] = _column_dict_value
|
||||
_column_dict_value += 1
|
||||
|
||||
if init_column:
|
||||
self.columns_dict['Init'] = _column_dict_value
|
||||
_column_dict_value += 1
|
||||
_column_dict_value += 1
|
||||
|
||||
if standby_column:
|
||||
self.columns_dict['Standby'] = _column_dict_value
|
||||
_column_dict_value += 1
|
||||
|
||||
self.columns_dict['Value'] = _column_dict_value
|
||||
|
||||
if show_timestamp:
|
||||
_column_dict_value += 1
|
||||
self.columns_dict['Timestamp'] = _column_dict_value
|
||||
|
||||
_column_dict_value += 1
|
||||
self.columns_dict['Reconnect'] = _column_dict_value
|
||||
|
||||
self.setWindowModality(Qt.ApplicationModal)
|
||||
self.no_columns = _column_dict_value + 1
|
||||
self.no_columns = _column_dict_value + 1
|
||||
|
||||
self.init_column = init_column
|
||||
|
||||
self.init_list = init_list
|
||||
if self.init_column and not self.init_list:
|
||||
self.init_list = pv_list
|
||||
|
||||
self.standby_column = standby_column
|
||||
self.standby_list = standby_list
|
||||
if self.standby_column and not self.standby_list:
|
||||
self.standby_list = pv_list
|
||||
self.standby_values = standby_values
|
||||
self.set_delay = set_delay
|
||||
|
||||
self.icount = 0
|
||||
self.notify_freq_hz = abs(notify_freq_hz)
|
||||
self.notify_freq_hz_default = self.notify_freq_hz
|
||||
@@ -1374,9 +1420,13 @@ class CAQTableWidget(QTableWidget):
|
||||
|
||||
_color_mode = [None] * len(self.pv_list)
|
||||
|
||||
if isinstance(color_mode, list):
|
||||
for i in range(0, len(color_mode)):
|
||||
_color_mode[i] = color_mode[i]
|
||||
if color_mode is not None:
|
||||
if isinstance(color_mode, list):
|
||||
for i in range(0, len(color_mode)):
|
||||
_color_mode[i] = color_mode[i]
|
||||
else:
|
||||
for i in range(0, len(_color_mode)):
|
||||
_color_mode[i] = color_mode
|
||||
|
||||
for i in range(0, len(self.pv_list)):
|
||||
|
||||
@@ -1412,6 +1462,7 @@ class CAQTableWidget(QTableWidget):
|
||||
self.timer.singleShot(0, self.widget_update)
|
||||
self.timer.start(self.notify_milliseconds)
|
||||
|
||||
self.reconnect_button = None
|
||||
self.configure_widget()
|
||||
|
||||
#Connect only deals with colours - only helps on reconnect
|
||||
@@ -1427,7 +1478,11 @@ class CAQTableWidget(QTableWidget):
|
||||
if not self.pv_gateway[i].pv_within_daq_group:
|
||||
self.pv_gateway[i].monitor_start()
|
||||
|
||||
self.update_init_values()
|
||||
if init_column:
|
||||
self.update_init_values()
|
||||
|
||||
if standby_column:
|
||||
self.update_standby_values()
|
||||
|
||||
self.configure_context_menu()
|
||||
|
||||
@@ -1450,7 +1505,108 @@ class CAQTableWidget(QTableWidget):
|
||||
QApplication.processEvents()
|
||||
|
||||
|
||||
|
||||
def set_standby_values(self, pv_list: list = []):
|
||||
if self.init_column:
|
||||
self.init_value_button.setEnabled(False)
|
||||
self.restore_value_button.setEnabled(False)
|
||||
|
||||
_text = self.standby_value_button.text()
|
||||
self.standby_value_button.setText("Downing")
|
||||
self.standby_value_button.setEnabled(False)
|
||||
|
||||
if self.reconnect_button is not None:
|
||||
self.reconnect_button.setEnabled(False)
|
||||
|
||||
|
||||
_set_values_dict = self.get_standby_values()
|
||||
|
||||
#return 1,2,3
|
||||
|
||||
if not pv_list:
|
||||
_pvs_to_set, _values_to_set = zip(*_set_values_dict.items())
|
||||
#zip returns tuples
|
||||
_pvs_to_set = list(_pvs_to_set)
|
||||
_values_to_set = list(_values_to_set)
|
||||
else:
|
||||
_pvs_to_set = []
|
||||
_values_to_set = []
|
||||
for pv in pv_list:
|
||||
if pv in _set_values_dict.keys():
|
||||
_pvs_to_set.append(pv)
|
||||
_values_to_set.append(_set_values_dict[pv])
|
||||
|
||||
#self.standby_value_button.setEnabled(False)
|
||||
#QApplication.processEvents(QEventLoop.AllEvents, 1.0)
|
||||
|
||||
if self.set_delay <= 0:
|
||||
status, status_list = self.cafe.setScalarList(_pvs_to_set,
|
||||
_values_to_set)
|
||||
else:
|
||||
status_list = [self.cyca.ICAFE_NORMAL] * len(_pvs_to_set)
|
||||
status = self.cyca.ICAFE_NORMAL
|
||||
for i, (pv, val) in enumerate(zip(_pvs_to_set, _values_to_set)):
|
||||
status_list[i] = self.cafe.set(pv, val)
|
||||
if status_list[i] != self.cyca.ICAFE_NORMAL:
|
||||
status = status_list[i]
|
||||
|
||||
##self.standby_value_button.setEnabled(False)
|
||||
##QApplication.processEvents(QEventLoop.AllEvents, 1.0)
|
||||
time.sleep(self.set_delay)
|
||||
##self.standby_value_button.setEnabled(False)
|
||||
#QApplication.sendPostedEvents()
|
||||
QApplication.processEvents(QEventLoop.AllEvents, 1.0)
|
||||
|
||||
if status != self.cyca.ICAFE_NORMAL:
|
||||
_mess = ("The following devices reported an error " +
|
||||
"in 'set' operation:")
|
||||
for i, status_value in enumerate(status_list):
|
||||
if status_value != self.cyca.ICAFE_NORMAL:
|
||||
_mess += ("\n" + _pvs_to_set[i] + " has status = " +
|
||||
str(status_value) + " " +
|
||||
self.cafe.getStatusCodeAsString(status_value)
|
||||
+ " " + self.cafe.getStatusInfo(status_value))
|
||||
qm = QMessageBox()
|
||||
qm.setText(_mess)
|
||||
#qm.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
|
||||
#qm.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
||||
#qm.setFixedWidth(800)
|
||||
##self.standby_value_button.setEnabled(False)
|
||||
##QApplication.sendPostedEvents()
|
||||
qm.exec()
|
||||
#QApplication.processEvents()
|
||||
|
||||
|
||||
if self.init_column:
|
||||
self.init_value_button.setEnabled(True)
|
||||
self.restore_value_button.setEnabled(True)
|
||||
|
||||
|
||||
self.standby_value_button.setText(_text)
|
||||
self.standby_value_button.setEnabled(True)
|
||||
if self.reconnect_button is not None:
|
||||
self.reconnect_button.setEnabled(True)
|
||||
|
||||
return status, status_list, _pvs_to_set
|
||||
|
||||
|
||||
|
||||
|
||||
def restore_init_values(self, pv_list: list = []):
|
||||
|
||||
_text = self.restore_value_button.text()
|
||||
self.restore_value_button.setText("Restoring")
|
||||
self.restore_value_button.setEnabled(False)
|
||||
|
||||
if self.init_column:
|
||||
self.init_value_button.setEnabled(False)
|
||||
|
||||
if self.standby_column:
|
||||
self.standby_value_button.setEnabled(False)
|
||||
|
||||
if self.reconnect_button is not None:
|
||||
self.reconnect_button.setEnabled(False)
|
||||
|
||||
_set_values_dict = self.get_init_values()
|
||||
|
||||
if not pv_list:
|
||||
@@ -1466,8 +1622,19 @@ class CAQTableWidget(QTableWidget):
|
||||
_pvs_to_set.append(pv)
|
||||
_values_to_set.append(_set_values_dict[pv])
|
||||
|
||||
status, status_list = self.cafe.setScalarList(_pvs_to_set,
|
||||
_values_to_set)
|
||||
|
||||
if self.set_delay <= 0:
|
||||
status, status_list = self.cafe.setScalarList(_pvs_to_set,
|
||||
_values_to_set)
|
||||
else:
|
||||
status_list = [self.cyca.ICAFE_NORMAL] * len(_pvs_to_set)
|
||||
status = self.cyca.ICAFE_NORMAL
|
||||
for i, (pv, val) in enumerate(zip(_pvs_to_set, _values_to_set)):
|
||||
status_list[i] = self.cafe.set(pv, val)
|
||||
if status_list[i] != self.cyca.ICAFE_NORMAL:
|
||||
status = status_list[i]
|
||||
time.sleep(self.set_delay)
|
||||
QApplication.processEvents(QEventLoop.AllEvents, 1.0)
|
||||
|
||||
if status != self.cyca.ICAFE_NORMAL:
|
||||
_mess = ("The following device(s) reported an error " +
|
||||
@@ -1480,12 +1647,23 @@ class CAQTableWidget(QTableWidget):
|
||||
" " + self.cafe.getStatusInfo(status_value))
|
||||
qm = QMessageBox()
|
||||
qm.setText(_mess)
|
||||
|
||||
|
||||
qm.exec()
|
||||
QApplication.processEvents()
|
||||
|
||||
self.init_value_button.setEnabled(True)
|
||||
if self.init_column:
|
||||
self.init_value_button.setEnabled(True)
|
||||
|
||||
self.restore_value_button.setText(_text)
|
||||
self.restore_value_button.setEnabled(True)
|
||||
|
||||
if self.standby_column:
|
||||
self.standby_value_button.setEnabled(True)
|
||||
|
||||
if self.reconnect_button is not None:
|
||||
self.reconnect_button.setEnabled(True)
|
||||
|
||||
return status, status_list, _pvs_to_set
|
||||
|
||||
def is_same_as_init_values(self):
|
||||
_init_values_dict = self.get_column_values(self.columns_dict['Init'])
|
||||
@@ -1528,6 +1706,8 @@ class CAQTableWidget(QTableWidget):
|
||||
|
||||
if _pvs[_row] in self.pv_list_show:
|
||||
_values_dict[self.pv_gateway[_row].pv_name] = _values[_row]
|
||||
else:
|
||||
_values_dict[_row] = _values[_row]
|
||||
|
||||
return _values_dict #_pvs_to_set, _values_to_set
|
||||
|
||||
@@ -1535,6 +1715,9 @@ class CAQTableWidget(QTableWidget):
|
||||
def get_init_values(self):
|
||||
return self.get_column_values(self.columns_dict['Init'])
|
||||
|
||||
def get_standby_values(self):
|
||||
return self.get_column_values(self.columns_dict['Standby'])
|
||||
|
||||
def get_init_values_previous(self):
|
||||
_set_values_dict = {}
|
||||
_start = 0
|
||||
@@ -1562,17 +1745,69 @@ class CAQTableWidget(QTableWidget):
|
||||
_set_values_dict[
|
||||
self.pv_gateway[_row].pv_name] = _values_to_set[_row]
|
||||
|
||||
|
||||
|
||||
return _set_values_dict
|
||||
|
||||
|
||||
def update_standby_values(self):
|
||||
_start = 0
|
||||
_end = len(self.standby_values)
|
||||
if 'Standby' in self.columns_dict:
|
||||
_column_no = self.columns_dict['Standby']
|
||||
else:
|
||||
return
|
||||
|
||||
for _row in range(_start, _end):
|
||||
_value = self.standby_values[_row]
|
||||
|
||||
if self.scale_factor != 1:
|
||||
_value = _value * self.scale_factor
|
||||
_value = self.pv_gateway[_row].format_display_value(_value)
|
||||
qtwi = QTableWidgetItem(str(_value)+ " ")
|
||||
_f = qtwi.font()
|
||||
_f.setPointSize(8)
|
||||
qtwi.setFont(_f)
|
||||
self.setItem(_row, _column_no, qtwi)
|
||||
self.item(_row, _column_no).setTextAlignment(Qt.AlignRight |
|
||||
Qt.AlignVCenter)
|
||||
|
||||
|
||||
def set_init_values(self, values):
|
||||
_start = 0
|
||||
_end = min(len(self.pv_gateway), len(values))
|
||||
|
||||
if 'Init' in self.columns_dict:
|
||||
_column_no = self.columns_dict['Init']
|
||||
else:
|
||||
return
|
||||
|
||||
for _row in range(_start, _end):
|
||||
_value = self.pv_gateway[_row].format_display_value(values[_row])
|
||||
qtwi = QTableWidgetItem(str(_value)+ " ")
|
||||
_f = qtwi.font()
|
||||
_f.setPointSize(8)
|
||||
qtwi.setFont(_f)
|
||||
self.setItem(_row, _column_no, qtwi)
|
||||
self.item(_row, _column_no).setTextAlignment(Qt.AlignRight |
|
||||
Qt.AlignVCenter)
|
||||
|
||||
|
||||
def update_init_values(self):
|
||||
_start = 0
|
||||
_end = len(self.pv_gateway)
|
||||
|
||||
if 'Init' in self.columns_dict:
|
||||
_column_no = self.columns_dict['Init']
|
||||
else:
|
||||
return
|
||||
|
||||
for _row in range(_start, _end):
|
||||
|
||||
|
||||
_handle = self.pv_gateway[_row].handle
|
||||
_value = self.pv_gateway[_row].cafe.getCache(_handle)
|
||||
|
||||
|
||||
if _value is not None:
|
||||
if self.scale_factor != 1:
|
||||
_value = _value * self.scale_factor
|
||||
@@ -1582,9 +1817,11 @@ class CAQTableWidget(QTableWidget):
|
||||
_f = qtwi.font()
|
||||
_f.setPointSize(8)
|
||||
qtwi.setFont(_f)
|
||||
self.setItem(_row, 1, qtwi)
|
||||
self.item(_row, 1).setTextAlignment(Qt.AlignRight | Qt.AlignVCenter)
|
||||
self.setItem(_row, _column_no, qtwi)
|
||||
|
||||
self.item(_row, _column_no).setTextAlignment(Qt.AlignRight |
|
||||
Qt.AlignVCenter)
|
||||
|
||||
|
||||
def configure_widget(self):
|
||||
|
||||
@@ -1599,8 +1836,10 @@ class CAQTableWidget(QTableWidget):
|
||||
self.resizeColumnsToContents()
|
||||
self.resizeRowsToContents()
|
||||
#self.horizontalHeader().setStretchLastSection(True);
|
||||
self.setColumnWidth(self.columns_dict['PV'], _column_width_pvname)
|
||||
|
||||
if 'PV' in self.columns_dict.keys():
|
||||
self.setColumnWidth(self.columns_dict['PV'], _column_width_pvname)
|
||||
_pv_column = self.columns_dict['PV']
|
||||
|
||||
self.setColumnWidth(self.columns_dict['Value'], _column_width_value)
|
||||
if 'Init' in self.columns_dict.keys():
|
||||
self.setColumnWidth(self.columns_dict['Init'], _column_width_value)
|
||||
@@ -1610,18 +1849,22 @@ class CAQTableWidget(QTableWidget):
|
||||
self.setColumnWidth(self.columns_dict['Reconnect'],
|
||||
_column_width_checkbox)
|
||||
|
||||
_pv_column = self.columns_dict['PV']
|
||||
|
||||
|
||||
for i in range(0, len(self.pv_gateway)):
|
||||
qtwt = QTableWidgetItem(self.pv_list_show[i])
|
||||
f = qtwt.font()
|
||||
f.setPointSize(8)
|
||||
qtwt.setFont(f)
|
||||
istart = 1
|
||||
if 'PV' in self.columns_dict.keys():
|
||||
qtwt = QTableWidgetItem(self.pv_list_show[i])
|
||||
f = qtwt.font()
|
||||
f.setPointSize(8)
|
||||
qtwt.setFont(f)
|
||||
|
||||
self.setItem(i, _pv_column, qtwt)
|
||||
self.item(i, _pv_column).setTextAlignment(Qt.AlignHCenter |
|
||||
Qt.AlignVCenter)
|
||||
for i_column in range(1, self.no_columns-1):
|
||||
self.setItem(i, _pv_column, qtwt)
|
||||
self.item(i, _pv_column).setTextAlignment(Qt.AlignHCenter |
|
||||
Qt.AlignVCenter)
|
||||
else:
|
||||
istart = 0
|
||||
|
||||
for i_column in range(istart, self.no_columns-1):
|
||||
self.setItem(i, i_column, QTableWidgetItem(str("")))
|
||||
self.item(i, i_column).setTextAlignment(Qt.AlignHCenter |
|
||||
Qt.AlignVCenter)
|
||||
@@ -1638,25 +1881,29 @@ class CAQTableWidget(QTableWidget):
|
||||
|
||||
if self.init_column:
|
||||
self.init_widget = QWidget()
|
||||
_init_layout = QHBoxLayout(self.init_widget)
|
||||
self.init_layout = QHBoxLayout(self.init_widget)
|
||||
self.init_value_button = QPushButton()
|
||||
self.init_value_button.setText("Update")
|
||||
_f = self.init_value_button.font()
|
||||
_f.setPointSize(8)
|
||||
self.init_value_button.setFont(_f)
|
||||
self.init_value_button.setFixedWidth(80)
|
||||
self.init_value_button.setFixedWidth(64)
|
||||
self.init_value_button.clicked.connect(self.update_init_values)
|
||||
self.init_value_button.setToolTip(
|
||||
("Stores initial, pre-measurement value. Update is also " +
|
||||
"typically executed automatically before new optics are set."))
|
||||
_init_layout.addWidget(self.init_value_button)
|
||||
_init_layout.setAlignment(Qt.AlignRight)
|
||||
_init_layout.setContentsMargins(1, 1, 0, 0) #Required
|
||||
self.init_widget.setLayout(_init_layout)
|
||||
self.setCellWidget(len(self.pv_gateway), 1, self.init_widget)
|
||||
"typically executed automatically before analysis procedure."))
|
||||
self.init_layout.addWidget(self.init_value_button)
|
||||
self.init_layout.setAlignment(Qt.AlignCenter)
|
||||
self.init_layout.setContentsMargins(1, 1, 1, 0) #Required
|
||||
self.init_widget.setLayout(self.init_layout)
|
||||
|
||||
if 'PV' in self.columns_dict:
|
||||
self.setCellWidget(len(self.pv_gateway), 0, self.init_widget)
|
||||
else:
|
||||
self.setCellWidget(len(self.pv_gateway), self.columns_dict['Init'], self.init_widget)
|
||||
|
||||
_restore_widget = QWidget()
|
||||
_restore_layout = QHBoxLayout(_restore_widget)
|
||||
self.restore_widget = QWidget()
|
||||
self.restore_layout = QHBoxLayout(self.restore_widget)
|
||||
self.restore_value_button = QPushButton()
|
||||
self.restore_value_button.setStyleSheet(
|
||||
"QPushButton{background-color: rgb(212, 219, 157);}")
|
||||
@@ -1668,11 +1915,36 @@ class CAQTableWidget(QTableWidget):
|
||||
self.restore_value_button.clicked.connect(self.restore_init_values)
|
||||
self.restore_value_button.setToolTip(
|
||||
("Restore devices to their pre-measurement values"))
|
||||
_restore_layout.addWidget(self.restore_value_button)
|
||||
_restore_layout.setAlignment(Qt.AlignRight)
|
||||
_restore_layout.setContentsMargins(1, 1, 0, 0)
|
||||
_restore_widget.setLayout(_restore_layout)
|
||||
self.setCellWidget(len(self.pv_gateway), 2, _restore_widget)
|
||||
self.restore_layout.addWidget(self.restore_value_button)
|
||||
self.restore_layout.setAlignment(Qt.AlignCenter)
|
||||
self.restore_layout.setContentsMargins(1, 1, 0, 0)
|
||||
self.restore_widget.setLayout(self.restore_layout)
|
||||
if 'PV' in self.columns_dict:
|
||||
self.setCellWidget(len(self.pv_gateway),
|
||||
self.columns_dict['Init'],
|
||||
self.restore_widget)
|
||||
|
||||
if self.standby_column:
|
||||
|
||||
_standby_widget = QWidget()
|
||||
_standby_layout = QHBoxLayout(_standby_widget)
|
||||
self.standby_value_button = QPushButton()
|
||||
self.standby_value_button.setStyleSheet(
|
||||
"QPushButton{background-color: rgb(212, 219, 157);}")
|
||||
self.standby_value_button.setText("Standby")
|
||||
_f = self.standby_value_button.font()
|
||||
_f.setPointSize(8)
|
||||
self.standby_value_button.setFont(_f)
|
||||
self.standby_value_button.setFixedWidth(80)
|
||||
self.standby_value_button.clicked.connect(self.set_standby_values)
|
||||
self.standby_value_button.setToolTip(
|
||||
("Set devices to their pre-set standby values"))
|
||||
_standby_layout.addWidget(self.standby_value_button)
|
||||
_standby_layout.setAlignment(Qt.AlignCenter)
|
||||
_standby_layout.setContentsMargins(1, 1, 0, 0)
|
||||
_standby_widget.setLayout(_standby_layout)
|
||||
self.setCellWidget(len(self.pv_gateway), self.columns_dict['Standby'], _standby_widget)
|
||||
|
||||
|
||||
#Do not display no for last row (Reconnect button)
|
||||
_row_digit_last_cell = QTableWidgetItem(str(""))
|
||||
@@ -1689,13 +1961,13 @@ class CAQTableWidget(QTableWidget):
|
||||
f.setPointSize(8)
|
||||
self.reconnect_button.setFixedWidth(100)
|
||||
else:
|
||||
f.setPointSize(6)
|
||||
self.reconnect_button.setFixedWidth(58)
|
||||
f.setPointSize(7) #6
|
||||
self.reconnect_button.setFixedWidth(66) #58
|
||||
|
||||
self.reconnect_button.setFont(f)
|
||||
|
||||
self.reconnect_button.setText("Reconnect")
|
||||
|
||||
self.reconnect_button.setToolTip("Reconnect selected/checked channels")
|
||||
_layout = QHBoxLayout(_qwb)
|
||||
_layout.addWidget(self.reconnect_button)
|
||||
_layout.setAlignment(Qt.AlignCenter)
|
||||
@@ -1712,9 +1984,10 @@ class CAQTableWidget(QTableWidget):
|
||||
self.setCellWidget(len(self.pv_gateway), self.no_columns-1,
|
||||
self.cb_item_all)
|
||||
|
||||
header_item = QTableWidgetItem("Process Variable")
|
||||
|
||||
self.setHorizontalHeaderItem(self.columns_dict['PV'], header_item)
|
||||
if 'PV' in self.columns_dict.keys():
|
||||
header_item = QTableWidgetItem("Process Variable")
|
||||
self.setHorizontalHeaderItem(self.columns_dict['PV'], header_item)
|
||||
|
||||
if 'Init' in self.columns_dict.keys():
|
||||
self.setHorizontalHeaderItem(self.columns_dict['Init'],
|
||||
@@ -1749,9 +2022,13 @@ class CAQTableWidget(QTableWidget):
|
||||
self.setMinimumWidth(_min_table_width)
|
||||
|
||||
for _row in range(0, len(self.pv_gateway)):
|
||||
self.item(_row, _pv_column).setForeground(QColor("#000000"))
|
||||
if 'PV' in self.columns_dict.keys():
|
||||
self.item(_row, _pv_column).setForeground(QColor("#000000"))
|
||||
istart = 1
|
||||
else:
|
||||
istart = 0
|
||||
|
||||
for i_column in range(1, self.no_columns-2):
|
||||
for i_column in range(istart, self.no_columns-2):
|
||||
self.item(_row, i_column).setForeground(QColor("#000000"))
|
||||
self.item(_row, i_column).setTextAlignment(Qt.AlignRight |
|
||||
Qt.AlignVCenter)
|
||||
@@ -1834,16 +2111,16 @@ class CAQTableWidget(QTableWidget):
|
||||
if _prop == self.pv_gateway[_row].READBACK_ALARM:
|
||||
|
||||
if alarm_severity == self.pv_gateway[_row].cyca.SEV_MAJOR:
|
||||
_bgcolor = self.pv_gateway[_row].settings.fgAlarmMajor
|
||||
_bgcolor = self.pv_gateway[_row].fg_alarm_major
|
||||
_fgcolor = "black"
|
||||
elif alarm_severity == self.pv_gateway[_row].cyca.SEV_MINOR:
|
||||
_bgcolor = self.pv_gateway[_row].settings.fgAlarmMinor
|
||||
_bgcolor = self.pv_gateway[_row].fg_alarm_minor
|
||||
_fgcolor = "black"
|
||||
elif alarm_severity == self.pv_gateway[_row].cyca.SEV_INVALID:
|
||||
_bgcolor = self.pv_gateway[_row].settings.fgAlarmInvalid
|
||||
_bgcolor = self.pv_gateway[_row].fg_alarm_invalid
|
||||
_fgcolor = "#777777"
|
||||
else:
|
||||
_bgcolor = self.pv_gateway[_row].settings.fgAlarmNoAlarm
|
||||
_bgcolor = self.pv_gateway[_row].fg_alarm_noalarm
|
||||
_fgcolor = "black"
|
||||
|
||||
#Colors for bg/fg reversed as is the old norm
|
||||
@@ -2455,6 +2732,7 @@ class QNoDockWidget(QDockWidget):
|
||||
class CAQStripChart(PlotWidget):
|
||||
'''Channel access enabled pyqtgraph.PlotWidget'''
|
||||
|
||||
|
||||
def __init__(self, parent=None, pv_list: list = ['PV_NAME_NOT_GIVEN'],
|
||||
monitor_callback=None, pv_within_daq_group: bool = False,
|
||||
color_mode=None, show_units: bool = False, prefix: str = "",
|
||||
@@ -2477,17 +2755,18 @@ class CAQStripChart(PlotWidget):
|
||||
self.val_previous = [None] * self.no_channels
|
||||
|
||||
self.curve = [None] * self.no_channels
|
||||
|
||||
print (self.pv_list, flush=True)
|
||||
|
||||
|
||||
for i in range (0, len(self.pv_list)):
|
||||
self.pv_gateway[i] = PVGateway().__init__(
|
||||
parent, pv_list[i], monitor_callback, pv_within_daq_group,
|
||||
|
||||
self.pv_gateway[i] = PVGateway(
|
||||
parent, self.pv_list[i], monitor_callback, pv_within_daq_group,
|
||||
color_mode, show_units, prefix, suffix,
|
||||
#connect_callback=self.py_connect_callback,
|
||||
connect_triggers=False, notify_freq_hz=notify_freq_hz,
|
||||
monitor_dbr_time = True)
|
||||
|
||||
print(i, pv_list[i], "gateway object", self.pv_gateway[i])
|
||||
|
||||
self.pv_gateway[i].is_initialize_complete()
|
||||
|
||||
|
||||
@@ -2529,8 +2808,8 @@ class CAQStripChart(PlotWidget):
|
||||
|
||||
# Data stuff
|
||||
self._interval = int(sampleinterval*1000)
|
||||
self._bufsize = 9000 #int(timewindow/0.33)
|
||||
self._bufsize2 = 9000 # int(timewindow/1.33)
|
||||
self._bufsize = 10000 #int(timewindow/0.33)
|
||||
self._bufsize2 = 10000 # int(timewindow/1.33)
|
||||
self.databuffer = [None] * self.no_channels
|
||||
self.timebuffer = [None] * self.no_channels
|
||||
self.x = [None] * self.no_channels
|
||||
@@ -2561,13 +2840,37 @@ class CAQStripChart(PlotWidget):
|
||||
if title is not None:
|
||||
self.setTitle(str(title)) #self.pv_gateway[0].pv_name)
|
||||
self.showGrid(x=True, y=True)
|
||||
self.setLabel('left', ylabel, self.pv_gateway[0].units)
|
||||
#self.setLabel('left', ylabel, self.pv_gateway[0].units)
|
||||
self.setLabel('bottom', 'time', 's')
|
||||
self.setBackground((60, 60, 60)) #247, 236, 249))
|
||||
self.setLimits(yMin=-0.11)
|
||||
#self.setLimits(yMin=-0.11)
|
||||
#self.setLimits(yMin=-1, yMax=1)
|
||||
|
||||
ax = pg.AxisItem('left')
|
||||
ax.enableAutoSIPrefix(enable=False)
|
||||
ax.setLabel(ylabel, self.pv_gateway[0].units)
|
||||
ax.setGrid(155)
|
||||
|
||||
ay = pg.AxisItem('bottom')
|
||||
ay.enableAutoSIPrefix(enable=False)
|
||||
ay.setLabel('time', 'min')
|
||||
ay.setGrid(175)
|
||||
|
||||
if 'BPM' in text_label:
|
||||
ax.setTickSpacing(0.2, 0.1)
|
||||
#ax.setRange(-1, 1)
|
||||
#ax.setParentItem(self.graphicsItem())
|
||||
axitems = {}
|
||||
axitems['left'] = ax
|
||||
axitems['bottom'] = ay
|
||||
|
||||
self.setAxisItems(axitems)
|
||||
|
||||
pg.setConfigOption('leftButtonPan', False)
|
||||
|
||||
self.plotItem.setMouseEnabled(y=True) # Only allow zoom in X-axis
|
||||
self.plotItem.setMouseEnabled(x=True) # Only allow zoom in Y-axis
|
||||
|
||||
#(125, 249, 255)
|
||||
if self.pen_color_idx == 0:
|
||||
pen_list = [ (255, 155, 0), (255,255,0), (0, 180, 255) ]
|
||||
@@ -2601,20 +2904,37 @@ class CAQStripChart(PlotWidget):
|
||||
|
||||
@Slot(object, int)
|
||||
def receive_monitor_dbr_time(self, pvdata, alarm_severity):
|
||||
|
||||
#if not self.mutex.tryLock(): #locked():
|
||||
# print("Event locked", pvdata.ts[0], pvdata.ts[1])
|
||||
# return
|
||||
|
||||
|
||||
#self.mutex.lock() #acquire()
|
||||
|
||||
_row = self.pv2item_dict[self.sender()]
|
||||
#print("row, value from pvdata==>", _row, pvdata.value[0], self.pv_gateway[_row].pv_name)
|
||||
|
||||
|
||||
ts_now = pvdata.ts[0] + pvdata.ts[1] * 10**(-9)
|
||||
ts_previous = (self.pvd_previous_list[_row].ts[0] +
|
||||
self.pvd_previous_list[_row].ts[1] * 10**(-9))
|
||||
self.pvd_previous_list[_row].ts[1] * 10**(-9))
|
||||
ts_delta = ts_now - ts_previous
|
||||
|
||||
|
||||
if (pvdata.ts[0] == self.pvd_previous_list[_row].ts[0]) and (
|
||||
pvdata.ts[1] == self.pvd_previous_list[_row].ts[1]):
|
||||
pvdata.show()
|
||||
self.pvd_previous_list[_row].show()
|
||||
#print("SAME TIMESTAMP")
|
||||
#pvdata.show()
|
||||
#self.pvd_previous_list[_row].show()
|
||||
#print("================")
|
||||
#self.mutex.unlock() #release()
|
||||
return
|
||||
|
||||
|
||||
if pvdata.ts[0] < self.pvd_previous_list[_row].ts[0]:
|
||||
print("Funny ts value", self.pv_gateway[_row].pv_name)
|
||||
pvdata.show()
|
||||
#self.mutex.unlock() #release()
|
||||
return
|
||||
|
||||
value = pvdata.value[0]
|
||||
#discard first callbacks
|
||||
#if ts_delta > 2.0:
|
||||
@@ -2630,6 +2950,7 @@ class CAQStripChart(PlotWidget):
|
||||
|
||||
highest_ts = self.timebuffer[0][0] \
|
||||
if self.timebuffer[0][0] is not None else 0
|
||||
|
||||
for i in range(1, len(self.timebuffer)):
|
||||
if self.timebuffer[i][0] is None:
|
||||
continue
|
||||
@@ -2655,9 +2976,10 @@ class CAQStripChart(PlotWidget):
|
||||
# self.curve[row].setData(self.x_shifted[row], self.y[row][idx:])
|
||||
|
||||
self.curve[_row].setData(self.x_shifted[_row], self.y[_row][idx:])
|
||||
self.time_delta[_row] = (
|
||||
pvdata.ts[0] + pvdata.ts[1]*10**(-9)) - self.time_zero[0]
|
||||
|
||||
self.time_delta[_row] = ((
|
||||
pvdata.ts[0] + pvdata.ts[1]*10**(-9)) - self.time_zero[0])/60
|
||||
|
||||
#self.mutex.unlock() #release()
|
||||
#QApplication.processEvents()
|
||||
|
||||
|
||||
|
||||
310
pvwidgets.py-
310
pvwidgets.py-
@@ -239,11 +239,9 @@ class CAQMenu(QComboBox, PVGateway):
|
||||
super().__init__(parent, pv_name, monitor_callback,
|
||||
pv_within_daq_group, color_mode, show_units, prefix,
|
||||
suffix, connect_callback=self.py_connect_callback)
|
||||
|
||||
|
||||
self.is_initialize_complete()
|
||||
|
||||
self.configure_widget()
|
||||
|
||||
#After configure:widget
|
||||
self.currentIndexChanged.connect(self.value_change)
|
||||
|
||||
@@ -254,6 +252,7 @@ class CAQMenu(QComboBox, PVGateway):
|
||||
'''Callback function to be invoked on change of
|
||||
pv connection status.
|
||||
'''
|
||||
|
||||
self.trigger_connect.emit(int(handle), str(pvname), int(status))
|
||||
|
||||
def configure_widget(self):
|
||||
@@ -269,9 +268,10 @@ class CAQMenu(QComboBox, PVGateway):
|
||||
enumStringList = self.cafe.getEnumStrings(self.handle)
|
||||
|
||||
self.addItems(enumStringList)
|
||||
|
||||
for i in range(0, self.count()):
|
||||
self.setItemData(i, Qt.AlignCenter, Qt.TextAlignmentRole)
|
||||
|
||||
|
||||
fm = QFontMetricsF(QFont("Sans Serif", 10))
|
||||
qrect = fm.boundingRect(self.suggested_text)
|
||||
|
||||
@@ -283,9 +283,11 @@ class CAQMenu(QComboBox, PVGateway):
|
||||
self.qt_property_initial_values(qt_object_name=self.PV_CONTROLLER)
|
||||
|
||||
def post_display_value(self, value):
|
||||
|
||||
|
||||
'''Convert value to index'''
|
||||
if "setCurrentIndex" in dir(self):
|
||||
|
||||
|
||||
if LooseVersion(QT_VERSION_STR) >= LooseVersion("5.3"):
|
||||
self.blockSignals(True)
|
||||
|
||||
@@ -311,7 +313,6 @@ class CAQMenu(QComboBox, PVGateway):
|
||||
|
||||
|
||||
def value_change(self, indx):
|
||||
|
||||
status = self.cafe.set(self.handle, indx)
|
||||
|
||||
if status != self.cyca.ICAFE_NORMAL:
|
||||
@@ -346,9 +347,8 @@ class CAQMenu(QComboBox, PVGateway):
|
||||
if self.pv_info.accessWrite == 0:
|
||||
event.ignore()
|
||||
return
|
||||
else:
|
||||
QComboBox.mousePressEvent(self, event)
|
||||
|
||||
|
||||
QComboBox.mousePressEvent(self, event)
|
||||
self.previousIndex = self.currentIndex()
|
||||
|
||||
def enterEvent(self, event):
|
||||
@@ -2431,10 +2431,17 @@ class QNoDockWidget(QDockWidget):
|
||||
self.topLevelChanged.connect(self._top_level_changed)
|
||||
self.setVisible(False)
|
||||
self.setFloating(True)
|
||||
|
||||
x = self.geometry_from_qsettings.x() + 480 # 3500 #screen.width() - widget.width()
|
||||
y = self.geometry_from_qsettings.y() + 350 #100 #screen.height() - widget.height()
|
||||
self.move(x, y)
|
||||
|
||||
|
||||
def changeEvent(self, event):
|
||||
if "QAbstractButton" in str(self.sender()):
|
||||
self.geometry_from_qsettings = self.parent.geometry()
|
||||
|
||||
|
||||
|
||||
def _top_level_changed(self): #, is_floating):
|
||||
self.setVisible(False)
|
||||
@@ -2452,40 +2459,46 @@ class CAQStripChart(PlotWidget):
|
||||
monitor_callback=None, pv_within_daq_group: bool = False,
|
||||
color_mode=None, show_units: bool = False, prefix: str = "",
|
||||
suffix: str = "", notify_freq_hz: int = 0, title: str = "",
|
||||
ylabel: str = ""):
|
||||
ylabel: str = "", force_ts_align = True, text_label = [],
|
||||
pen_color_idx = 0):
|
||||
super().__init__()
|
||||
|
||||
self.no_channels = len(pv_list)
|
||||
|
||||
self.pen_color_idx = pen_color_idx
|
||||
self.text_label = text_label
|
||||
self.found = False
|
||||
self.time_zero = [0] * self.no_channels
|
||||
self.time_delta = [0] * self.no_channels
|
||||
self.pv_list = pv_list
|
||||
self.pv_list = pv_list
|
||||
self.pv2item_dict = {}
|
||||
self.pv_gateway = [None] * self.no_channels
|
||||
|
||||
|
||||
self.pvd_previous_list = [None] * self.no_channels
|
||||
self.val_previous = [None] * self.no_channels
|
||||
|
||||
self.curve = [None] * self.no_channels
|
||||
|
||||
for i in range(0, len(self.pv_list)):
|
||||
|
||||
for i in range (0, len(self.pv_list)):
|
||||
print("in atripchart", i, self.pv_list[i])
|
||||
self.pv_gateway[i] = PVGateway(
|
||||
parent, pv_list[i], monitor_callback, pv_within_daq_group,
|
||||
color_mode, show_units, prefix, suffix,
|
||||
parent, self.pv_list[i], monitor_callback, pv_within_daq_group,
|
||||
color_mode, show_units, prefix, suffix,
|
||||
#connect_callback=self.py_connect_callback,
|
||||
connect_triggers=False, notify_freq_hz=notify_freq_hz,
|
||||
monitor_dbr_time=True)
|
||||
monitor_dbr_time = True)
|
||||
|
||||
|
||||
self.pv_gateway[i].is_initialize_complete()
|
||||
|
||||
|
||||
|
||||
self.pvd_previous_list[i] = self.pv_gateway[i].pvd
|
||||
|
||||
self.pv_gateway[i].trigger_connect.connect(
|
||||
self.receive_connect_update)
|
||||
|
||||
|
||||
self.pv_gateway[i].trigger_monitor_str.connect(
|
||||
self.receive_monitor_update)
|
||||
self.receive_monitor_update)
|
||||
self.pv_gateway[i].trigger_monitor_int.connect(
|
||||
self.receive_monitor_update)
|
||||
self.pv_gateway[i].trigger_monitor_float.connect(
|
||||
@@ -2493,38 +2506,40 @@ class CAQStripChart(PlotWidget):
|
||||
self.pv_gateway[i].trigger_monitor.connect(
|
||||
self.receive_monitor_dbr_time)
|
||||
|
||||
self.pv_gateway[i].widget_class = "PlotWidget"
|
||||
self.pv_gateway[i].widget_class = "PlotWidget"
|
||||
|
||||
self.pv2item_dict[self.pv_gateway[i]] = i
|
||||
|
||||
self.cafe = self.pv_gateway[0].cafe
|
||||
self.cyca = self.pv_gateway[0].cyca
|
||||
for i in range(0, len(self.pv_gateway)):
|
||||
for i in range(0, len(self.pv_gateway)):
|
||||
if self.cafe.isConnected(self.pv_gateway[i].pv_name):
|
||||
self.pv_gateway[i].trigger_connect.emit(
|
||||
self.pv_gateway[i].handle, str(self.pv_gateway[i].pv_name),
|
||||
self.pv_gateway[i].cyca.ICAFE_CS_CONN)
|
||||
|
||||
|
||||
for i in range(0, len(self.pv_gateway)):
|
||||
if not self.pv_gateway[i].pv_within_daq_group:
|
||||
self.pv_gateway[i].monitor_start()
|
||||
|
||||
sampleinterval = 0.2
|
||||
##timewindow = 1800.0
|
||||
|
||||
sampleinterval = 0.2
|
||||
timewindow = 1800.0
|
||||
|
||||
self.ts_delta_max = 0.6
|
||||
|
||||
|
||||
# Data stuff
|
||||
self._interval = int(sampleinterval*1000)
|
||||
self._bufsize = 9000 #int(timewindow/0.33)
|
||||
self._bufsize2 = 9000 # int(timewindow/1.33)
|
||||
self.databuffer = [None] * self.no_channels
|
||||
self.timebuffer = [None] * self.no_channels
|
||||
self.x = [None] * self.no_channels
|
||||
self.y = [None] * self.no_channels
|
||||
self.x = [None] * self.no_channels
|
||||
self.y = [None] * self.no_channels
|
||||
self.x_shifted = [None] * self.no_channels
|
||||
|
||||
self.idx = [0] * self.no_channels
|
||||
|
||||
|
||||
for i in range(0, self.no_channels):
|
||||
bsize = self._bufsize if i == 0 else self._bufsize2
|
||||
self.databuffer[i] = collections.deque([None]*bsize, bsize)
|
||||
@@ -2532,9 +2547,9 @@ class CAQStripChart(PlotWidget):
|
||||
self.x[i] = np.zeros(bsize, dtype=np.float)
|
||||
self.y[i] = np.zeros(bsize, dtype=np.float)
|
||||
|
||||
##_long_size=20
|
||||
_long_size=20
|
||||
#self.data_series_buffer = collections.deque([0]*_long_size, _long_size)
|
||||
#self.time_series_buffer = collections.deque([0]*_long_size, _long_size)
|
||||
#self.time_series_buffer = collections.deque([0]*_long_size, _long_size)
|
||||
|
||||
#self.data_series = [] * self.no_channels
|
||||
#self.time_series = [] * self.no_channels
|
||||
@@ -2545,98 +2560,118 @@ class CAQStripChart(PlotWidget):
|
||||
#self.x_series = np.zeros(_long_size, dtype=np.float)
|
||||
#self.y_series = np.zeros(_long_size, dtype=np.float)
|
||||
if title is not None:
|
||||
self.setTitle(str(title)) #self.pv_gateway[0].pv_name)
|
||||
self.setTitle(str(title)) #self.pv_gateway[0].pv_name)
|
||||
self.showGrid(x=True, y=True)
|
||||
self.setLabel('left', ylabel, self.pv_gateway[0].units)
|
||||
self.setLabel('bottom', 'time', 's')
|
||||
self.setLabel('bottom', 'time', 's')
|
||||
self.setBackground((60, 60, 60)) #247, 236, 249))
|
||||
self.setLimits(yMin=-0.11)
|
||||
|
||||
self.plotItem.setMouseEnabled(y=False) # Only allow zoom in X-axis
|
||||
self.plotItem.setMouseEnabled(y=True) # Only allow zoom in X-axis
|
||||
self.plotItem.setMouseEnabled(x=True) # Only allow zoom in Y-axis
|
||||
|
||||
pen_list = [(125, 249, 255), (255, 255, 0)]
|
||||
#(125, 249, 255)
|
||||
if self.pen_color_idx == 0:
|
||||
pen_list = [ (255, 155, 0), (255,255,0), (0, 180, 255) ]
|
||||
elif self.pen_color_idx == 1:
|
||||
pen_list = [ (125, 249, 255), (255,255,0), (0, 180, 255) ]
|
||||
else:
|
||||
pen_list = [ (0, 180, 255), (125, 249, 255), (255,255,0) ]
|
||||
|
||||
for i in range(0, len(self.pv_gateway)):
|
||||
self.curve[i] = self.plot(self.x[0], self.y[0], pen=pen_list[i])
|
||||
self.curve[i] = self.plot(self.x[0], self.y[0], pen=pen_list[i]) # (0, 253, 235))
|
||||
#self.curve[1] = self.plot(self.x[1], self.y[1], pen=(255,255,0))
|
||||
#offset=(1.0, 1.0),
|
||||
l=pg.LegendItem() #horSpacing=20, verSpacing=0, labelTextColor=(205, 205, 205),
|
||||
#labelTextSize='6px', colCount=1)
|
||||
|
||||
l = pg.LegendItem(offset=(0., 0.5), colCount=1)
|
||||
l.setParentItem(self.graphicsItem())
|
||||
l.anchor((0,0), (0.08, 0.0))
|
||||
#l.setLabelTextColor((205, 205, 205))
|
||||
#l.setLabelTextSize(9) does not exists(!)
|
||||
#l.setOffset(-60)
|
||||
for curv, label in zip(self.curve, self.text_label):
|
||||
l.addItem(curv, label)
|
||||
|
||||
l.setLabelTextColor((255, 255, 255))
|
||||
|
||||
for curv, pv in zip(self.curve, self.pv_gateway):
|
||||
l.addItem(curv, pv.pv_name)
|
||||
|
||||
#for curv, pv in zip(self.curve, self.pv_gateway):
|
||||
# l.addItem(curv, self.textpv.pv_name)
|
||||
|
||||
#self.daq_stop()
|
||||
#print(self._bufsize)
|
||||
#print(len(self.x), len(self.y))
|
||||
QApplication.processEvents()
|
||||
|
||||
@Slot(object, int)
|
||||
|
||||
@Slot(object, int)
|
||||
def receive_monitor_dbr_time(self, pvdata, alarm_severity):
|
||||
|
||||
#Check on alarm_severity??
|
||||
|
||||
_row = self.pv2item_dict[self.sender()]
|
||||
|
||||
#print("row, value from pvdata==>", _row, pvdata.value[0], self.pv_gateway[_row].pv_name)
|
||||
|
||||
ts_now = pvdata.ts[0] + pvdata.ts[1] * 10**(-9)
|
||||
ts_previous = (self.pvd_previous_list[_row].ts[0] +
|
||||
self.pvd_previous_list[_row].ts[1] * 10**(-9))
|
||||
##ts_delta = ts_now - ts_previous
|
||||
|
||||
ts_previous = (self.pvd_previous_list[_row].ts[0] +
|
||||
self.pvd_previous_list[_row].ts[1] * 10**(-9))
|
||||
ts_delta = ts_now - ts_previous
|
||||
|
||||
if (pvdata.ts[0] == self.pvd_previous_list[_row].ts[0]) and (
|
||||
pvdata.ts[1] == self.pvd_previous_list[_row].ts[1]):
|
||||
pvdata.show()
|
||||
#pvdata.show()
|
||||
self.pvd_previous_list[_row].show()
|
||||
return
|
||||
|
||||
value = pvdata.value[0]
|
||||
|
||||
value = pvdata.value[0]
|
||||
#discard first callbacks
|
||||
#if ts_delta > 2.0:
|
||||
# self.pvd_previous_list[_row] = _pvd
|
||||
# self.pvd_previous_list[_row] = _pvd
|
||||
# return;
|
||||
self.pvd_previous_list[_row] = pvdata
|
||||
self.val_previous[_row] = value
|
||||
#self.pvd_previous_list[_row].ts[0] = _pvd.ts[0]
|
||||
#self.pvd_previous_list[_row].ts[0] = _pvd.ts[0]
|
||||
#self.pvd_previous_list[_row].ts[1] = _pvd.ts[1]
|
||||
|
||||
|
||||
self.databuffer[_row].append(value)
|
||||
self.timebuffer[_row].append(self.time_delta[_row])
|
||||
|
||||
highest_ts = self.timebuffer[0][0] \
|
||||
if self.timebuffer[0][0] is not None else 0
|
||||
for i in range(1, len(self.timebuffer)):
|
||||
for i in range(1, len(self.timebuffer)):
|
||||
if self.timebuffer[i][0] is None:
|
||||
continue
|
||||
elif self.timebuffer[i][0] > highest_ts:
|
||||
highest_ts = self.timebuffer[i][0]
|
||||
|
||||
|
||||
if self.timebuffer[_row][0] is not None:
|
||||
for i, val in enumerate(self.timebuffer[_row]):
|
||||
if val > highest_ts:
|
||||
self.idx[_row] = i - 1
|
||||
break
|
||||
break
|
||||
|
||||
self.y[_row][:] = self.databuffer[_row]
|
||||
self.x[_row][:] = self.timebuffer[_row]
|
||||
|
||||
|
||||
idx = self.idx[_row]
|
||||
self.x_shifted[_row] = list(
|
||||
map(lambda m: (m - self.time_delta[_row]), self.x[_row][idx:]))
|
||||
self.x_shifted[_row] = list(map(lambda m : (m - self.time_delta[_row]), self.x[_row][idx:]))
|
||||
|
||||
self.curve[_row].setData(self.x_shifted[_row], self.y[_row][idx:])
|
||||
#print("idx", self.idx)
|
||||
|
||||
#if 'AVG' in self.pv_gateway[_row].pv_name:
|
||||
# for row in range(0, len(self.curve)):
|
||||
# self.curve[row].setData(self.x_shifted[row], self.y[row][idx:])
|
||||
|
||||
self.curve[_row].setData(self.x_shifted[_row], self.y[_row][idx:])
|
||||
self.time_delta[_row] = (
|
||||
pvdata.ts[0] + pvdata.ts[1]*10**(-9)) - self.time_zero[0]
|
||||
|
||||
pvdata.ts[0] + pvdata.ts[1]*10**(-9)) - self.time_zero[0]
|
||||
|
||||
#QApplication.processEvents()
|
||||
|
||||
|
||||
@Slot(str, int, int)
|
||||
@Slot(int, int, int)
|
||||
@Slot(float, int, int)
|
||||
def receive_monitor_update(self, value, status, alarm_severity):
|
||||
|
||||
|
||||
#self.pv_gateway.receive_monitor_update(value, status, alarm_severity)
|
||||
_row = self.pv2item_dict[self.sender()]
|
||||
|
||||
#print("row, value===>", _row, value, self.pv_gateway[_row].pv_name)
|
||||
#if _row == 1:
|
||||
# return
|
||||
print("row, value===>", _row, value, self.pv_gateway[_row].pv_name)
|
||||
_pvd = self.pv_gateway[_row].cafe.getPVCache(
|
||||
self.pv_gateway[_row].handle)
|
||||
|
||||
@@ -2644,109 +2679,106 @@ class CAQStripChart(PlotWidget):
|
||||
|
||||
_pvd2 = self.pv_gateway[_row].pvd
|
||||
|
||||
print("val", value, _pvd2.value[0], _pvd.value[0],
|
||||
self.pvd_previous_list[_row].value[0])
|
||||
print ("val", value, _pvd2.value[0], _pvd.value[0], self.pvd_previous_list[_row].value[0])
|
||||
|
||||
ts_now = _pvd.ts[0] + _pvd.ts[1] * 10**(-9)
|
||||
|
||||
ts_previous = (self.pvd_previous_list[_row].ts[0] +
|
||||
self.pvd_previous_list[_row].ts[1] * 10**(-9))
|
||||
ts_delta = ts_now - ts_previous
|
||||
|
||||
ts_previous = (self.pvd_previous_list[_row].ts[0] +
|
||||
self.pvd_previous_list[_row].ts[1] * 10**(-9))
|
||||
ts_delta = ts_now - ts_previous
|
||||
|
||||
if value == self.val_previous[_row]:
|
||||
#if (_pvd.ts[0] == self.pvd_previous_list[_row].ts[0]) and (
|
||||
# _pvd.ts[1] == self.pvd_previous_list[_row].ts[1]):
|
||||
_pvd.show()
|
||||
|
||||
#self.pvd_previous_list[_row].show()
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
#discard first callbacks
|
||||
#if ts_delta > 2.0:
|
||||
# self.pvd_previous_list[_row] = _pvd
|
||||
# self.pvd_previous_list[_row] = _pvd
|
||||
# return;
|
||||
self.pvd_previous_list[_row] = _pvd2
|
||||
self.val_previous[_row] = value
|
||||
#self.pvd_previous_list[_row].ts[0] = _pvd.ts[0]
|
||||
#self.pvd_previous_list[_row].ts[0] = _pvd.ts[0]
|
||||
#self.pvd_previous_list[_row].ts[1] = _pvd.ts[1]
|
||||
|
||||
|
||||
self.databuffer[_row].append(value)
|
||||
self.timebuffer[_row].append(self.time_delta[_row])
|
||||
|
||||
highest_ts = self.timebuffer[0][0] \
|
||||
if self.timebuffer[0][0] is not None else 0
|
||||
for i in range(1, len(self.timebuffer)):
|
||||
for i in range(1, len(self.timebuffer)):
|
||||
if self.timebuffer[i][0] is None:
|
||||
continue
|
||||
elif self.timebuffer[i][0] > highest_ts:
|
||||
highest_ts = self.timebuffer[i][0]
|
||||
|
||||
|
||||
|
||||
|
||||
if self.timebuffer[_row][0] is not None:
|
||||
for i, val in enumerate(self.timebuffer[_row]):
|
||||
if val > highest_ts:
|
||||
self.idx[_row] = i - 1
|
||||
break
|
||||
|
||||
|
||||
#for i in range(1, self.timebuffer):
|
||||
# if self.timebuffer[i][0] is not None:
|
||||
# a = self.timebuffer[0][0]
|
||||
# for i, val in enumerate(self.timebuffer[_row]):
|
||||
# if val > a:
|
||||
# idx = i - 1
|
||||
# break
|
||||
break
|
||||
|
||||
|
||||
'''
|
||||
for i in range(1, self.timebuffer):
|
||||
if self.timebuffer[i][0] is not None:
|
||||
a = self.timebuffer[0][0]
|
||||
for i, val in enumerate(self.timebuffer[_row]):
|
||||
if val > a:
|
||||
idx = i - 1
|
||||
break
|
||||
'''
|
||||
|
||||
self.y[_row][:] = self.databuffer[_row]
|
||||
self.x[_row][:] = self.timebuffer[_row]
|
||||
|
||||
|
||||
|
||||
#self.y[_row][:] = self.databuffer[_row]
|
||||
#self.x[_row][:] = self.timebuffer[_row]
|
||||
|
||||
'''
|
||||
#print(ts_delta, value, self.pvd_previous.value[0])
|
||||
#if (ts_delta < self.ts_delta_max) and (value <
|
||||
#self.pvd_previous.value[0]) :
|
||||
#if (ts_delta < self.ts_delta_max) and (value < self.pvd_previous.value[0]) :
|
||||
if (value < self.pvd_previous.value[0]) :
|
||||
self.data_series_buffer.append(value)
|
||||
self.time_series_buffer.append(ts_now - self.time_zero )
|
||||
self.time_series_buffer.append(ts_now - self.time_zero ) #self.time_delta)
|
||||
self.y_series[:] = self.data_series_buffer
|
||||
self.x_series[:] = self.time_series_buffer
|
||||
#print(self.x_series, self.y_series)
|
||||
#elif ts_delta < 1.0:
|
||||
if len(self.data_series_buffer) > 15:
|
||||
if len(self.data_series_buffer) > 15:
|
||||
#x_series = np.array(self.time_series, dtype=np.float)
|
||||
#y_series = np.array(self.data_series, dtype=np.float)
|
||||
_x=self.x_series.reshape((-1, 1))
|
||||
|
||||
|
||||
model = LinearRegression()
|
||||
model.fit(_x, self.y_series)
|
||||
r_sq = model.score(_x, self.y_series)
|
||||
###JCprint('coefficient of determination:',
|
||||
##r_sq, "slope", model.coef_ , "lifetime:",
|
||||
###self.y_series[0]/model.coef_ / 3600)
|
||||
###JCprint('coefficient of determination:', r_sq, "slope", model.coef_ , "lifetime:", self.y_series[0]/model.coef_ / 3600)
|
||||
#print('intercept:', model.intercept_)
|
||||
#print('slope:', model.coef_)
|
||||
#print('max value', y_series[0], y_series[1])
|
||||
if r_sq > 0.995:
|
||||
_I = self.y_series[0]
|
||||
###JCprint("lifetime:", _I/model.coef_ / 3600)
|
||||
|
||||
|
||||
|
||||
|
||||
y_pred = model.predict(_x)
|
||||
#print("len, y_pred, _x", len(y_pred),
|
||||
#len(self.y_series), len(_x))
|
||||
#print("len, y_pred, _x", len(y_pred), len(self.y_series), len(_x))
|
||||
#print('predicted response:', y_pred, sep='\n')
|
||||
m_sq_error = mean_squared_error(self.y_series, y_pred)
|
||||
#print('Mean squared error: {0:.9f}'.format(
|
||||
# mean_squared_error(y_series, y_pred)))
|
||||
#print('Coefficient of determination: {0:.9f}'.format(
|
||||
# r2_score(y_series, y_pred)))
|
||||
# r2_score(y_series, y_pred)))
|
||||
|
||||
|
||||
|
||||
|
||||
self.trigger_series_sequence.emit(self.x_series,
|
||||
self.y_series)
|
||||
self.trigger_series_sequence.emit(self.x_series, self.y_series)
|
||||
#print("emit")
|
||||
self.data_series = []
|
||||
self.time_series = []
|
||||
@@ -2754,75 +2786,73 @@ class CAQStripChart(PlotWidget):
|
||||
else:
|
||||
self.data_series = []
|
||||
self.time_series = []
|
||||
|
||||
|
||||
'''
|
||||
|
||||
|
||||
|
||||
#dt = (self.x[-1] - self.x[-2])
|
||||
#dt = (self.x[-1] - self.x[-2])
|
||||
#print("dt", dt)
|
||||
#Lowet IPCT before trigger is set to t=0
|
||||
idx = self.idx[_row]
|
||||
self.x_shifted[_row] = list(
|
||||
map(lambda m: (m - self.time_delta[_row]), self.x[_row][idx:]))
|
||||
self.x_shifted[_row] = list(map(lambda m : (m - self.time_delta[_row]), self.x[_row][idx:]))
|
||||
|
||||
##self.y = np.where(self.y != self.y, 0, self.y) #test for nan
|
||||
|
||||
|
||||
#print("row len len ", _row, self.time_delta[0], self.time_delta[1])
|
||||
|
||||
|
||||
|
||||
|
||||
self.curve[_row].setData(self.x_shifted[_row], self.y[_row][idx:])
|
||||
|
||||
|
||||
self.time_delta[_row] = (
|
||||
_pvd.ts[0] + _pvd.ts[1]*10**(-9)) - self.time_zero[0]
|
||||
|
||||
|
||||
_pvd.ts[0] + _pvd.ts[1]*10**(-9)) - self.time_zero[0]
|
||||
|
||||
|
||||
'''
|
||||
LOOK_BACK = -800
|
||||
LOOK_BACK = -800
|
||||
if 'ARIDI-PCT2:CURRENT' in self.pv_gateway[_row].pv_name:
|
||||
LOOK_BACK = -250
|
||||
|
||||
if value > self.y[-2]:
|
||||
if value > self.y[-2]:
|
||||
if not self.found:
|
||||
#print(x_shifted[-240:], self.y[-240:])
|
||||
#self.y = np.where(self.y != self.y, 0, self.y) #test for nan
|
||||
max_index = self.y[LOOK_BACK:].argmax()
|
||||
|
||||
|
||||
if max_index == 0:
|
||||
return
|
||||
print("max index=", max_index)
|
||||
|
||||
#print(x_shifted[-600+max_index:], self.x[-600+max_index:])
|
||||
#print(self.y[-600+max_index:-2])
|
||||
|
||||
#print(x_shifted[-600+max_index:], self.x[-600+max_index:])
|
||||
#print(self.y[-600+max_index:-2])
|
||||
self.found = True
|
||||
#print("Are Signals blocked??", self.signalsBlocked())
|
||||
self.trigger_decay_sequence.emit(np.array(
|
||||
x_shifted[LOOK_BACK+max_index+9:-2]),
|
||||
self.y[LOOK_BACK+max_index+9:-2])
|
||||
x_shifted[LOOK_BACK+max_index+9:-2]), self.y[LOOK_BACK+max_index+9:-2])
|
||||
else:
|
||||
self.found = False
|
||||
'''
|
||||
|
||||
'''
|
||||
|
||||
|
||||
@Slot(int, str, int)
|
||||
def receive_connect_update(self, handle: int, pv_name: str, status: int):
|
||||
'''Triggered by connect signal'''
|
||||
print("pv_name==>", pv_name)
|
||||
|
||||
|
||||
_row = self.pv2item_dict[self.sender()]
|
||||
self.pv_gateway[_row].receive_connect_update(handle, pv_name, status,
|
||||
self.pv_gateway[_row].receive_connect_update(handle, pv_name, status,
|
||||
post_display=False)
|
||||
|
||||
#self.pv_gateway.receive_connect_update(handle, pv_name, status)
|
||||
_pvd = self.pv_gateway[_row].cafe.getPVCache(
|
||||
self.pv_gateway[_row].handle)
|
||||
_pvd = self.pv_gateway[_row].cafe.getPVCache(self.pv_gateway[_row].handle)
|
||||
if self.time_zero[_row] == 0:
|
||||
self.time_zero[_row] = _pvd.ts[0] + _pvd.ts[1]*10**(-9)
|
||||
|
||||
|
||||
self.pvd_previous = _pvd
|
||||
|
||||
|
||||
#renove highlighting which persists after mouse leaves
|
||||
def mouseMoveEvent(self, event):
|
||||
#event.ignore()
|
||||
pass
|
||||
|
||||
def leaveEvent(self, event):
|
||||
|
||||
3461
pvwidgets.py:2.9
Normal file
3461
pvwidgets.py:2.9
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user