diff --git a/Readme.md b/Readme.md index 72a84bf..ca8f8ba 100644 --- a/Readme.md +++ b/Readme.md @@ -7,7 +7,6 @@ pyqtgraph.examples.run() ``` - EPICS simulator --------------- ``` @@ -67,8 +66,13 @@ cd /tmp/qtawesome EPICS_CA_ADDR_LIST='129.129.244.255 sf-saresc-cagw.psi.ch:5062 sf-saresc-cagw.psi.ch:5066' cd /home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/oldRepos/app/src python swissmx.py +``` - +pyqtgraph examples +------------------ +``` +import pyqtgraph.examples +pyqtgraph.examples.run() ``` @@ -90,8 +94,6 @@ wlp2s0: MAC: 80:38:fb:d6:01:78 wlan-corp 129.129.64.249 enx00e04c680519: MAC: 00:e0:4c:68:05:19 -import pyqtgraph.examples -pyqtgraph.examples.run() Benchmark -> VideoSpeedTest rsync -vai /home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/SwissMX/ saresc-cons-02:/tmp/zamofing_t/ diff --git a/app_config.py b/app_config.py index e56d275..d12b385 100644 --- a/app_config.py +++ b/app_config.py @@ -12,20 +12,22 @@ from PyQt5.QtCore import QSettings import os, json, yaml class AppCfg(QSettings): - WINDOW_GEOMETRY="window/geometry" - WINDOW_STATE= "window/state" - WINDOW_SPLITTER="window/splitter" - - # ---------- OBSOLETE ??? ---------- - ZOOM_BUTTONS="sample_viewing/zoom_buttons" - - SKIP_ESCAPE_TRANSITIONS_IF_SAFE="escape/skip_transitions_if_safe" GEO_OPT_CTR='geometry/opt_ctr' GEO_PIX2POS='geometry/pix2pos' - BEAM_MARKER_POSITIONS="beam/marker_positions" - BEAM_SIZE="beam/size" + GEO_BEAM_SZ="geometry/beam_size" + GEO_BEAM_POS="geometry/beam_pos" + + + WINDOW_GEOMETRY="window/geometry" + WINDOW_SPLITTER="window/splitter" + WINDOW_STATE= "window/state" + + # ---------- OBSOLETE ??? ---------- + #ZOOM_BUTTONS="sample_viewing/zoom_buttons" + + SKIP_ESCAPE_TRANSITIONS_IF_SAFE="escape/skip_transitions_if_safe" CRYOJET_MOTION_ENABLED="cryojet/motion_enabled" CRYOJET_NOZZLE_OUT="cryojet/nozzle_out" @@ -47,9 +49,78 @@ class AppCfg(QSettings): def __init__(self): super(AppCfg, self).__init__("PSI", "SwissMX") keys = self.allKeys() + # Dump config to debug + #for k in keys: + # print(k, self.value(k)) + #set default keys if not existing - if AppCfg.BEAM_SIZE not in keys: - self.setValue(AppCfg.BEAM_SIZE, [40, 20]) #([40, 20) -> tuples are not supported natively + if AppCfg.GEO_BEAM_SZ not in keys: + _log.warning(f'{AppCfg.GEO_BEAM_SZ} not defined. set default') + self.setValue(AppCfg.GEO_BEAM_SZ, [40, 20]) #([40, 20) -> tuples are not supported natively + + if AppCfg.GEO_PIX2POS not in keys: + _log.warning(f'{AppCfg.GEO_OPT_CTR} not defined. calc default') + import geometry + geo=geometry.geometry() + pix2pos_measure={ + 1:[(-3.0, -7.6, 116.99110193046, 632.5463827525), + (-2.0, -7.6, 934.07501517856, 600.7926167715), + (-2.0, -7.1, 916.54131238102, 191.0366615002), + (-3.0, -7.1, 103.74668003329, 226.2150231456)], + 200:[(-3.1, -7.3, 113.66321353086, 824.9041423107), + (-2.3, -7.3, 1065.97386092697, 792.2851118419), + (-2.3, -6.7, 1033.68452410347, 74.0336610693), + (-3.1, -6.7, 84.62681572700, 116.6832971512)], + 400:[(-3.4, -6.7, 155.00053674203, 601.3838942136), + (-3.0, -6.7, 957.95919656052, 573.0827012272), + (-3.2, -6.5, 541.08684037200, 187.9171307943), + (-3.2, -6.8, 564.32152887203, 789.1146957326)], + 600:[(-3.3, -6.8, 328.27244399903, 509.5061192017), + (-3.1, -6.8, 992.78996735279, 488.0323963092), + (-3.2, -6.9, 672.03111567934, 832.4122409755), + (-3.2, -6.7, 645.70960116180, 164.2534779331)], + 800:[(-3.2, -6.7, 639.52253576449, 53.4455632943), + (-3.2, -6.85, 671.47023245203, 882.6335091391), + (-3.3, -6.75, 105.12470026379, 361.3051859197), + (-3.1, -6.75, 1195.96864609255, 313.1068618673)], + 1000:[(-3.25, -6.75, 195.05641095116, 353.3492286375), + (-3.15, -6.75, 1117.27204644084, 314.9636405871), + (-3.2, -6.8, 675.10991143017, 790.3040145281), + (-3.2, -6.72, 638.98580653116, 59.3803912957)]} + geo.update_pix2pos(pix2pos_measure) + self.setValue(AppCfg.GEO_PIX2POS, geo._lut_pix2pos) + + if AppCfg.GEO_OPT_CTR not in keys: + _log.warning(f'{AppCfg.GEO_OPT_CTR} not defined. calc default') + import geometry + geo=geometry.geometry() + opt_ctr_meas={ # x,y = 0.02, -4.89 + 1000:[(1057.4251530483375, 116.10122290395591), + (117.84916300310408, 190.27827474963223), + (184.2181041281829, 963.2812360887852), + (1092.5616512910262, 899.514998537239)], + 800:[(888.2494207687248, 203.2917926172947), + (329.96950424600305, 248.83910515411347), + (372.9141132092893, 708.2162858826), + (906.4683457834523, 675.6824912134438)], + 600:[(781.5385742538922, 251.44180872764602), + (447.09116505496564, 264.4553265953085), + (471.81684900352445, 554.6567750441825), + (798.4561474818535, 535.1364982426887)], + 400:[(722.9777438494109, 286.5783069703348), + (525.1722722609408, 295.68776947769857), + (535.5830865550707, 462.26079818377866), + (729.4845027832422, 450.5486321028824)], + 200:[(689.1425973934884, 308.70128734536104), + (565.5141776506945, 307.39993555859473), + (574.6236401580583, 406.30267135282986), + (693.0466527537872, 399.79591241899857)], + 1:[(673.5263759522934, 307.39993555859473), + (591.5412133860195, 308.70128734536104), + (595.4452687463182, 376.3715802572061), + (672.2250241655271, 373.7688766836736)]} + geo.update_optical_center(opt_ctr_meas) + self.setValue(AppCfg.GEO_OPT_CTR, geo._opt_ctr) #if AppCfg.ACTIVATE_PULSE_PICKER not in keys: # self.setValue(AppCfg.ACTIVATE_PULSE_PICKER, False) diff --git a/epics_widgets/SimMotorTweak.py b/epics_widgets/SimMotorTweak.py index 112f238..29401f6 100644 --- a/epics_widgets/SimMotorTweak.py +++ b/epics_widgets/SimMotorTweak.py @@ -18,8 +18,8 @@ from PyQt5.uic import loadUiType from epics.ca import pend_event Ui_MotorTweak, QWidget = loadUiType('epics_widgets/MotorTweak.ui') -logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) +_log = logging.getLogger(__name__) +#logger.setLevel(logging.INFO) class SimMotor: def __init__(self,motor_base, short_name): @@ -140,9 +140,9 @@ class SimMotorTweak(QWidget, Ui_MotorTweak): if assert_position: wait=True if drive is None: - logger.debug('{} abs target from widget'.format(self.short_name)) + _log.debug('{} abs target from widget'.format(self.motor._short_name)) drive = float(self._drive_val.text()) - logger.debug('{} abs move => {}'.format(self.short_name, drive)) + _log.debug('{} abs move => {}'.format(self.motor._short_name, drive)) self._pos=drive def emit_signals(self, **kw): @@ -180,12 +180,12 @@ class SimMotorTweak(QWidget, Ui_MotorTweak): 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)) + _log.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)) + _log.debug('updating VAL = {}'.format(v)) self._drive_val.setText(v) def update_label(self, **kwargs): @@ -242,9 +242,9 @@ class SimMotorTweak(QWidget, Ui_MotorTweak): self._controlbox.setDisabled(False) elif action == changeprecAction: msg = 'Precision for motor {}'.format(name) - logger.debug('prec before %d', prec) + _log.debug('prec before %d', prec) prec, ok = QInputDialog.getInt(self, msg, msg, prec, 0, 10) - logger.debug('prec after (%d) %d', ok, prec) + _log.debug('prec after (%d) %d', ok, prec) if ok: self._prec = prec diff --git a/illumination.py b/illumination.py index c10f87d..17b2897 100755 --- a/illumination.py +++ b/illumination.py @@ -92,7 +92,7 @@ class IlluminationControl(object): try: s=self._socket except AttributeError: #simulated mode - _log.info('simulated mode') + _log.debug('simulated mode') return self._sim['stat'] self.send_command(bytes((stat,all))) resp = self._socket.recv(1024) diff --git a/pyqtUsrObj.py b/pyqtUsrObj.py index 476e288..bd78dc2 100644 --- a/pyqtUsrObj.py +++ b/pyqtUsrObj.py @@ -19,29 +19,37 @@ import numpy as np from PyQt5.QtGui import QPolygon,QPolygonF from PyQt5.QtCore import QPointF,QLineF -def obj_info(obj): - print(f"obj_info:{obj}") +def obj_tree(obj,p=''): + obj_info(obj,p) + for o in obj.childItems(): + obj_tree(o,p+'.') + +def obj_info(obj,p=''): + print(f"{p}obj_info:{obj}") try: pos=obj.pos() - print(f"Pos:({pos.x():.6g},{pos.y():.6g})") # in coordinate value on the scene (no change by zooming) + print(f"{p}Pos:({pos.x():.6g},{pos.y():.6g})") # in coordinate value on the scene (no change by zooming) except AttributeError: pass try: for k, v in (('Viewport', obj.viewport()), ('Window', obj.window())): print( - f"{k} (x,y)(w,h):({v.x():.6g},{v.y():.6g})({v.width():.6g},{v.height():.6g})") # in coordinate value on the scene (no change by zooming) + f"{p}{k} (x,y)(w,h):({v.x():.6g},{v.y():.6g})({v.width():.6g},{v.height():.6g})") # in coordinate value on the scene (no change by zooming) except AttributeError: pass try: scnPos=obj.scenePos() - print(f"scenePos:({scnPos.x():.6g},{scnPos.y():.6g})") # in pixel on the scene (changes by zooming) + print(f"{p}scenePos:({scnPos.x():.6g},{scnPos.y():.6g})") # in pixel on the scene (changes by zooming) except AttributeError: pass try: - t=obj.transform() - print(f"QTransform:{t.m11():8.5g} {t.m12():8.5g} {t.m13():8.5g}") - print(f" {t.m21():8.5g} {t.m22():8.5g} {t.m23():8.5g}") - print(f" {t.m31():8.5g} {t.m32():8.5g} {t.m33():8.5g}") + if type(obj)==QtGui.QTransform: + t=obj + else: + t=obj.transform() + print(f"{p}QTransform:{t.m11():8.5g} {t.m12():8.5g} {t.m13():8.5g}") + print(f"{p} {t.m21():8.5g} {t.m22():8.5g} {t.m23():8.5g}") + print(f"{p} {t.m31():8.5g} {t.m32():8.5g} {t.m33():8.5g}") except AttributeError: pass diff --git a/swissmx.py b/swissmx.py index 8075b3c..5a3ff3e 100755 --- a/swissmx.py +++ b/swissmx.py @@ -20,13 +20,18 @@ bitmask for simulation: ''' import logging +logging.basicConfig(level=logging.DEBUG, format='%(levelname)s:%(module)s:%(lineno)d:%(funcName)s:%(message)s ') + logging.getLogger('PyQt5.uic').setLevel(logging.INFO) logging.getLogger('requests').setLevel(logging.INFO) logging.getLogger('urllib3').setLevel(logging.INFO) logging.getLogger('paramiko').setLevel(logging.INFO) logging.getLogger('matplotlib').setLevel(logging.INFO) -logging.basicConfig(level=logging.DEBUG, format='%(levelname)s:%(module)s:%(lineno)d:%(funcName)s:%(message)s ') +logging.getLogger('PIL').setLevel(logging.INFO) +logging.getLogger('illumination').setLevel(logging.INFO) +logging.getLogger('zoom').setLevel(logging.INFO) _log = logging.getLogger("swissmx") +#_log.setLevel(logging.INFO) import time class timestamp(): @@ -52,7 +57,7 @@ import random, signal TASK_JUNGFRAU_SETTINGS = "jungfrau_settings" -TASK_SETUP_PPM_CALIBRATION = "ppm_calibration" +TASK_SETUP_GEOMETRY_CALIB = "geometry_calib" TASK_SETUP_PPM_CALIBRATION_TBOX = "ppm_calibration_tbox" TASK_SETUP_BEAM_CENTER = "beamcenter_calibration" TASK_SETUP_CAMERA = "setup_camera" @@ -146,25 +151,9 @@ ts.log('Import part 7/7:') #_log.info(f"connecting to microscope to camera server: {appsconf['microscope']['sample_camera']['pv_prefix']} ") #sample_camera = camera.camera_server(basename=appsconf["microscope"]["sample_camera"]["pv_prefix"]) #ZAC: orig. code -def print_transform(t): - m11 = t.m11() - m12 = t.m12() - m13 = t.m13() - m21 = t.m21() - m22 = t.m22() - m23 = t.m23() - m31 = t.m31() - m32 = t.m32() - m33 = t.m33() - print("{:20s}{:12.3f} {:12.3f} {:12.3f}".format("Transform", m11, m12, m13)) - print("{:20s}{:12.3f} {:12.3f} {:12.3f}".format(" ", m21, m22, m23)) - print("{:20s}{:12.3f} {:12.3f} {:12.3f}".format(" ", m31, m32, m33)) - - def tdstamp(): return time.strftime("%Y%m%dH%H%M%S") - def datestamp(): return time.strftime("%Y%m%d") @@ -286,12 +275,12 @@ class Main(QMainWindow, Ui_MainWindow): self._status_task.setAccessibleName("status_task_label") self.statusbar.addPermanentWidget(self._status_task) - self.add_beam_marker() - self._beam_markers = {} + #self.add_beam_marker() + #self._beam_markers = {} # ppm calibration - self._zoom_to_ppm = {} - self._ppm_click = None + #self._zoom_to_ppm = {} + #self._ppm_click = None self.load_stylesheet() @@ -318,31 +307,53 @@ class Main(QMainWindow, Ui_MainWindow): self.switch_task() def init_graphics(self): + app = QApplication.instance() + cfg = app._cfg self.glw = pg.GraphicsLayoutWidget() self.microscope_page.setLayout(QVBoxLayout()) self.microscope_page.layout().addWidget(self.glw) self.glw.show() + self.glw.scene().sigMouseMoved.connect(self.mouse_move_event) + self.glw.scene().sigMouseClicked.connect(self.mouse_click_event) - self.vb=vb=self.glw.addViewBox(invertY=False)#,enableMenu=False) + #--- viewbox --- + self.vb=vb=self.glw.addViewBox(invertY=False)#),border='r')#,enableMenu=False) + vb.setAspectLocked(True) + vb.setBackgroundColor((120, 90, 90)) + + #--- image --- self.img=img=pg.ImageItem() tr=QtGui.QTransform() # prepare ImageItem transformation: - tr.rotate(30) + #opt_ctr=app._geometry._opt_ctr tr.setMatrix(-1, 0, 0, 0,-1, 0, 0, 0, 1) + # opt_ctr[0], opt_ctr[1], 1) img.setTransform(tr) # assign transform - # self.graphicsView.setCentralItem(self.vb) - self.glw.scene().sigMouseMoved.connect(self.mouse_move_event) - self.glw.scene().sigMouseClicked.connect(self.mouse_click_event) - vb.setAspectLocked(True) - vb.setBackgroundColor((120, 90, 90)) vb.addItem(img) + + #--- grid --- try: grid=pg.GridItem(pen=(0,255,0),textPen=(0,255,0)) #green grid and labels except: grid=pg.GridItem() + tr.reset() + grid.setTransform(tr) # assign transform vb.addItem(grid) + #--- beam marker --- + w, h = cfg.value(AppCfg.GEO_BEAM_SZ) + bm=UsrGO.BeamMark([50, 120], [30, 20]) + bm.setTransform(tr) # assign transform + self.vb.addItem(bm) + + #--- testing scan grid --- + vi=UsrGO.Grid((120, -100), (200, 150), (30, 22), 2) + vi.setTransform(tr) # assign transform + self.vb.addItem(vi) + #UsrGO.obj_tree(vb) + + def create_helical_widgets(self): tbox = self._helical_tablebox htab = self._helical_scan_table = HelicalTableWidget() @@ -392,7 +403,7 @@ class Main(QMainWindow, Ui_MainWindow): def add_beam_marker(self): app = QApplication.instance() cfg = app._cfg - w, h = cfg.value(AppCfg.BEAM_SIZE) + w, h = cfg.value(AppCfg.GEO_BEAM_SZ) self._beammark = bm = CstROI.BeamMark([100, 100], (int(w), int(h)), parent=self) tr=QtGui.QTransform() # prepare ImageItem transformation: tr.rotate(30) @@ -797,37 +808,50 @@ class Main(QMainWindow, Ui_MainWindow): # group regions block = QWidget() - block.setAccessibleName(TASK_SETUP_PPM_CALIBRATION) + block.setAccessibleName(TASK_SETUP_GEOMETRY_CALIB) block.setContentsMargins(0, 0, 0, 0) block.setLayout(QVBoxLayout()) grp = QWidget() block.layout().addWidget(grp) block.layout().addStretch() grp.setLayout(QGridLayout()) - tbox.addItem(block, "Pixel/MM Settings") - grp.layout().addWidget(QLabel("feature size (µM)"), 0, 0) - self._ppm_feature_size_spinbox = QDoubleSpinBox() - self._ppm_feature_size_spinbox.setRange(5, 10000) - self._ppm_feature_size_spinbox.setValue(50) - self._ppm_feature_size_spinbox.setDecimals(0) - self._ppm_feature_size_spinbox.setSuffix(" µM") - grp.layout().addWidget(self._ppm_feature_size_spinbox, 0, 1) - self._ppm_calibration = but = QPushButton("Start calibration") + tbox.addItem(block, "geometry calibration") + #grp.layout().addWidget(QLabel("feature size (µM)"), 0, 0) + #self._ppm_feature_size_spinbox = QDoubleSpinBox() + #self._ppm_feature_size_spinbox.setRange(5, 10000) + #self._ppm_feature_size_spinbox.setValue(50) + #self._ppm_feature_size_spinbox.setDecimals(0) + #self._ppm_feature_size_spinbox.setSuffix(" µM") + #grp.layout().addWidget(self._ppm_feature_size_spinbox, 0, 1) + self._btn_pix2pos = but = QPushButton("pix2pos") but.setCheckable(True) - but.clicked.connect(self.update_ppm_fitters) - grp.layout().addWidget(but, 1, 0, 1, 2) + but.clicked.connect(self.update_pix2pos) + grp.layout().addWidget(but, 0, 0) + self._btn_opt_ctr = but = QPushButton("opt_ctr") + but.setCheckable(True) + but.clicked.connect(self.update_opt_ctr) + grp.layout().addWidget(but, 1, 0) + help = QTextBrowser() - grp.layout().addWidget(help, 2, 0, 5, 2) + grp.layout().addWidget(help, 2, 0) help.setHtml( """
-