This commit is contained in:
2024-08-29 16:35:14 +02:00
parent 2e0600128c
commit dfd21755e0
2 changed files with 293 additions and 171 deletions

View File

@@ -9,11 +9,18 @@
""" """
Furka ARES chamber visualization 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")] 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-ARES:MOT_2TRY.RBV # 2thetha angle
SATES30-ARES:MOT_DRY.RBV # detector angle
SATES30-RIXS:MOT_RY.RBV # sliding seal 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 SATES30-ARES:MOT_SRY.RBV # sample rotation
@@ -61,15 +68,17 @@ class ARESdevice():
self._name=name self._name=name
self._paint=p={ self._paint=p={
'ofs':(500, 500), # location of device 'ofs':(500, 500), # location of device
'rArm':150, # radius of chamber (RIXS arm) 'rArm':3*62, # radius of chamber (RIXS arm)
'r2Th':120, # radius 2Theta platfform 'rJFr':3*52, # radius of Jungfrau
'rDet':80, # radius of detector 'r2Th':3*48, # radius 2Theta platfform
'rTrg':10, # radius of target 'rDet':3*23, # radius of detector table
'rTrg':3*20, # radius of target
'szArm':(20, 50), 'szArm':(20, 50),
'aaArm':100, # angle RIXS arm 'aArm':100, # angle RIXS arm
'aa2Th':110, # angle 2thetha 'aJFr':140, # angle detector
'aaDet':120, # angle detector 'a2Th':30, # angle 2thetha
'aaTrg':130, # angle target 'aDet':-20, # angle detector
'aTrg':10, # angle target
'mode':4, #difraction beam paint mode 'mode':4, #difraction beam paint mode
'szG':(200, 5), # size VLS grating 'szG':(200, 5), # size VLS grating
@@ -167,13 +176,16 @@ class ARESdevice():
ofs=p['ofs'] ofs=p['ofs']
rArm=p['rArm'] rArm=p['rArm']
rJFr=p['rJFr']
r2Th=p['r2Th'] r2Th=p['r2Th']
rDet=p['rDet'] rDet=p['rDet']
rTrg=p['rTrg'] rTrg=p['rTrg']
aaArm=p['aaArm']
aa2Th=p['aa2Th'] aArm=p['aArm']
aaDet=p['aaDet'] aJFr=p['aJFr']
aaTrg=p['aaTrg'] a2Th=p['a2Th']
aDet=p['aDet']
aTrg=p['aTrg']
sclTrf=p['sclTrf'] sclTrf=p['sclTrf']
# --- prepare transformations --- # --- prepare transformations ---
# tf0: target not rotated # tf0: target not rotated
@@ -186,13 +198,15 @@ class ARESdevice():
tf0.translate(ofs[0], ofs[1]) tf0.translate(ofs[0], ofs[1])
tf0.scale(sclTrf[1],sclTrf[1]) tf0.scale(sclTrf[1],sclTrf[1])
tfArm=copy.copy(tf0) # center tfArm=copy.copy(tf0) # center
tfArm.rotate(aaArm) tfArm.rotate(-aArm)
tf2Th=copy.copy(tf0) # center tfJFr=copy.copy(tf0)
tf2Th.rotate(aa2Th) tfJFr.rotate(-aJFr)
tf2Th=copy.copy(tf0)
tf2Th.rotate(-a2Th)
tfDet=copy.copy(tf0) tfDet=copy.copy(tf0)
tfDet.rotate(aaDet) tfDet.rotate(-aDet)
tfTrg=copy.copy(tf0) tfTrg=copy.copy(tf0)
tfTrg.rotate(aaTrg) tfTrg.rotate(-aTrg)
#tfd.translate(r2,0).rotate(-cc) #tfd.translate(r2,0).rotate(-cc)
penBk=QPen(QtCore.Qt.black, 0, QtCore.Qt.SolidLine) penBk=QPen(QtCore.Qt.black, 0, QtCore.Qt.SolidLine)
@@ -221,6 +235,7 @@ class ARESdevice():
#circles of rtation #circles of rtation
qp.drawEllipse(-rArm, -rArm, 2*rArm, 2*rArm) # ARES chamber 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(-r2Th, -r2Th, 2*r2Th, 2*r2Th) # 2theta
qp.drawEllipse(-rDet, -rDet, 2*rDet, 2*rDet) # detector qp.drawEllipse(-rDet, -rDet, 2*rDet, 2*rDet) # detector
qp.drawEllipse(-rTrg, -rTrg, 2*rTrg, 2*rTrg) # target qp.drawEllipse(-rTrg, -rTrg, 2*rTrg, 2*rTrg) # target
@@ -237,36 +252,58 @@ class ARESdevice():
#RIXS-arm devices #RIXS-arm devices
qp.setTransform(tfArm) qp.setTransform(tfArm)
qp.setPen(QPen(QtCore.Qt.red, 3, QtCore.Qt.SolidLine)) qp.setPen(QPen(QtCore.Qt.red, 3, QtCore.Qt.SolidLine))
qp.drawLine(0,rArm,0,rArm+10) qp.drawLine(0,-rArm,0,-rArm+10)
qp.setPen(penBk) qp.setPen(penBk)
qp.setBrush(QColor(255,0,0,128)) qp.setBrush(QColor(255,0,0,128))
qp.drawRect(-15, -20+rArm, 5, 50) # foc. mirror 1 qp.drawRect(-20, -50-rArm, 40, 50) # 2th mount sample
qp.drawRect(+10, -20+rArm, 5, 50) # foc. mirror 2 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 #2-theta devices
qp.setTransform(tf2Th) qp.setTransform(tf2Th)
qp.setPen(QPen(QtCore.Qt.green, 3, QtCore.Qt.SolidLine)) qp.setPen(QPen(QtCore.Qt.green, 3, QtCore.Qt.SolidLine))
qp.drawLine(0,r2Th,0,r2Th+10) qp.drawLine(0,-r2Th,0,-r2Th+10)
qp.setPen(penBk) qp.setPen(penBk)
qp.setBrush(QColor(0,255,0,128)) qp.setBrush(QColor(0,255,0,128))
qp.drawRect(-20, -20+r2Th, 15, 15) # 2th mount sample 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 #detector devices
qp.setTransform(tfDet) qp.setTransform(tfDet)
qp.setPen(QPen(QtCore.Qt.blue, 3, QtCore.Qt.SolidLine)) qp.setPen(QPen(QtCore.Qt.blue, 3, QtCore.Qt.SolidLine))
qp.drawLine(0,rDet,0,rDet+10) qp.drawLine(0,-rDet,0,-rDet+10)
qp.setPen(penBk) qp.setPen(penBk)
qp.setBrush(QColor(0,0,255,128)) qp.setBrush(QColor(0,0,255,128))
qp.drawRect(+20, -20+rDet, 10, 15) # detector mount sample 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 #target devices
qp.setTransform(tfTrg) qp.setTransform(tfTrg)
qp.setPen(QPen(QtCore.Qt.cyan, 3, QtCore.Qt.SolidLine)) qp.setPen(QPen(QtCore.Qt.cyan, 3, QtCore.Qt.SolidLine))
qp.drawLine(0,rTrg,0,rTrg+10) qp.drawLine(0,-rTrg,0,-rTrg+10)
qp.setPen(penBk) qp.setPen(penBk)
qp.setBrush(QColor(0,255,255,128)) qp.setBrush(QColor(0,255,255,128))
qp.drawRect(+20, +20+rTrg, 10, 10) # target mount sample 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.setPen(penBk)
#qp.drawRect(-10, -10+rArm, 20, 20) #qp.drawRect(-10, -10+rArm, 20, 20)
@@ -293,156 +330,180 @@ class ARESdevice():
# qp.setTransform(tf);self.plotOrig(qp) # qp.setTransform(tf);self.plotOrig(qp)
class WndVisualize(QWidget): class WndVisualize(QWidget):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.initUI() self.initUI()
self.connectEPICS()
def initUI(self): def initUI(self):
self.setGeometry(560, 100, 1300, 800) self.setGeometry(560, 100, 1300, 800)
self.setWindowTitle('Visualize') self.setWindowTitle('Visualize')
app=QApplication.instance() app=QApplication.instance()
dev=app._dev dev=app._dev
self._wdGrpDraw=w=QGroupBox(dev._name,self) self._wdGrpDraw=w=QGroupBox(dev._name,self)
w.move(10,10) w.move(10,10)
row=0 row=0
lg=QGridLayout(w) lg=QGridLayout(w)
pDev=dev._paint pDev=dev._paint
for key, rng, tk in ( for key, rng, tk in (
('aaArm',(0,360,), 30), # angle ARES sliding seal ('aArm',(0,360,), 30), # angle ARES sliding seal
('aa2Th',(0,360,), 30), # angle 2thetha ('aJFr' ,(0,360,), 30), # angle Jungfrau
('aaDet',(0,360,), 30), # angle detector ('a2Th',(0,360,), 30), # angle 2thetha
('aaTrg',(0,360,), 30), # angle target ('aDet',(0,360,), 30), # angle detector
('sclA', ( -8, 8), 1), ('aTrg',(0,360,), 30), # angle target
('sclD', (-8, 8), 1),): ('sclA', ( -8, 8), 1),
('sclD', (-8, 8), 1),):
wLb=QLabel(key) wLb=QLabel(key)
wSl=QSlider(QtCore.Qt.Horizontal,objectName=key) wSl=QSlider(QtCore.Qt.Horizontal,objectName=key)
wSl.setFixedWidth(200);wSl.setMinimum(rng[0]);wSl.setMaximum(rng[1]) 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 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'): if key.startswith('scl'):
wGrp=self._wdGrpDraw
if key[-1]=='A': if key[-1]=='A':
p['sclTrf']=(2**(val/2),p['sclTrf'][1]) v=pDev['sclTrf'][0]
else: else:
p['sclTrf']=(p['sclTrf'][0],2**(val/2)) v=pDev['sclTrf'][1]
print(p['sclTrf']) v=int(round(np.log2(v)*2))
dev.setGeometry(dev._geo)
else: else:
p[key]=val v=pDev[key]
g=dev._geo wSl.setValue(v)
if key in ('r1','r2'): wSl.setTickPosition(QSlider.TicksBelow);wSl.setTickInterval(tk)
sclD=p['sclTrf'][1] wSl.valueChanged.connect(lambda val,key=key: self.sldChanged(key,val))
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): lg.addWidget(wLb, row, 0)
try: lg.addWidget(wSl, row, 1);row+=1
del self._mouseDrag self.show()
except AttributeError:
pass
def mousePressEvent(self, a0): def connectEPICS(self):
app=QApplication.instance() self._pv=pv=set()
mousePos=a0.pos() for rec_name in (
print(a0.type) 'SATES30-RIXS:MOT_RY',
if a0.type()!=QtGui.QMouseEvent.MouseButtonPress: 'SATES30-ARES:MOT_JFRY',
return '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 wGrp=self._wdGrpDraw
#if wGrp.underMouse(): #draging sliders? if key[-1]=='A':
if wGrp.geometry().contains(mousePos): p['sclTrf']=(2**(val/2),p['sclTrf'][1])
self._mouseDrag={'obj':wGrp, 'start':mousePos} else:
return p['sclTrf']=(p['sclTrf'][0],2**(val/2))
dev=app._dev print(p['sclTrf'])
if dev.containsPoint(mousePos): dev.setGeometry(dev._geo)
self._devSel=dev else:
wGrp=self._wdGrpDraw p[key]=val
wGrp.setTitle(dev._name) g=dev._geo
devP=dev._paint if key in ('r1','r2'):
for wSl in wGrp.findChildren(QSlider): sclD=p['sclTrf'][1]
#_log.info(wSl) g[key]=val/sclD
key=wSl.objectName() elif key in ('aa', 'bb'):
if key.startswith('scl'): sclA=p['sclTrf'][0]
if key[-1]=='A': g[key]=90-val/sclA
v=devP['sclTrf'][0] else:
else: g[key]=val
v=devP['sclTrf'][1] self.update()
v=int(round(np.log2(v)*2))
else:
v=devP[key]
wSl.setValue(v)
self._mouseDrag={'obj':dev,'start':(mousePos,dev._paint['ofs'])} def mouseReleaseEvent(self, a0):
try: try:
_log.info(f'{self._mouseDrag}') del self._mouseDrag
except AttributeError: except AttributeError:
_log.info(f'no object to drag') pass
def mousePressEvent(self, a0):
def mouseMoveEvent(self, a0): app=QApplication.instance()
try: mousePos=a0.pos()
md=self._mouseDrag print(a0.type)
except AttributeError: if a0.type()!=QtGui.QMouseEvent.MouseButtonPress:
return return
obj=md['obj'] wGrp=self._wdGrpDraw
s=md['start'] #if wGrp.underMouse(): #draging sliders?
if obj==self._wdGrpDraw: if wGrp.geometry().contains(mousePos):
p=a0.pos() self._mouseDrag={'obj':wGrp, 'start':mousePos}
md['start']=p return
p=obj.geometry().topLeft()+p-s dev=app._dev
obj.move(p) if dev.containsPoint(mousePos):
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 self._devSel=dev
devP=dev._paint
wGrp=self._wdGrpDraw wGrp=self._wdGrpDraw
wGrp.setTitle(dev._name) wGrp.setTitle(dev._name)
devP=dev._paint
for wSl in wGrp.findChildren(QSlider): for wSl in wGrp.findChildren(QSlider):
# _log.info(wSl) #_log.info(wSl)
key=wSl.objectName() key=wSl.objectName()
if key.startswith('scl'): if key.startswith('scl'):
if key[-1]=='A': if key[-1]=='A':
@@ -452,14 +513,67 @@ class WndVisualize(QWidget):
v=int(round(np.log2(v)*2)) v=int(round(np.log2(v)*2))
else: else:
v=devP[key] v=devP[key]
wSl.blockSignals(True)
wSl.setValue(v) wSl.setValue(v)
wSl.blockSignals(False)
self.update()
def OnEvent(self,*args,**kwargs): self._mouseDrag={'obj':dev,'start':(mousePos,dev._paint['ofs'])}
#test event try:
print(f'OnEvent: {args} ,{kwargs}') _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__': if __name__ == '__main__':

View File

@@ -179,7 +179,15 @@ class WndMainRIXS(QWidget):
with open(fn, 'rb') as fh: with open(fn, 'rb') as fh:
app=QApplication.instance() app=QApplication.instance()
app._rawData=pickle.load(fh) app._rawData=pickle.load(fh)
_log.info(app._rawData.keys()) #_log.info(app._rawData.keys())
#run=app._rawData[226]
#_log.info(run.keys())
#raw2D=run['2D']
#_log.info(f'{type(raw2D)}:{len(raw2D)} {raw2D}')
#line=raw2D[0]
#_log.info(f'{type(line)}: {line}')
#_log.info(raw2D)
#np.shape(raw2D)
w=self._cbRaw w=self._cbRaw
for i, tx in enumerate(tuple(app._rawData.keys())): for i, tx in enumerate(tuple(app._rawData.keys())):
w.insertItem(i, str(tx)) w.insertItem(i, str(tx))