From 7db60ba6ee2689387d7b66c5e45e1ad874d37071 Mon Sep 17 00:00:00 2001 From: Thierry Zamofing Date: Tue, 16 Aug 2022 15:24:49 +0200 Subject: [PATCH] wip --- pyqtUsrObj.py | 176 +++++++++++++++++++++++++++++++++++++++++--------- swissmx.py | 88 ++++++++++++++++++------- 2 files changed, 211 insertions(+), 53 deletions(-) diff --git a/pyqtUsrObj.py b/pyqtUsrObj.py index bd78dc2..2730b0f 100644 --- a/pyqtUsrObj.py +++ b/pyqtUsrObj.py @@ -17,7 +17,7 @@ import pyqtgraph as pg from pyqtgraph.Qt import QtCore, QtGui import numpy as np from PyQt5.QtGui import QPolygon,QPolygonF -from PyQt5.QtCore import QPointF,QLineF +from PyQt5.QtCore import Qt,QPointF,QLineF def obj_tree(obj,p=''): obj_info(obj,p) @@ -28,7 +28,12 @@ def obj_info(obj,p=''): print(f"{p}obj_info:{obj}") try: pos=obj.pos() - print(f"{p}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: + sz=obj.size() + print(f"{p}size:({sz.x():.6g},{sz.y():.6g})") # in coordinate value on the scene (no change by zooming) except AttributeError: pass try: @@ -53,11 +58,18 @@ def obj_info(obj,p=''): except AttributeError: pass -class BeamMark(pg.ROI): +class Marker(pg.ROI): """A crosshair ROI whose position is at the center of the crosshairs. By default, it is scalable, rotatable and translatable.""" - def __init__(self, pos=None, size=None, **kargs): + def __init__(self, pos, size, mode, **kargs): pg.ROI.__init__(self, pos, size, **kargs) + self._mode=mode + #widget.signal.connect(slot_function) + #self.sigRegionChangeFinished.connect(self.OnRgnChanged) + + #def OnRgnChanged(self, event): + # print(event) + # obj_info(self) def paint(self, p, *args): #pg.ROI.paint(self, p, *args) @@ -65,24 +77,66 @@ class BeamMark(pg.ROI): p.setRenderHint(QtGui.QPainter.Antialiasing) p.setPen(self.currentPen) p.translate(r.left(), r.top()) - p.scale(r.width(), r.height()) - p.drawEllipse(0, 0, 1, 1) - p.drawRect(0, 0, 1, 1) - p.setPen(pg.mkPen(width=3, color=[200, 100, 100])) - p.drawLine(pg.Point(.5, 0), pg.Point(.5, 1)) - p.drawLine(pg.Point( 0,.5), pg.Point( 1,.5)) - #w, h = self.getState()["size"] - #v1, v2 = -(h * 0.8) / 2, (h * 0.8) / 2 - #h1, h2 = -(w * 0.8) / 2, (w * 0.8) / 2 - #p.setRenderHint(QtGui.QPainter.Antialiasing) - #p.setPen(pg.mkPen(width=3, color=[200, 100, 100])) - #p.drawLine(pg.Point(0, v1), pg.Point(0, v2)) - #p.drawLine(pg.Point(h1, 0), pg.Point(h2, 0)) - #p.setPen(self.currentPen) - ##p.setPen(pg.mkPen(width=3, color=[200, 200, 100])) - #p.drawRect(-w / 2, -h / 2, w, h) - ## p.drawText(-w, -h, '{:.0f}x{:.0f}'.format(*self._size)) + #p.scale(r.width(), r.height()) # -> values x,y 0 to 1 + #f=p.font(); + #f.setPixelSize(50) + #p.setFont(f) + # p.drawText(0, 0, '{:.0f}x{:.0f}'.format(*tuple(self.size()))) + #p.drawText(0, 0, 'Thierry') + p.scale(.01*r.width(), .01*r.height()) # -> values x,y 0 to 100 + m=self._mode + if m==0: + p.drawEllipse(0, 0, 100, 100) + p.drawRect(0, 0, 100, 100) + p.setPen(pg.mkPen(width=3, color=[200, 100, 100])) + p.drawLine(pg.Point(50, 0), pg.Point(50, 100)) + p.drawLine(pg.Point( 0,50), pg.Point(100, 50)) + tr=p.transform() + tr.setMatrix(tr.m11(), tr.m12(), tr.m13(), tr.m21(), -tr.m22(), tr.m23(), tr.m31(), tr.m32(), tr.m33()) + p.setTransform(tr) + f=p.font() + f.setPixelSize(10) + p.setFont(f) + p.drawText(24, -80, 'beam marker') + ctr=tuple(self.pos()+self.size()/2) + sz=tuple(self.size()) + p.drawText(5, -55, '{:.1f}x{:.1f}'.format(*sz)) + #p.drawText(5, -35, '{:.1f}'.format(ctr[0])) + p.drawText(5, -45,42,30,Qt.AlignRight, '{:.1f}'.format(ctr[0])) + p.drawText(55, -35, '{:.1f}'.format(ctr[1])) + + elif m==1: + p.drawEllipse(20,20,60,60) + p.drawRect(0, 0, 100, 100) + p.setPen(pg.mkPen(width=2, color=[10, 255, 0])) + p.drawLine(pg.Point(50, 0), pg.Point( 50,100)) + p.drawLine(pg.Point( 0,50), pg.Point(100, 50)) + tr=p.transform() + tr.setMatrix(tr.m11(), tr.m12(), tr.m13(), tr.m21(), -tr.m22(), tr.m23(), tr.m31(), tr.m32(), tr.m33()) + p.setTransform(tr) + f=p.font(); + f.setPixelSize(10) + p.setFont(f) + px=tuple(self.pos()+self.size()/2) + p.drawText(5, -90, 'optical') + p.drawText(55,-90, 'center') + #p.drawText(5, -10, '{:.1f}/{:.1f}'.format(*px)) + p.drawText(5, -10, '{:.1f}'.format(px[0])) + p.drawText(55, -10, '{:.1f}'.format(px[1])) + #p.drawText(0, 0, 'Thierry') + + # w, h = self.getState()["size"] + # v1, v2 = -(h * 0.8) / 2, (h * 0.8) / 2 + # h1, h2 = -(w * 0.8) / 2, (w * 0.8) / 2 + # p.setRenderHint(QtGui.QPainter.Antialiasing) + # p.setPen(pg.mkPen(width=3, color=[200, 100, 100])) + # p.drawLine(pg.Point(0, v1), pg.Point(0, v2)) + # p.drawLine(pg.Point(h1, 0), pg.Point(h2, 0)) + # p.setPen(self.currentPen) + # #p.setPen(pg.mkPen(width=3, color=[200, 200, 100])) + # p.drawRect(-w / 2, -h / 2, w, h) + # # p.drawText(-w, -h, '{:.0f}x{:.0f}'.format(*self._size)) class Grid(pg.ROI): '''a grid''' @@ -182,20 +236,43 @@ class Path(pg.ROI): fid=self._fiducial for i in range(fid.shape[0]): - x,y=fid[i,:];print(x,y) + x,y=fid[i,:]#;print(x,y) lh=QLineF(x-5*rx,y,x+5*rx,y) lv=QLineF(x, y-5*ry, x, y+5*ry) p.drawLines(lh,lv) +class TxtROI(pg.ROI): + def __init__(self, pos, size, **kargs): + pg.ROI.__init__(self, pos, size, **kargs) + def paint(self, p, *args): + #pg.ROI.paint(self, p, *args) + r=QtCore.QRectF(0, 0, self.state['size'][0], self.state['size'][1]).normalized() + + p.setRenderHint(QtGui.QPainter.Antialiasing) + p.setPen(self.currentPen) + #p.translate(r.left(), r.top()) + #p.scale(r.width(), r.height()) + #p.drawRect(0, 0, 1, 1) + p.drawRect(r) + tr=p.worldTransform() + obj_info(tr) + tr.setMatrix(tr.m11(),tr.m12(),tr.m13(),tr.m21(),-tr.m22(),tr.m23(),tr.m31(),tr.m32(),tr.m33()) + p.setWorldTransform(tr) + obj_info(tr) + obj_info(p.transform()) + obj_info(p.worldTransform()) + f=p.font(); + f.setPixelSize(15) + p.setFont(f) + p.drawText(0, 5, 'Thierry') ## Start Qt event loop unless running in interactive mode or using pyside. if __name__=='__main__': import sys import argparse - #(h, t)=os.path.split(sys.argv[0]);cmd='\n '+(t if len(h)>20 else sys.argv[0])+' ' #exampleCmd=('', '-m0xf -v0') epilog=__doc__ #+'\nExamples:'+''.join(map(lambda s:cmd+s, exampleCmd))+'\n' @@ -234,13 +311,36 @@ if __name__=='__main__': def mouse_click_event(event): + #event.pos(): return Point(self.currentItem.mapFromScene(self._scenePos)) pos=event.pos() scn=event.scenePos() # there is a small black border, that makes the difference - img=viImg.mapFromScene(scn) - roi=viUsrRoi.mapFromScene(scn) - print(f'mouse:{pt2str(pos)} {pt2str(scn)} img:{pt2str(img)} roi:{pt2str(roi)}') + print(f'mouse-> scene pos:{pt2str(scn)} currentItem pos:{pt2str(pos)}') + #img=viImg.mapFromScene(scn) + #roi=viUsrRoi.mapFromScene(scn) + #print(f'mouse-> img:{pt2str(img)} roi:{pt2str(roi)}') #childTree(vb) - obj_info(viUsrRoi) + #obj_info(viImg) + m=int(event.modifiers()) + o=event.currentItem + if m&Qt.ShiftModifier: + o.setPos((100,200)) + o.setSize((200,100)) + o.rotate(10) + pass + elif m&Qt.ControlModifier: + tr=o.transform() + obj_info(tr) + #tr.setMatrix(tr.m11(),tr.m12(),tr.m13()+100,tr.m21(),tr.m22(),tr.m23(),tr.m31(),tr.m32(),tr.m33()) + #tr.setMatrix(tr.m11(),tr.m12(),tr.m13(),tr.m21(),tr.m22(),tr.m23(),tr.m31(),tr.m32()+20,tr.m33()) + tr.setMatrix(tr.m11(),tr.m12(),tr.m13(),tr.m21(),-tr.m22(),tr.m23(),tr.m31(),tr.m32(),tr.m33()) + obj_info(tr) + o.setTransform(tr) + elif m&Qt.AltModifier: + pass + else: + obj_info(o) + print(o.state) + ## Create image to display arr=np.ones((100, 100), dtype=float) @@ -264,17 +364,23 @@ if __name__=='__main__': w=pg.GraphicsLayoutWidget(show=True, size=(1000, 800), border=True) w.setWindowTitle('pyqtgraph example: ROI Examples') - vb=w.addViewBox(row=1, col=0, lockAspect=True) - g=pg.GridItem() + vb=w.addViewBox(row=1, col=0, lockAspect=True,invertY=False) + try: + g=pg.GridItem(pen=(0, 255, 0), textPen=(0, 255, 0)) # green grid and labels + except: + g=pg.GridItem() vb.addItem(g) viImg=pg.ImageItem(arr, border='y') vb.addItem(viImg) # Custom ROI for selecting an image region - viRoi=pg.ROI([20, -50], [60, 40]) + #viRoi=pg.ROI([20, -50], [60, 40]) + viRoi=TxtROI([20, -50], [60, 40]) vb.addItem(viRoi) - viUsrRoi=BeamMark([50, 120], [30, 20]) + viUsrRoi=Marker([50, 120], [30, 20],mode=0) vb.addItem(viUsrRoi) + obj=Marker([250, 220], [30, 20],mode=1) + vb.addItem(obj) vi=Grid( (120,-100), (200,150), (30,20),2) #vi=Grid( (50,10), (200,150), (6,4)) vb.addItem(vi) #vi= visual item @@ -283,11 +389,19 @@ if __name__=='__main__': fiducial=np.array(((18, 7), (25, 16), (70, 20))) path=gen_swissmx_points(ofs=(10, 5), width=200) vi=Path((120,100),path,fiducial,fidScl) + #tr=QtGui.QTransform() # prepare ImageItem transformation: + #tr.setMatrix(1, 0, 0, + # 0, 1, 0, + # 10, 10, 1) + #vi.setTransform(tr) # assign transform vb.addItem(vi) childTree(vb) w.scene().sigMouseClicked.connect(mouse_click_event) + #viImg.sigImageChanged + #print(vb.pos()) + #vb.setPos(50,50) if (sys.flags.interactive!=1) or not hasattr(QtCore, 'PYQT_VERSION'): QtGui.QApplication.instance().exec_() diff --git a/swissmx.py b/swissmx.py index 5a3ff3e..6399100 100755 --- a/swissmx.py +++ b/swissmx.py @@ -317,14 +317,16 @@ class Main(QMainWindow, Ui_MainWindow): self.glw.scene().sigMouseClicked.connect(self.mouse_click_event) #--- viewbox --- - self.vb=vb=self.glw.addViewBox(invertY=False)#),border='r')#,enableMenu=False) + #self.vb=vb=self.glw.addViewBox(invertY=False,border='r',enableMenu=False) + 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: - #opt_ctr=app._geometry._opt_ctr + opt_ctr=app._geometry._opt_ctr + + #--- image --- + self._goImg=img=pg.ImageItem() tr.setMatrix(-1, 0, 0, 0,-1, 0, 0, 0, 1) @@ -334,19 +336,24 @@ class Main(QMainWindow, Ui_MainWindow): #--- grid --- try: - grid=pg.GridItem(pen=(0,255,0),textPen=(0,255,0)) #green grid and labels + self._goGrid=grid=pg.GridItem(pen=(0,255,0),textPen=(0,255,0)) #green grid and labels except: - grid=pg.GridItem() + self._goGrid=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_sz=np.array(tuple(map(int, cfg.value(AppCfg.GEO_BEAM_SZ)))) + self._goBeamMarker=bm=UsrGO.Marker(-opt_ctr-[50, 120],bm_sz,mode=0) bm.setTransform(tr) # assign transform self.vb.addItem(bm) + #--- opctical center --- + self._goOptCtr=obj=UsrGO.Marker(-opt_ctr, [50, 50],mode=1) + bm.setTransform(tr) # assign transform + self.vb.addItem(obj) + #--- testing scan grid --- vi=UsrGO.Grid((120, -100), (200, 150), (30, 22), 2) vi.setTransform(tr) # assign transform @@ -426,7 +433,7 @@ class Main(QMainWindow, Ui_MainWindow): sim['imgIdx']=(idx+1)%imgSeq.shape[0] # _log.info('simulated idx:{}'.format(idx)) pic=imgSeq[idx] - self.img.setImage(pic) + self._goImg.setImage(pic) delay=500 # ms -> 2fps QtCore.QTimer.singleShot(delay, self.new_frame_sim_cb) @@ -443,7 +450,7 @@ class Main(QMainWindow, Ui_MainWindow): if pic.dtype==np.int16: pic.dtype=np.uint16 camera.epics_cam.set_fiducial(pic, 255) - self.img.setImage(pic) + self._goImg.setImage(pic) def init_settings_tracker(self): app=QApplication.instance() @@ -1093,7 +1100,7 @@ class Main(QMainWindow, Ui_MainWindow): app = QApplication.instance() self._mouse_pos = pos task = self.active_task() - xy = self.img.mapFromScene(pos) + xy = self._goImg.mapFromScene(pos) z = app._zoom.get() #_log.debug('mouse_pos:{} scene_pos:{} zoom:{}'.format(pos,xy,z)) #TODO: implement mouse handling @@ -1142,7 +1149,7 @@ class Main(QMainWindow, Ui_MainWindow): raw=app._raw_pix2pos[zoom] except KeyError as e: raw=app._raw_pix2pos[zoom]=list() - imgPos=self.img.mapFromScene(event.scenePos()) + imgPos=self._goImg.mapFromScene(event.scenePos()) fx=fast_x.get_position(); fy=fast_y.get_position() x=imgPos.x();y=imgPos.y() @@ -1153,7 +1160,7 @@ class Main(QMainWindow, Ui_MainWindow): raw=app._raw_opt_ctr[zoom] except KeyError as e: raw=app._raw_opt_ctr[zoom]=list() - imgPos=self.img.mapFromScene(event.scenePos()) + imgPos=self._goImg.mapFromScene(event.scenePos()) x=imgPos.x();y=imgPos.y() _log.debug('append calib: zoom:{} cam_pix_x_y:{}/{}'.format(zoom, x, y)) raw.append(( x, y)) @@ -1161,24 +1168,61 @@ class Main(QMainWindow, Ui_MainWindow): QMessageBox.warning(self, "calibration", "no calibration started yet.\nPress 'pix2pos' or 'opt_ctr' button first") def mouse_click_event(self, event): - _log.debug("{}".format(event)) - _log.debug("screen pos {}".format(event.screenPos())) #pixel position on the whole screen - _log.debug("scene pos {}".format(event.scenePos())) #pixel position on the scene (including black frame) + #_log.debug("{}".format(event)) + #_log.debug("screen pos {}".format(event.screenPos())) #pixel position on the whole screen + #_log.debug("scene pos {}".format(event.scenePos())) #pixel position on the scene (including black frame) #_log.debug(" pos {}".format(event.pos())) #pixel position of the ckicked object mapped to its coordinates - p=event.scenePos() - _log.debug(f"vb pos {self.vb.mapFromScene(p)}") #pixel position on the scene (including black frame) - for o in self.vb.childGroup.childItems(): - _log.debug(f"{type(o)} pos {o.mapFromScene(p)}") #pixel position on the scene (including black frame) + #p=event.scenePos() + #_log.debug(f"vb pos {self.vb.mapFromScene(p)}") #pixel position on the scene (including black frame) + #for o in self.vb.childGroup.childItems(): + # _log.debug(f"{type(o)} pos {o.mapFromScene(p)}") #pixel position on the scene (including black frame) task = self.active_task() if task==TASK_SETUP_GEOMETRY_CALIB: self.mouse_click_event_geometry_calib(event) return + #Ctrl-left : move to position + #Ctrl-left : move to position + + #dblclick = event.double() + app=QApplication.instance() + mod=event.modifiers() + btn=event.button() + if btn==Qt.LeftButton: + if mod&Qt.ShiftModifier: + pass + elif mod&Qt.ControlModifier: + pos=event.scenePos() + _log.debug(f'move to position :scene pos {pos}') + geo=app._geometry + geo.interp_zoom(1) + bm=self._goBeamMarker + p1=self._goImg.mapFromScene(pos) + p2=bm.pos()+bm.size()/2 + px=p2+p1 + um=geo.pix2pos(px) + _log.debug(f'{px} -> {um}') + pass + elif mod&Qt.AltModifier: + pass + else: + pass + elif btn==Qt.RightButton: + if mod&Qt.ShiftModifier: + pass + elif mod&Qt.ControlModifier: + _log.debug('object tree') + UsrGO.obj_tree(self.vb) + pass + elif mod&Qt.AltModifier: + pass + else: + pass + return return assert(event.currentItem==self.vb) - UsrGO.obj_tree(self.vb) #UsrGO.obj_info(self.img) event.pos()# return Point(self.currentItem.mapFromScene(self._scenePos)) @@ -1203,7 +1247,7 @@ class Main(QMainWindow, Ui_MainWindow): ctrl = Qt.ControlModifier & event.modifiers() alt = Qt.AltModifier & event.modifiers() - xy = self.img.mapFromScene(pos) + xy = self._goImg.mapFromScene(pos) x, y = xy.x(), xy.y() bx, by = self.get_beam_mark_on_camera_xy() a = np.asarray([x, y])