diff --git a/Readme.md b/Readme.md
index d8b0e3a..3d4c00b 100644
--- a/Readme.md
+++ b/Readme.md
@@ -291,17 +291,44 @@ bt
Localize mionitors and callbacks:
```
-grep -n 'def cb_update_img(self):' *.py
+grep -Rn 'add_callback' *.py
swissmx.py:698: self.sigNewCamImg.connect(self.cb_update_img)
swissmx.py:745: def cb_update_img(self):
+epics_widgets/MotorTweak.py:88: m.set_callback('RBV', self.emit_signals, {'source_field': 'RBV'})
+epics_widgets/SmaractMotorTweak.py:100: self._pv_readback.add_callback(self.update_label)
+swissmx.py:717: cam.run(self.cb_new_frame_pv)
+swissmx.py:743: self.sigNewCamImg.emit()
+swissmx.py:745: def cb_update_img(self):
+swissmx.py:698: self.sigNewCamImg.connect(self.cb_update_img)
+camera.py:159: self._pv['pic'] = epics.PV(self._prefix + "FPICTURE", auto_monitor=True, callback=cb)
+-> try to turn of the monitors during ascuisition:
+zamofing_t@ganymede:~/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX$
+grep -r set_callback *
+
+https://pyepics.github.io/pyepics/pv.html#automatic-monitoring-of-a-pv
+
+
+Try with:
+pv.clear_auto_monitor() -> pv.reconnect()
+
+pv.remove_callback(index=None) -> pv.add_callback(callback=None[, index=None [, with_ctrlvars=True[, **kw]])
+pv.set_callback
+
+FixTargetFrame -> paint -> _log.debug()
+
+
+Turn off jungfrau.
+no motion -> wait 1h
+constant up-dow motion code -> wait 1h
```
+ try: #pv-monitor-func
----------------------------------- SCRATCH -----------------------------------
diff --git a/epics_widgets/SmaractMotorTweak.py b/epics_widgets/SmaractMotorTweak.py
deleted file mode 100644
index 2ea597a..0000000
--- a/epics_widgets/SmaractMotorTweak.py
+++ /dev/null
@@ -1,341 +0,0 @@
-import math
-import logging
-from time import sleep
-from PyQt5.QtCore import Qt, pyqtSignal
-from PyQt5.QtGui import QPainter, QBrush, QColor, QPainterPath, QPen, QDoubleValidator
-from PyQt5.QtWidgets import QMenu, QInputDialog, QAction
-from PyQt5.uic import loadUiType
-from epics import PV
-from epics.ca import pend_event
-from app_utils import assert_tweaker_positions
-
-Ui_MotorTweak, QWidget = loadUiType('epics_widgets/MotorTweak.ui')
-logger = logging.getLogger(__name__)
-logger.setLevel(logging.INFO)
-
-SPMG_STOP = 0
-SPMG_PAUSE = 1
-SPMG_MOVE = 2
-SPMG_GO = 3
-
-
-
-class SmaractMotorTweak(QWidget, Ui_MotorTweak):
- event_val = pyqtSignal(str, dict)
- event_rbv = pyqtSignal(str, dict)
- event_soft_limit = pyqtSignal(str, dict)
- event_high_hard_limit = pyqtSignal(str, dict)
- event_low_hard_limit = pyqtSignal(str, dict)
- event_axis_fault = pyqtSignal(str, dict)
-
- def __init__(self, parent=None):
- super(SmaractMotorTweak, self).__init__(parent=parent)
- self.setupUi(self)
- self._wheel_tweaks = True
- self._auto_labels = True
- self._locked = False
- self._label_style = 'basic'
- self._templates_source = {
- 'basic': '{label} {{rbv:.{precision}f}} {units}',
- 'small': '{label} {{rbv:.{precision}f}} {units}',
- '2 lines': '{label}
{{rbv:.{precision}f}} {units}',
- 'busy': '{label} {{rbv:.{precision}f}} {units}'
- }
- self._templates = {}
-
-
- def connect_motor(self, rec_name, **kwargs):
- # TODO: DO NOT USE so many PVs, but reduce to the only really needed PV: s.a. class QopticZoom(object)
- label=kwargs['label']
- self._label=label
- self._pvname = rec_name+':DRIVE'
- self._pv_name = PV(rec_name+':NAME')
- self._pv_drive = PV(rec_name+':DRIVE')
- self._pv_readback = PV(rec_name+':MOTRBV')
- self._pv_tweak_r = PV(rec_name+':TWR.PROC')
- self._pv_tweak_f = PV(rec_name+':TWF.PROC')
- self._pv_tweak_val = PV(rec_name+':TWV')
- self._pv_status = PV(rec_name + ':STATUS')
- self._pv_home_f = PV(rec_name + ':FRM_FORW.PROC')
- self._pv_home_b = PV(rec_name + ':FRM_BACK.PROC')
- self._pv_is_homed = PV(rec_name + ':GET_HOMED')
- self._pv_llm = PV(rec_name + ':LLM')
- self._pv_hlm = PV(rec_name + ':HLM')
-
- self.label.setToolTip('{} => {}'.format(rec_name, self._pv_name.get()))
-
- try:
- self._prec = kwargs['prec']
- except:
- self._prec = 5
-
- try:
- self._units = kwargs['units']
- except:
- self._units = 'mm'
-
- self._ignore_limits = self._pv_llm.get() == self._pv_hlm.get() # if both high/low limits are equal they are meaningless
-
- self.set_motor_validator()
- self._drive_val.setText(self._pv_drive.get(as_string=True))
- self._drive_val.returnPressed.connect(self.move_abs)
-
- self.jog_forward.hide()
- self.jog_reverse.hide()
-
- tweak_min = kwargs.get("tweak_min", 0.0001)
- tweak_max = kwargs.get("tweak_max", 20.0)
- self._tweak_val.setText(self._pv_tweak_val.get(as_string=True))
- self._tweak_val.setValidator(QDoubleValidator(tweak_min, tweak_max, 4, self._tweak_val))
- self._tweak_val.editingFinished.connect(lambda m=self._pv_tweak_val: m.put(self._tweak_val.text()))
-
- self.tweak_forward.clicked.connect(lambda m: self._pv_tweak_f.put(1))
- self.tweak_reverse.clicked.connect(lambda m: self._pv_tweak_r.put(1))
-
-
- self.bind_wheel()
-
- self.update_label_template()
-
- self._pv_readback.add_callback(self.update_label)
- self._pv_status.add_callback(self.set_val_on_status_change)
-
- # self._pv_drive.add_callback(self.set_val)
- self._pv_drive.add_callback(self.emit_signals, source_field='VAL')
- self._pv_readback.add_callback(self.emit_signals, source_field='RBV')
- self._pv_hlm.add_callback(self.emit_signals, source_field='HLS')
- self._pv_llm.add_callback(self.emit_signals, source_field='LLS')
-
- # m.set_callback('HLM', self.set_motor_validator)
-
-
- def set_motor_validator(self, **kwargs):
- lineedit = self._drive_val
- min, max = self._pv_llm.get(), self._pv_hlm.get()
- if min == max:
- min = -1e6
- max = 1e6
- lineedit.setValidator(QDoubleValidator(min, max, 5, lineedit))
-
-
- def move_rel(self, dist, delay=None):
- cur = self._pv_readback.get()
- target = cur + dist
- if delay:
- sleep(delay)
- self._pv_drive.put(target)
-
- def get_rbv(self):
- return self._pv_readback.get(use_monitor=False)
-
- def get_val(self):
- # return self._motor.get('VAL')
- try:
- v=self._val
- except AttributeError:
- self._val=v=self._pv_drive.get()
- return v
-
- def is_homed(self):
- pend_event()
- return 1 == self._pv_is_homed.get(use_monitor=False)
-
- def get_status(self, as_string=False):
- """
- States:
- 0 Stopped
- 1 Stepping
- 2 Scanning
- 3 Holding
- 4 Targeting
- 5 Move Delay
- 6 Calibrating
- 7 Finding Ref
- 8 Locked
- :return:
- """
- return self._pv_status.get(as_string=as_string, use_monitor=False)
-
- def wait(self):
- pend_event(.01)
- while not self.is_done():
- pend_event(0.2)
-
- def is_done(self):
- return self._pv_status.get() in (0, 3)
-
- def move_abs(self, drive=None, wait=False, assert_position=False):
- if assert_position:
- wait=True
- if drive is None:
- logger.debug('{} abs target from widget'.format(self._label))
- drive = float(self._drive_val.text())
- logger.debug('{} abs move => {}'.format(self._label, drive))
- self._pv_drive.put(drive)
- if wait:
- self.wait()
- if assert_position:
- assert_tweaker_positions([(self, drive, 0.05)], timeout=10.)
-
- def emit_signals(self, **kw):
- field = kw['source_field']
- if field == 'VAL':
- self.event_val.emit(self._pvname, kw)
- elif field == 'RBV':
- self.event_rbv.emit(self._pvname, kw)
- elif field == 'LVIO':
- self.event_soft_limit.emit(self._pvname, kw)
- elif field == 'HLS':
- self.event_high_hard_limit.emit(self._pvname, kw)
- self.event_axis_fault.emit(self._pvname, kw)
- elif field == 'LVIO':
- self.event_low_hard_limit.emit(self._pvname, kw)
- self.event_axis_fault.emit(self._pvname, kw)
- elif field == 'STAT':
- self.event_axis_fault.emit(self._pvname, kw)
-
-
- def set_val_on_status_change(self, **kw):
- '''
- 0 Stopped
- 1 Stepping
- 2 Scanning
- 3 Holding
- 4 Targeting
- 5 Move Delay
- 6 Calibrating
- 7 Finding Ref
- 8 Locked
- :param kw:
- :return:
- '''
- status = kw['char_value']
- if status in ('Holding', 'Stopped'):
- v = self._pv_readback.get(as_string=True)
- logger.debug('updating VAL on status change to holding/stopped = {}'.format(v))
- self._drive_val.setText(v)
-
- def set_val(self, **kw):
- v = kw['char_value']
- logger.debug('updating VAL = {}'.format(v))
- self._drive_val.setText(v)
-
- def update_label(self, **kwargs):
- self.label.setText(self._templates[self._label_style].format(rbv=self._pv_readback.get()))
- self.tweak_forward.setToolTip('tweak forward by {:.3f} {}'.format(self._pv_tweak_val.get(), self._units))
- self.tweak_reverse.setToolTip('tweak reverse by {:.3f} {}'.format(self._pv_tweak_val.get(), self._units))
-
- def tweak_event(self, event):
- sign = event.angleDelta().y()
- if sign < 0:
- self._pv_tweak_r.put(1)
- else:
- self._pv_tweak_f.put(1)
-
- def bind_wheel(self):
- self.tweak_forward.wheelEvent = self.tweak_event
- self.tweak_reverse.wheelEvent = self.tweak_event
-
- def contextMenuEvent(self, event):
- name = self._pv_name.get()
- unit = self._units
- prec = self._prec
-
- menu = QMenu(self)
- menu.setTitle(self._label)
-
- lockmotor = QAction('lock motor', menu, checkable=True)
- lockmotor.setChecked(self._locked)
- menu.addAction(lockmotor)
-
- autolabelsAction = QAction('auto', menu, checkable=True)
- autolabelsAction.setChecked(self._auto_labels)
- menu.addAction(autolabelsAction)
-
- wheel_tweaks = QAction('Mouse wheel tweaks motor', menu, checkable=True)
- wheel_tweaks.setChecked(self._wheel_tweaks)
- menu.addAction(wheel_tweaks)
-
- # stopmotorAction = QAction('Stopped', menu, checkable=True)
- # stopmotorAction.setChecked(SPMG_STOP == m.stop_go)
- # menu.addAction(stopmotorAction)
- changeprecAction = menu.addAction("Change Precision")
- changetweakstepAction = menu.addAction("Tweak step {:.3f} {}".format(self._pv_tweak_val.get(), unit))
-
- tozeroAction = menu.addAction("move to Zero")
-
-
- action = menu.exec_(self.mapToGlobal(event.pos()))
- if action == lockmotor:
- self._locked = not self._locked
- if self._locked:
- self._controlbox.setDisabled(True)
- else:
- self._controlbox.setDisabled(False)
- elif action == changeprecAction:
- msg = 'Precision for motor {}'.format(name)
- logger.debug('prec before %d', prec)
- prec, ok = QInputDialog.getInt(self, msg, msg, prec, 0, 10)
- logger.debug('prec after (%d) %d', ok, prec)
- if ok:
- self._prec = prec
-
- elif action == changetweakstepAction:
- tv = self._pv_tweak_val.get()
- msg = 'Tweak step for motor {} at {} {}'.format(name, tv, unit)
- tv, ok = QInputDialog.getDouble(self, msg, msg, tv, pow(10, -prec), 10.0, prec)
- if ok:
- self._pv_tweak_val.put(tv)
-
- elif action == tozeroAction:
- self._pv_drive.put(0.0)
-
- elif action == autolabelsAction:
- self._auto_labels = not self._auto_labels
-
- elif action == wheel_tweaks:
- self._wheel_tweaks = not self._wheel_tweaks
- self.bind_wheel()
-
- self.update_label_template()
-
- def resizeEvent(self, event):
- pass
-
- def update_label_template(self):
- source = self._templates_source
- target = self._templates
-
- for k in source:
- target[k] = source[k].format(
- label=self._label,
- precision=self._prec,
- units=self._units)
- self.label.setText(target[self._label_style].format(rbv=self._pv_readback.get()))
-
- def paintEvent(self, e):
- qp = QPainter()
- qp.begin(self)
- qp.setRenderHint(QPainter.Antialiasing)
- self._draw_limits(qp)
- qp.end()
-
- def _draw_limits(self, qp):
- pass
- # width, height = self.size().width(), self.size().height()
- # pad = 5
- # rounding = 2
- # size = 10
- # if m.HLS:
- # x, y, w, h = width - size, pad, size, height - 2 * pad
- # elif m.LLS:
- # x, y, w, h = 0, pad, size, height - 2 * pad
- # else:
- # return
- # color = QColor('indianred')
- # qp.setBrush(QBrush(color, Qt.SolidPattern))
- # qp.setPen(QPen(color))
- # path = QPainterPath()
- # path.setFillRule(Qt.WindingFill)
- # path.addRoundedRect(x, y, w, h, rounding, rounding)
- # qp.drawPath(path)
diff --git a/swissmx.py b/swissmx.py
index 36d26a0..8ffab76 100755
--- a/swissmx.py
+++ b/swissmx.py
@@ -143,7 +143,6 @@ from PyQt5.uic import loadUiType
ts.log('Import part 4/8:')
import pyqtUsrObj as UsrGO
from epics_widgets.MotorTweak import MotorTweak
-from epics_widgets.SmaractMotorTweak import SmaractMotorTweak
from epics_widgets.SimMotorTweak import SimMotorTweak
ts.log('Import part 5/8:')
import numpy as np
@@ -906,7 +905,7 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
if sim&0x20:
m_tw=SimMotorTweak()
else:
- m_tw=SmaractMotorTweak()
+ m_tw=MotorTweak()
m_tw.connect_motor(rec, **kwargs)
self.tweakers[kwargs['alias']] = m_tw
return m_tw
@@ -1019,6 +1018,8 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
def build_group_collimator(self, toolbox):
pfx=QApplication.instance()._cfg.value(AppCfg.GBL_DEV_PREFIX)[1]
+ _log.warning('TODO: cleanup PV names!!!')
+ pfx='SARES30-SMX'
c=QWidget()
c.setLayout(QGridLayout())
f=lambda v: lambda x:self.move_collimator(v) #needs nested lambda to work ...
@@ -1027,8 +1028,8 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
but.clicked.connect(f(v))
c.layout().addWidget(but, 0, i)
widgets = [
- self.get_tweaker(f"{pfx}1", alias="colli_x", label="colli X", mtype=1,),
- self.get_tweaker(f"{pfx}2", alias="colli_y", label="colli Y", mtype=1,),
+ self.get_tweaker(f"{pfx}:MCS1", alias="colli_x", label="colli X", mtype=1,),
+ self.get_tweaker(f"{pfx}:MCS2", alias="colli_y", label="colli Y", mtype=1,),
c,
]
qutilities.add_item_to_toolbox(toolbox,"Collimator",widget_list=widgets)
@@ -1036,12 +1037,14 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
def build_group_posttube(self, toolbox):
pfx=QApplication.instance()._cfg.value(AppCfg.GBL_DEV_PREFIX)[1]
+ _log.warning('TODO: cleanup PV names!!!')
+ pfx='SARES30-SMX'
widgets = [
- self.get_tweaker(f"{pfx}4", alias="tube_usx", label="upstream X", mtype=1,),
- self.get_tweaker(f"{pfx}6", alias="tube_usy", label="upstream Y", mtype=1,),
- self.get_tweaker(f"{pfx}5", alias="tube_dsx", label="downstream X", mtype=1,),
- self.get_tweaker(f"{pfx}7", alias="tube_dsy", label="downstream Y", mtype=1,),
- self.get_tweaker(f"{pfx}8", alias="tube_z", label="tube Z", mtype=1),
+ self.get_tweaker(f"{pfx}:MCS4", alias="tube_usx", label="upstream X", mtype=1,),
+ self.get_tweaker(f"{pfx}:MCS6", alias="tube_usy", label="upstream Y", mtype=1,),
+ self.get_tweaker(f"{pfx}:MCS5", alias="tube_dsx", label="downstream X", mtype=1,),
+ self.get_tweaker(f"{pfx}:MCS7", alias="tube_dsy", label="downstream Y", mtype=1,),
+ self.get_tweaker(f"{pfx}:MCS8", alias="tube_z", label="tube Z", mtype=1),
]
c = QWidget()
c.setLayout(QGridLayout())
@@ -1067,9 +1070,11 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
def build_group_xeye(self, toolbox):
pfx=QApplication.instance()._cfg.value(AppCfg.GBL_DEV_PREFIX)[1]
+ _log.warning('TODO: cleanup PV names!!!')
+ pfx='SARES30-SMX'
widgets=[
- self.get_tweaker(f"{pfx}14", alias="xeye_x", label="X", mtype=1),
- self.get_tweaker(f"{pfx}15", alias="xeye_y", label="Y", mtype=1),
+ self.get_tweaker(f"{pfx}:MCS14", alias="xeye_x", label="X", mtype=1),
+ self.get_tweaker(f"{pfx}:MCS15", alias="xeye_y", label="Y", mtype=1),
]
qutilities.add_item_to_toolbox(toolbox,"X-Ray Eye",widget_list=widgets)
WndSwissMx.pv_monitor_add(widgets)