601 lines
18 KiB
Python
Executable File
601 lines
18 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# *-----------------------------------------------------------------------*
|
|
# | |
|
|
# | Copyright (c) 2024 by Paul Scherrer Institute (http://www.psi.ch) |
|
|
# | |
|
|
# | Author Thierry Zamofing (thierry.zamofing@psi.ch) |
|
|
# *-----------------------------------------------------------------------*
|
|
|
|
"""
|
|
Furka ARES chamber visualization
|
|
|
|
For simulated motor IOC:
|
|
/home/zamofing_t/Documents/prj/SwissFEL/test_ioc/MotorSim/iocBoot/ARESvis/ARESvis.cmd
|
|
For motor ui:
|
|
caQtDM ~/Documents/prj/SwissFEL/test_ioc/MotorSim/iocBoot/ARESvis/ARESvis.ui&
|
|
|
|
|
|
self.pv_angles = [epics.PV("SATES30-ARES:MOT_SRY.RBV"), epics.PV("SATES30-ARES:MOT_DRY.RBV"), epics.PV("SATES30-ARES:MOT_2TRY.RBV")]
|
|
|
|
SATES30-RIXS:MOT_RY.RBV # sliding seal
|
|
SATES30-ARES:MOT_JFRY.RBV # jungfrau detector angle:
|
|
SATES30-ARES:MOT_2TRY.RBV # 2thetha angle: foc.mirror Diode2 Diode3
|
|
SATES30-ARES:MOT_DRY.RBV # detector angle: Diode1 Mirror
|
|
SATES30-ARES:MOT_SRY.RBV # sample rotation
|
|
|
|
|
|
bitmask for simulation:
|
|
0x01: EPICS motors
|
|
0x02:
|
|
0x04:
|
|
0x08:
|
|
0x10:
|
|
0x20:
|
|
0x40:
|
|
0x80:
|
|
|
|
"""
|
|
|
|
|
|
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QSlider, QLineEdit,\
|
|
QCheckBox, QHBoxLayout, QVBoxLayout, QGroupBox, QGridLayout, QComboBox
|
|
from PyQt5.QtGui import QPainter, QColor, QPen, QBrush, QPolygon, QTransform
|
|
from PyQt5.QtCore import QPoint, QPointF, Qt
|
|
|
|
from pyqtgraph.Qt import QtCore, QtGui
|
|
import PyQt5.QtGui as QtGui
|
|
import PyQt5.QtCore as QtCore
|
|
import PyQt5.QtWidgets as QtW
|
|
from PyQt5.uic import loadUiType
|
|
import numpy as np
|
|
|
|
import sys, logging, copy
|
|
import epics
|
|
|
|
_log=logging.getLogger(__name__)
|
|
|
|
class ARESdevice():
|
|
_lutDifrBeamPaint=( # (number of difr beam,draw mode,alpha,width)
|
|
(4, 2, 190, 0),
|
|
(4, 1, 200, 0),
|
|
(32, 1, 120, 0),
|
|
(8, 1, 196, 0),
|
|
(32, 0, 120, 3),
|
|
(32, 2, 255, 0),
|
|
)
|
|
|
|
def __init__(self,name,**kwargs):
|
|
self._name=name
|
|
self._paint=p={
|
|
'ofs':(500, 500), # location of device
|
|
'rArm':3*62, # radius of chamber (RIXS arm)
|
|
'rJFr':3*52, # radius of Jungfrau
|
|
'r2Th':3*48, # radius 2Theta platfform
|
|
'rDet':3*23, # radius of detector table
|
|
'rTrg':3*20, # radius of target
|
|
'szArm':(20, 50),
|
|
'aArm':100, # angle RIXS arm
|
|
'aJFr':140, # angle detector
|
|
'a2Th':30, # angle 2thetha
|
|
'aDet':-20, # angle detector
|
|
'aTrg':10, # angle target
|
|
|
|
'mode':4, #difraction beam paint mode
|
|
'szG':(200, 5), # size VLS grating
|
|
'szD':(150, 5), # size detector
|
|
'sclTrf':(2**(6/2), 2**(0/2)), # scaling transfformation [angle, distance]
|
|
}
|
|
# 2thetha angle SATES30-ARES:MOT_2TRY
|
|
# detector angle SATES30-ARES:MOT_DRY
|
|
# sliding seal SATES30-RIXS:MOT_RY
|
|
|
|
p.update(kwargs)
|
|
self._geo=g={
|
|
'r1':2000, # distance probe grating
|
|
'r2':3500, # distance grating detector
|
|
'aa':88, # grating angle
|
|
'bb':87, # reflection angle
|
|
'cc':22, # detector angle
|
|
}
|
|
self.setGeometry(g)
|
|
|
|
|
|
def setGeometry(self,geo):
|
|
self._geo=geo
|
|
p=self._paint
|
|
sclA,sclD=p['sclTrf']
|
|
p.update({
|
|
'r1':int(geo['r1']*sclD),
|
|
'r2':int(geo['r2']*sclD),
|
|
'aa':int((90-geo['aa'])*sclA),
|
|
'bb':int((90-geo['bb'])*sclA),
|
|
'cc':int(geo['cc']),
|
|
})
|
|
|
|
def geometry2motor(self):
|
|
# returns raw motor positions
|
|
# offset detector plane to deflected beam: 34deg
|
|
|
|
geo=self._geo
|
|
r1,r2,aa,bb,cc=geo['r1'],geo['r2'],geo['aa'],geo['bb'],geo['cc']
|
|
mt=gtz=gty1=gty2=grx=gtx=dtz=dty1=dty2=drx=None
|
|
degArm=90-aa+90-bb
|
|
radArm=np.deg2rad(degArm)
|
|
gtz=r1
|
|
grx=90-aa
|
|
dtz=np.cos(radArm)*r2
|
|
dty1=dty2=np.sin(radArm)*r2
|
|
drx=90-aa+90-bb+cc-34
|
|
dd=cc-34 # angle of bellow to detector
|
|
|
|
geo.update({
|
|
'mt':mt,
|
|
'gtz':gtz,
|
|
'gty1':gty1,
|
|
'gty2': gty2,
|
|
'grx':grx,
|
|
'gtx':gtx,
|
|
'dtz':dtz,
|
|
'dty1':dty1,
|
|
'dty2':dty2,
|
|
'drx':drx})
|
|
|
|
if degArm>10:
|
|
raise(ValueError('angle arm > 10°'))
|
|
elif degArm<1:
|
|
raise(ValueError('angle arm < 1°'))
|
|
elif abs(dd)>15:
|
|
raise(ValueError('angle bellow to detector > 15°'))
|
|
|
|
def containsPoint(self,point):
|
|
try:
|
|
pg=self._polygon
|
|
except AttributeError:
|
|
return False
|
|
return pg.containsPoint(point,Qt.OddEvenFill)
|
|
|
|
@staticmethod
|
|
def plotOrig(qp):
|
|
penR=QPen(QtCore.Qt.red, 2, QtCore.Qt.SolidLine)
|
|
penG=QPen(QtCore.Qt.green, 2, QtCore.Qt.SolidLine)
|
|
pOrig=qp.pen()
|
|
qp.setPen(penR)
|
|
qp.drawLine(-20, 0, 20, 0)
|
|
qp.drawLine( 20, 0, 16, 2)
|
|
qp.setPen(penG)
|
|
qp.drawLine(0, -20, 0, 20)
|
|
qp.drawLine(0, 20, 2, 16)
|
|
qp.setPen(pOrig)
|
|
|
|
def paint(self,qp):
|
|
# qp QPainter to paint on
|
|
# ofs caanter to draw
|
|
# scl scaling for x and y translation of coordinate systems
|
|
# paintMode: mode how to paint the diffraction beam
|
|
p=self._paint
|
|
ofs=p['ofs']
|
|
|
|
rArm=p['rArm']
|
|
rJFr=p['rJFr']
|
|
r2Th=p['r2Th']
|
|
rDet=p['rDet']
|
|
rTrg=p['rTrg']
|
|
|
|
aArm=p['aArm']
|
|
aJFr=p['aJFr']
|
|
a2Th=p['a2Th']
|
|
aDet=p['aDet']
|
|
aTrg=p['aTrg']
|
|
sclTrf=p['sclTrf']
|
|
# --- prepare transformations ---
|
|
# tf0: target not rotated
|
|
# tfArm: target center rotated angle aaArm
|
|
# tf2Th: target center rotated angle tf2Th
|
|
# tfDet: target center rotated angle aaDet
|
|
# tfTrg: target center rotated angle aaTrg
|
|
|
|
tf0=QTransform()
|
|
tf0.translate(ofs[0], ofs[1])
|
|
tf0.scale(sclTrf[1],sclTrf[1])
|
|
tfArm=copy.copy(tf0) # center
|
|
tfArm.rotate(-aArm)
|
|
tfJFr=copy.copy(tf0)
|
|
tfJFr.rotate(-aJFr)
|
|
tf2Th=copy.copy(tf0)
|
|
tf2Th.rotate(-a2Th)
|
|
tfDet=copy.copy(tf0)
|
|
tfDet.rotate(-aDet)
|
|
tfTrg=copy.copy(tf0)
|
|
tfTrg.rotate(-aTrg)
|
|
#tfd.translate(r2,0).rotate(-cc)
|
|
|
|
penBk=QPen(QtCore.Qt.black, 0, QtCore.Qt.SolidLine)
|
|
penWt=QPen(QtCore.Qt.white, 1, QtCore.Qt.SolidLine)
|
|
penYl=QPen(QtCore.Qt.yellow, 1, QtCore.Qt.SolidLine)
|
|
penBl=QPen(QtCore.Qt.blue, 1, QtCore.Qt.SolidLine)
|
|
penRd=QPen(QtCore.Qt.red, 1, QtCore.Qt.SolidLine)
|
|
|
|
# --- visualize ---
|
|
#qp.setRenderHints(QPainter.HighQualityAntialiasing)
|
|
|
|
# setup and plot dragable region
|
|
#pl=[QPoint(*tf0.map (-rArm , -rArm)),QPoint(*tf0.map (-rArm , +rArm+50)),QPoint(*tf0.map (+rArm+50+aaArm, +rArm+50+aa2Th)),QPoint(*tf0.map(+rArm+50+aaDet , -rArm-50)),]
|
|
self._polygon=QPolygon([
|
|
QPoint(*tf0.map(-rArm ,-rArm)),
|
|
QPoint(*tf0.map(-rArm ,+rArm+100)),
|
|
QPoint(*tf0.map(+rArm,+rArm+100)),
|
|
QPoint(*tf0.map(+rArm,-rArm)),])
|
|
qp.setBrush(QColor(0, 0, 0,64))
|
|
qp.drawPolygon(self._polygon)
|
|
|
|
# plot beam path
|
|
qp.setTransform(tf0)
|
|
qp.setPen(penBk)
|
|
qp.setBrush(QColor(128, 128, 128, 128)) #r,g,b,a
|
|
|
|
#circles of rtation
|
|
qp.drawEllipse(-rArm, -rArm, 2*rArm, 2*rArm) # ARES chamber
|
|
qp.drawEllipse(-rJFr, -rJFr, 2*rJFr, 2*rJFr) # Jungfrau
|
|
qp.drawEllipse(-r2Th, -r2Th, 2*r2Th, 2*r2Th) # 2theta
|
|
qp.drawEllipse(-rDet, -rDet, 2*rDet, 2*rDet) # detector
|
|
qp.drawEllipse(-rTrg, -rTrg, 2*rTrg, 2*rTrg) # target
|
|
|
|
#beam arrow
|
|
qp.setPen(QPen(QtCore.Qt.black, 3, QtCore.Qt.SolidLine))
|
|
qp.drawLine(0,+rArm+100,0,rArm)
|
|
qp.drawPolygon(QPolygon([QPoint(0,rArm),QPoint(-5,rArm+20),QPoint(+5,rArm+20),]))
|
|
|
|
#self.plotOrig(qp)
|
|
#qp.setPen(penRd)
|
|
#qp.drawRect(-10, -10+rArm, 20, 20)
|
|
|
|
#RIXS-arm devices
|
|
qp.setTransform(tfArm)
|
|
qp.setPen(QPen(QtCore.Qt.red, 3, QtCore.Qt.SolidLine))
|
|
qp.drawLine(0,-rArm,0,-rArm+10)
|
|
qp.setPen(penBk)
|
|
qp.setBrush(QColor(255,0,0,128))
|
|
qp.drawRect(-20, -50-rArm, 40, 50) # 2th mount sample
|
|
qp.drawRect(-100, -200-rArm, 200, 150) # 2th mount sample
|
|
|
|
#Jungfrau devices
|
|
qp.setTransform(tfJFr)
|
|
qp.setPen(QPen(QtCore.Qt.magenta, 3, QtCore.Qt.SolidLine))
|
|
qp.drawLine(0,-rJFr,0,-rJFr+10)
|
|
qp.setPen(penBk)
|
|
qp.setBrush(QColor(255,0,255,128))
|
|
qp.drawRect(-50, -20-rJFr, 100, 15) # detector mount sample
|
|
|
|
#2-theta devices
|
|
qp.setTransform(tf2Th)
|
|
qp.setPen(QPen(QtCore.Qt.green, 3, QtCore.Qt.SolidLine))
|
|
qp.drawLine(0,-r2Th,0,-r2Th+10)
|
|
qp.setPen(penBk)
|
|
qp.setBrush(QColor(0,255,0,128))
|
|
qp.drawRect(-15, -30-r2Th, 5, 3*29) # foc. mirror 1
|
|
qp.drawRect(+10, -30-r2Th, 5, 3*29) # foc. mirror 2
|
|
qp.rotate(20)
|
|
qp.drawRect(-10, -r2Th, 20, 20) # diode2
|
|
qp.setTransform(tf2Th);qp.rotate(120)
|
|
qp.drawRect(-10, -r2Th, 20, 20) # diode3
|
|
|
|
#detector devices
|
|
qp.setTransform(tfDet)
|
|
qp.setPen(QPen(QtCore.Qt.blue, 3, QtCore.Qt.SolidLine))
|
|
qp.drawLine(0,-rDet,0,-rDet+10)
|
|
qp.setPen(penBk)
|
|
qp.setBrush(QColor(0,0,255,128))
|
|
qp.drawRect(-10, -rDet, 20, 10) # diode1
|
|
qp.rotate(30);qp.translate(0,-rDet);qp.rotate(45)
|
|
qp.drawRect(-10, 0, 30, 5) # mirror1
|
|
|
|
|
|
#target devices
|
|
qp.setTransform(tfTrg)
|
|
qp.setPen(QPen(QtCore.Qt.cyan, 3, QtCore.Qt.SolidLine))
|
|
qp.drawLine(0,-rTrg,0,-rTrg+10)
|
|
qp.setPen(penBk)
|
|
qp.setBrush(QColor(0,255,255,128))
|
|
qp.drawRect(-30, -20, 60, 20) # target mount sample
|
|
|
|
#parabola mirror
|
|
qp.setTransform(tf0)
|
|
qp.setPen(penBk)
|
|
qp.setBrush(QColor(80,80,80,128))
|
|
qp.drawPolygon(QPolygon([QPoint(-15,30),QPoint(-15,60),QPoint(15,60),]))
|
|
|
|
|
|
#qp.setPen(penBk)
|
|
#qp.drawRect(-10, -10+rArm, 20, 20)
|
|
#self.plotOrig(qp)
|
|
#qp.setTransform(tf2Th)
|
|
#qp.setPen(penYl)
|
|
#qp.drawRect(-10, -10+r2Th, 20, 20)
|
|
#self.plotOrig(qp)
|
|
#qp.setTransform(tfDet)
|
|
#qp.setPen(penBl)
|
|
#qp.drawRect(-10, -10+r2Th+20, 20, 20)
|
|
#qp.setTransform(tfTrg)
|
|
#qp.setPen(penBl)
|
|
#qp.drawRect(-10, -10+r2Th+20, 20, 20)
|
|
#self.plotOrig(qp)
|
|
#qp.setCompositionMode(QtGui.QPainter.CompositionMode_Lighten)
|
|
#qp.setCompositionMode(QtGui.QPainter.CompositionMode_SourceOver)
|
|
#mouse move polygon
|
|
#qp.setTransform(QTransform())
|
|
#qp.setPen(penRd)
|
|
#qp.drawPolygon(self._polygon)
|
|
#origin crosses
|
|
#for tf in (tf0,tfa,tfab,tfc):#,tfg,tfs):#,tfc,tfs):
|
|
# qp.setTransform(tf);self.plotOrig(qp)
|
|
|
|
class WndVisualize(QWidget):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.initUI()
|
|
self.connectEPICS()
|
|
|
|
def initUI(self):
|
|
self.setGeometry(560, 100, 1300, 800)
|
|
self.setWindowTitle('Visualize')
|
|
app=QApplication.instance()
|
|
dev=app._dev
|
|
self._wdGrpDraw=w=QGroupBox(dev._name,self)
|
|
w.move(10,10)
|
|
row=0
|
|
lg=QGridLayout(w)
|
|
pDev=dev._paint
|
|
for key, rng, tk in (
|
|
('aArm',(0,360,), 30), # angle ARES sliding seal
|
|
('aJFr' ,(0,360,), 30), # angle Jungfrau
|
|
('a2Th',(0,360,), 30), # angle 2thetha
|
|
('aDet',(0,360,), 30), # angle detector
|
|
('aTrg',(0,360,), 30), # angle target
|
|
('sclA', ( -8, 8), 1),
|
|
('sclD', (-8, 8), 1),):
|
|
|
|
wLb=QLabel(key)
|
|
wSl=QSlider(QtCore.Qt.Horizontal,objectName=key)
|
|
wSl.setFixedWidth(200);wSl.setMinimum(rng[0]);wSl.setMaximum(rng[1])
|
|
if key.startswith('scl'):
|
|
if key[-1]=='A':
|
|
v=pDev['sclTrf'][0]
|
|
else:
|
|
v=pDev['sclTrf'][1]
|
|
v=int(round(np.log2(v)*2))
|
|
else:
|
|
v=pDev[key]
|
|
wSl.setValue(v)
|
|
wSl.setTickPosition(QSlider.TicksBelow);wSl.setTickInterval(tk)
|
|
wSl.valueChanged.connect(lambda val,key=key: self.sldChanged(key,val))
|
|
|
|
lg.addWidget(wLb, row, 0)
|
|
lg.addWidget(wSl, row, 1);row+=1
|
|
self.show()
|
|
|
|
def connectEPICS(self):
|
|
self._pv=pv=set()
|
|
for rec_name in (
|
|
'SATES30-RIXS:MOT_RY',
|
|
'SATES30-ARES:MOT_JFRY',
|
|
'SATES30-ARES:MOT_2TRY',
|
|
'SATES30-ARES:MOT_DRY',
|
|
'SATES30-ARES:MOT_SRY',):
|
|
|
|
m=epics.Motor(rec_name)
|
|
pv.add(m)
|
|
#_log.debug(m.get_position()) # this is the VAL field
|
|
#_log.debug(m.PV('RBV').get()) # this is the RBV field
|
|
#_log.debug(m.get('RBV')) # this is the RBV field
|
|
#m.add_callback('RBV', self.update_label)
|
|
#m.set_callback('RBV', self.emit_signals, {'source_field': 'RBV'})
|
|
#/home/zamofing_t/.local/lib/python3.8/site-packages/epics/motor.py
|
|
m.add_callback('RBV', self.OnChangedRBV)
|
|
#print(pv)
|
|
# def update_label(self, **kwargs):
|
|
# _log.info(kwargs)
|
|
|
|
# def emit_signals(self, **kw):
|
|
# _log.info(kw)
|
|
|
|
#def OnChangedRBV(self, **kw):
|
|
def OnChangedRBV(self, pvname, value, **kw):
|
|
#_log.info(kw)
|
|
#{
|
|
# 'pvname': 'SATES30-ARES:MOT_2TRY.RBV',
|
|
# 'value': 102.507,
|
|
# 'char_value': '102.5070',
|
|
# 'status': 0,
|
|
# 'ftype': 20,
|
|
# 'chid': 26100744,
|
|
# 'host': 'localhost:5064',
|
|
# 'count': 1,
|
|
# 'access': 'read-only',
|
|
# 'write_access': False,
|
|
# 'read_access': True,
|
|
# 'severity': 0,
|
|
# 'timestamp': 1724915455.46745,
|
|
# 'posixseconds': 1724915455.0,
|
|
# 'nanoseconds': 467450100,
|
|
# 'precision': 4,
|
|
# 'units': 'deg',
|
|
# 'enum_strs': None,
|
|
# 'upper_disp_limit': 0.0,
|
|
# 'lower_disp_limit': 0.0,
|
|
# 'upper_alarm_limit': nan,
|
|
# 'lower_alarm_limit': nan,
|
|
# 'lower_warning_limit': nan,
|
|
# 'upper_warning_limit': nan,
|
|
# 'upper_ctrl_limit': 0.0,
|
|
# 'lower_ctrl_limit': 0.0,
|
|
# 'nelm': 1,
|
|
# 'type': 'time_double',
|
|
# 'typefull': 'time_double',
|
|
# 'cb_info': (1, <PV 'SATES30-ARES:MOT_2TRY.RBV', count=1, type=time_double, access=read-only>)
|
|
#}
|
|
#_log.info(f"{kw['pvname']}:{kw['value']}")
|
|
_log.info(f"{pvname}:{value}")
|
|
if pvname=='SATES30-RIXS:MOT_RY.RBV':
|
|
self.sldChanged('aArm',value)
|
|
elif pvname=='SATES30-ARES:MOT_JFRY.RBV':
|
|
self.sldChanged('aJFr',value)
|
|
elif pvname=='SATES30-ARES:MOT_2TRY.RBV':
|
|
self.sldChanged('a2Th',value)
|
|
elif pvname=='SATES30-ARES:MOT_DRY.RBV':
|
|
self.sldChanged('aDet',value)
|
|
elif pvname=='SATES30-ARES:MOT_SRY.RBV':
|
|
self.sldChanged('aTrg',value)
|
|
else:
|
|
_log.warning(f"can't handle PV: {pvname}:{value}")
|
|
|
|
def destroy(self, destroyWindow, destroySubWindows): #overloaded function
|
|
_log.info('destroy')
|
|
|
|
def closeEvent(self, event): #overloaded function
|
|
_log.info('closeEvent')
|
|
|
|
def sldChanged(self,key,val,*args,**kwargs):
|
|
app=QApplication.instance()
|
|
dev=app._dev
|
|
p=dev._paint
|
|
if key.startswith('scl'):
|
|
wGrp=self._wdGrpDraw
|
|
if key[-1]=='A':
|
|
p['sclTrf']=(2**(val/2),p['sclTrf'][1])
|
|
else:
|
|
p['sclTrf']=(p['sclTrf'][0],2**(val/2))
|
|
print(p['sclTrf'])
|
|
dev.setGeometry(dev._geo)
|
|
else:
|
|
p[key]=val
|
|
g=dev._geo
|
|
if key in ('r1','r2'):
|
|
sclD=p['sclTrf'][1]
|
|
g[key]=val/sclD
|
|
elif key in ('aa', 'bb'):
|
|
sclA=p['sclTrf'][0]
|
|
g[key]=90-val/sclA
|
|
else:
|
|
g[key]=val
|
|
self.update()
|
|
|
|
def mouseReleaseEvent(self, a0):
|
|
try:
|
|
del self._mouseDrag
|
|
except AttributeError:
|
|
pass
|
|
|
|
def mousePressEvent(self, a0):
|
|
app=QApplication.instance()
|
|
mousePos=a0.pos()
|
|
print(a0.type)
|
|
if a0.type()!=QtGui.QMouseEvent.MouseButtonPress:
|
|
return
|
|
wGrp=self._wdGrpDraw
|
|
#if wGrp.underMouse(): #draging sliders?
|
|
if wGrp.geometry().contains(mousePos):
|
|
self._mouseDrag={'obj':wGrp, 'start':mousePos}
|
|
return
|
|
dev=app._dev
|
|
if dev.containsPoint(mousePos):
|
|
self._devSel=dev
|
|
wGrp=self._wdGrpDraw
|
|
wGrp.setTitle(dev._name)
|
|
devP=dev._paint
|
|
for wSl in wGrp.findChildren(QSlider):
|
|
#_log.info(wSl)
|
|
key=wSl.objectName()
|
|
if key.startswith('scl'):
|
|
if key[-1]=='A':
|
|
v=devP['sclTrf'][0]
|
|
else:
|
|
v=devP['sclTrf'][1]
|
|
v=int(round(np.log2(v)*2))
|
|
else:
|
|
v=devP[key]
|
|
wSl.setValue(v)
|
|
|
|
self._mouseDrag={'obj':dev,'start':(mousePos,dev._paint['ofs'])}
|
|
try:
|
|
_log.info(f'{self._mouseDrag}')
|
|
except AttributeError:
|
|
_log.info(f'no object to drag')
|
|
|
|
|
|
def mouseMoveEvent(self, a0):
|
|
try:
|
|
md=self._mouseDrag
|
|
except AttributeError:
|
|
return
|
|
obj=md['obj']
|
|
s=md['start']
|
|
if obj==self._wdGrpDraw:
|
|
p=a0.pos()
|
|
md['start']=p
|
|
p=obj.geometry().topLeft()+p-s
|
|
obj.move(p)
|
|
return
|
|
p=a0.pos()
|
|
ofs=QPoint(*s[1])+p-s[0]
|
|
_log.info(f'{p} {ofs}')
|
|
obj._paint['ofs']=(ofs.x(),ofs.y())
|
|
self.update()
|
|
|
|
def paintEvent(self, e):
|
|
qp = QPainter()
|
|
qp.begin(self)
|
|
qp.setRenderHints(QPainter.HighQualityAntialiasing)
|
|
app=QApplication.instance()
|
|
dev=app._dev
|
|
app._dev.paint(qp)
|
|
qp.end()
|
|
|
|
def updateDevice(self, dev):
|
|
self._devSel=dev
|
|
devP=dev._paint
|
|
wGrp=self._wdGrpDraw
|
|
wGrp.setTitle(dev._name)
|
|
for wSl in wGrp.findChildren(QSlider):
|
|
# _log.info(wSl)
|
|
key=wSl.objectName()
|
|
if key.startswith('scl'):
|
|
if key[-1]=='A':
|
|
v=devP['sclTrf'][0]
|
|
else:
|
|
v=devP['sclTrf'][1]
|
|
v=int(round(np.log2(v)*2))
|
|
else:
|
|
v=devP[key]
|
|
wSl.blockSignals(True)
|
|
wSl.setValue(v)
|
|
wSl.blockSignals(False)
|
|
self.update()
|
|
|
|
def OnEvent(self,*args,**kwargs):
|
|
#test event
|
|
print(f'OnEvent: {args} ,{kwargs}')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
import argparse
|
|
logging.basicConfig(level=logging.DEBUG, format='%(levelname)s:%(module)s:%(lineno)d:%(funcName)s:%(message)s ')
|
|
|
|
|
|
def main():
|
|
epilog=__doc__ # +'\nExamples:'+''.join(map(lambda s:cmd+s, exampleCmd))+'\n'
|
|
parser=argparse.ArgumentParser(epilog=epilog, formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
parser.add_argument('--mode', '-m', type=lambda x:int(x, 0), help='mode (see bitmasks) default=0x%(default)x', default=1)
|
|
parser.add_argument("--sim", "-s", type=lambda x: int(x,0), help="simulate devices (see bitmasks) default=0x%(default)x", default=0x01)
|
|
args=parser.parse_args()
|
|
_log.info('Arguments:{}'.format(args.__dict__))
|
|
|
|
app=QApplication(sys.argv)
|
|
app._args=args
|
|
app._dev=dev=ARESdevice('Furka-ARES')
|
|
|
|
if args.mode&0x01:
|
|
app._wndVisualize=wnd=WndVisualize()
|
|
wnd.show()
|
|
sys.exit(app.exec_())
|
|
|
|
main() |