Files
EsfRixsApps/scratch/graphExample.py
2024-08-28 08:45:18 +02:00

759 lines
25 KiB
Python
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python
# *-----------------------------------------------------------------------*
# | |
# | Copyright (c) 2022 by Paul Scherrer Institute (http://www.psi.ch) |
# | |
# | Author Thierry Zamofing (thierry.zamofing@psi.ch) |
# *-----------------------------------------------------------------------*
from PyQt5.QtWidgets import QWidget, QLabel, QPushButton, QApplication
from PyQt5.QtGui import QPainter, QColor, QBrush
from pyqtgraph.Qt import QtCore, QtGui
import numpy as np
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 geometry
import sys
import logging
import epics
_log=logging.getLogger(__name__)
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)
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:
for k, v in (('Viewport', obj.viewport()), ('Window', obj.window())):
print(
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"{p}scenePos:({scnPos.x():.6g},{scnPos.y():.6g})") # in pixel on the scene (changes by zooming)
except AttributeError:
pass
try:
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
class RIXSgirder(QWidget):
_lutColor={0:(255,0,0),1:(0,255,0),2:(255,255,0)}
def __init__(self):
super().__init__()
self._param={'ctr':(200, 300), # location of big chamber
'rCmb':80, # radius of chamber
'rTrg':10, # radius of target
'szSeal': (20,50),
'szArm': (80,350),
'aaSeal':70, # RIXS sliding angle
'aaArm':70, # RIXS arm angle
'airPads':0, # air pads (off=0 on=1 undef=2)
'defComp':0, # deformation compensation (off=0 on=1 undef=2)
}
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 850, 800)
self.setWindowTitle('RIXS girder')
#label = QLabel('Python', self)
#label.move(50,50)
#b1 = QPushButton("Button1",self)
#b1.move(400,150)
self._wdGrpDraw=w=QtGui.QGroupBox("Drawing",self)
w.move(10,10)
l=QtGui.QVBoxLayout(w)
sld={}
for key,rng,tk in (('aaSeal',(0,180),5),('aaArm',(0,180),5),('airPads',(0,2),1),('defComp',(0,2),1),):
sl=QtGui.QSlider(QtCore.Qt.Horizontal,objectName=key)
sl.setFixedWidth(200);sl.setMinimum(rng[0]);sl.setMaximum(rng[1])
sl.setValue(self._param[key])
sl.setTickPosition(QtGui.QSlider.TicksBelow);sl.setTickInterval(tk)
l.addWidget(sl)
sl.valueChanged.connect(lambda val,key=key: self.sldChanged(key,val))
sld[key]=sl
self.show()
def sldChanged(self,key,val,*args,**kwargs):
p=self._param
#print(key,val)
if key=='aaArm':
p['aaSeal']=v=p['aaSeal']-p['aaArm']+val
wSl=self._wdGrpDraw.findChild(QtGui.QSlider, 'aaSeal')
wSl.blockSignals(True)
wSl.setValue(int(v))
wSl.blockSignals(False)
sl=QtGui.QSlider(QtCore.Qt.Horizontal,objectName=key)
p[key]=val
self.update()
def paintEvent(self, e):
p=self._param
ctr=p['ctr']
aaSeal=p['aaSeal']
aaArm=p['aaArm']
rCmb=p['rCmb']
rTrg=p['rTrg']
xa,ya=p['szArm']
xs,ys=p['szSeal']
ap=p['airPads']
dc=p['defComp']
qp = QPainter()
qp.begin(self)
qp.translate(ctr[0],ctr[1])
tf0=qp.transform()
qp.setPen(QtGui.QPen(QtCore.Qt.black, 2, QtCore.Qt.SolidLine))
qp.setBrush(QColor(155, 155, 155, 128))
br1=qp.brush()
qp.drawEllipse(-rCmb, -rCmb, 2*rCmb, 2*rCmb) # big chamber
qp.drawEllipse(-rTrg, -rTrg, 2*rTrg, 2*rTrg) # target
qp.drawLine(0,-rCmb-50,0,-rTrg) #beam
qp.rotate(-aaSeal)
qp.translate(0,rCmb)
tf1=qp.transform()
xs2=xs//2
xa2=xa//2
ya2=ya//2
d=int(abs(aaSeal-aaArm)*20)
r=min(155+d,255)
gb=max(155-d,0)
qp.setBrush(QColor(r, gb, gb, 255))
qp.drawRect(-xs2, 0, xs, ys) # seal bellow
qp.setBrush(br1)
qp.setTransform(tf0)
qp.rotate(-aaArm)
qp.translate(0,rCmb+ys)
tf2=qp.transform()
qp.drawRect(-xa2, 0, xa, ya) # girder
#qp.drawEllipse(-ya2, 100+150, 20, 20) #pusher left
#qp.drawEllipse( ya2-r, 100+150, 20, 20) #pusher right
#air pad
r,g,b=RIXSgirder._lutColor[ap]
rd=13
r3=int(rd*np.sqrt(3))
qp.setBrush(QColor(r, g, b, 255))
qp.drawEllipse(-xa2-rd, ya-4*rd, 2*rd, 2*rd) #left
qp.drawEllipse(-xa2-rd+r3,ya-3*rd, 2*rd, 2*rd) #left
qp.drawEllipse(-xa2-rd+r3,ya-5*rd, 2*rd, 2*rd) #left
qp.drawEllipse( xa2-rd, ya-4*rd, 2*rd, 2*rd) #right
qp.drawEllipse( xa2-rd-r3,ya-3*rd, 2*rd, 2*rd) #right
qp.drawEllipse( xa2-rd-r3,ya-5*rd, 2*rd, 2*rd) #right
qp.drawEllipse( -rd, 3*rd, 2*rd, 2*rd) #grating
qp.drawEllipse( 0, 3*rd-r3, 2*rd, 2*rd) #grating
qp.drawEllipse( -2*rd, 3*rd-r3, 2*rd, 2*rd) #grating
qp.setBrush(br1)
#deformation compensation
r,g,b=RIXSgirder._lutColor[dc]
rd=14
qp.setBrush(QColor(r, g, b, 255))
qp.drawEllipse(-xa2, ya2, 2*rd, 2*rd) #air pad left
qp.drawEllipse( xa2-2*rd, ya2, 2*rd, 2*rd) #air pad right
#qp.drawEllipse( -rd, rd, 2*rd, 2*rd) #air pad grating
qp.setBrush(br1)
qp.end()
#Ui_MainWindow, QMainWindow = loadUiType("graphEx1.ui")
#class RIXSgrating(QMainWindow, Ui_MainWindow):
# def __init__(self, ):
# super(RIXSgrating, self).__init__()
# self.setupUi(self)
class RIXSgrating(QWidget):
def __init__(self):
super().__init__()
self._param={'ctr':(500,500), # location of vlsg
'r1':314,#distance probe grating
'r2':447,#distance grating detector
'aa':18, #grating angle
'bb':18, #reflection angle
'cc':58, #detector angle
'szG':(200,5), #size VLS grating
'szD':(150,5), #size detector
'difrBeamPaint':4, # mode to plot the difracted beam
}
self._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),
)
# n=4;mode=2;alpha=190
# n=4;mode=1;alpha=200
# n=32;mode=1;alpha=120
# n=8;mode=1;alpha=196
n=32;
mode=0;
alpha=120;
width=3
# n=32;mode=2;alpha=255
self.initUI()
def initUI(self):
#p=self.palette()
#p.setColor(self.backgroundRole(), QtCore.Qt.black)
#self.setPalette(p)
self.setGeometry(300, 300, 1050, 700)
self.setWindowTitle('RIXS grating')
#w.move(400,100)
#w.setFixedSize(200,200)
self._wdGrpEnergy=w=QtGui.QGroupBox("Energy",self)
w.move(10,10)
#w.setFixedSize(200,42+32*2)
lv=QtGui.QVBoxLayout(w)
w=QtGui.QWidget() #QGroupBox("E2",self)
lv.addWidget(w)
lg=QtGui.QGridLayout(w)
i=0;t='Energy'
w=QLabel(t); lg.addWidget(w, i,0)
w=QtGui.QLineEdit(t,objectName=t); lg.addWidget(w, i,1)
w.returnPressed.connect(lambda w=w:self.OnEnergyChanged(w))
i+=1;t='Grating'
w=QLabel(t); lg.addWidget(w, i,0)
w=QtGui.QComboBox(objectName=t); lg.addWidget(w, i,1)
for i,t in enumerate(geometry.VLSgrating.vlsgTypes):
w.insertItem(i,t)
w.currentIndexChanged.connect(lambda val,w=w:self.OnEnergyChanged(w,val))
key,rng,tk,pos=('energy',(200,1500),50,60)
w=QtGui.QSlider(QtCore.Qt.Horizontal,objectName=key)
w.setFixedWidth(200);w.setMinimum(rng[0]);w.setMaximum(rng[1])
#w.setValue(self._param[key])
w.setTickPosition(QtGui.QSlider.TicksBelow);w.setTickInterval(tk)
lv.addWidget(w)
#sl.valueChanged.connect(lambda val,key=key: self.sldChanged(key,val))
w.valueChanged.connect(lambda val,w=w:self.OnEnergyChanged(w,val))
self._wdGrpGeometry=w=QtGui.QGroupBox("Geometry",self)
w.move(10,160)
#w.setFixedSize(200,42+32*4)
l=QtGui.QGridLayout(w)
lut={'aa':'\u03B1', 'bb':'\u03B2', 'cc':'\u03B3'}
for i,t in enumerate(('r1','r2','aa','bb','cc',)):
tl=lut.get(t,t)
w=QLabel(tl)
l.addWidget(w, i,0)
w=QtGui.QLineEdit(t,objectName=t)
l.addWidget(w, i,1)
self._wdGrpRaw=w=QtGui.QGroupBox("Motors",self)
w.move(250,10)
#w.setFixedSize(200,42+32*4)
l=QtGui.QGridLayout(w)
motors=(
('MT', 'Mask translation'),
('GTZ', 'Grating translation along Z-axis (along beam)'),
('GTY1', 'Grating translation along Y-axis (height) Wedge leveller 1'),
('GTY2', 'Grating translation along Y-axis (height) Wedge leveller 2'),
('GRX', 'Grating rotation around X-axis'),
('GTX', 'Grating translation along X-axis'),
('DTZ', 'Detector Translation along Z-axis'),
('DTY1', 'Detector Translation along Y-axis'),
('DTY2', 'Detector Translation along Y-axis'),
('DRX', 'Detector Rotation around X-axis (ɣ) '),
)
for i,m in enumerate(motors):
tl,inf=m
t=tl.lower()
w=QLabel(tl)
l.addWidget(w, i,0)
w=QtGui.QLineEdit(t,objectName=t)
w.setToolTip(inf)
l.addWidget(w, i,1)
w=QtGui.QPushButton('move all motors')
w.clicked.connect(self.btnMoveAllMotors)
l.addWidget(w, i+1, 1)
self._wdGrpDraw=w=QtGui.QGroupBox("Drawing",self)
w.move(470,10)
l=QtGui.QVBoxLayout(w)
sld={}
for key,rng,tk in (('r1',(50,800),50),('r2',(50,800),50),('aa',(0,90),5),('bb',(0,90),5),('cc',(0,180),5),
('difrBeamPaint',(0,len(self._lutDifrBeamPaint)-1),1),):
sl=QtGui.QSlider(QtCore.Qt.Horizontal,objectName=key)
sl.setFixedWidth(200);sl.setMinimum(rng[0]);sl.setMaximum(rng[1])
sl.setValue(self._param[key])
sl.setTickPosition(QtGui.QSlider.TicksBelow);sl.setTickInterval(tk)
l.addWidget(sl)
sl.valueChanged.connect(lambda val,key=key: self.sldChanged(key,val))
sld[key]=sl
self.show()
def OnEnergyChanged(self,w,*args):
#_log.debug(f'OnEnergyChanged: {w} {args}')
app=QApplication.instance()
#wCb=self._wdGrpEnergy.findChild(QtGui.QComboBox, 'Grating')
wLe=self._wdGrpEnergy.findChild(QtGui.QLineEdit, 'Energy')
wSl=self._wdGrpEnergy.findChild(QtGui.QSlider, 'energy')
t=type(w)
if t==QtGui.QLineEdit:
try:
e=float(w.text())
except ValueError as e:
return
wSl.blockSignals(True)
wSl.setValue(int(e))
wSl.blockSignals(False)
elif t==QtGui.QComboBox:
app=QApplication.instance()
vlsg=app._vlsg
vlsg.setup(w.currentText())
try:
e=float(wLe.text())
except ValueError as e:
return
elif t==QtGui.QSlider:
e=args[0]
wLe.setText(f'{e:.4g}')
else:
raise(TypeError(f'wrong type: {t}'))
self.setEnergy(e)
def OnEvent(self,*args,**kwargs):
#test event
print(f'OnEvent: {args} ,{kwargs}')
def setEnergy(self,val):
app=QApplication.instance()
p=self._param
wGrating=self._wdGrpEnergy.findChild(QtGui.QComboBox, 'Grating')
wEnergy=self._wdGrpEnergy.findChild(QtGui.QLineEdit, 'Energy')
wEnergy.setText(f'{val:.4g}')
vlsg=app._vlsg
vlsg.setup(wGrating.currentText())
self._vlsg_geo=geo=vlsg.energy2geometry(val)
p['r1']=geo['r1']/8
p['r2']=geo['r2']/8
p['aa']=(90-geo['aa'])*5
p['bb']=(90-geo['bb'])*5
p['cc']=geo['cc']
grp=self._wdGrpDraw
for k,v in p.items():
w=grp.findChild(QtGui.QSlider, k)
if w is not None:
w.blockSignals(True)
w.setValue(int(v))
w.blockSignals(False)
grp=self._wdGrpGeometry
for k,v in geo.items():
w=grp.findChild(QtGui.QLineEdit, k)
w.setText(f'{v:.6g}')
self._vlsg_raw=raw,err=vlsg.geometry2raw(**geo)
if err is not None:
_log.error(str(err))
self._vlsg_raw=raw
grp=self._wdGrpRaw
for k,v in raw.items():
w=grp.findChild(QtGui.QLineEdit, k)
if v is None:
w.setText('(null)')
else:
w.setText(f'{v:.6g}')
self.update()
def sldChanged(self,key,val,*args,**kwargs):
#print(key,val)
try:
self._vlsg_geo
except AttributeError:
pass
p=self._param
p[key]=val
self.update()
def btnMoveAllMotors(self):
p=self._param
wGr=self._wdGrpEnergy.findChild(QtGui.QComboBox, 'Grating')
wEn=self._wdGrpEnergy.findChild(QtGui.QLineEdit, 'Energy')
try:
mot=self._vlsg_raw
except AttributeError:
_log.error('no current energy set')
return
dlg=DlgMoveMotors()
dlg.initUI('prefix',mot)
#dlg.initUI('prefix',self._vlsg_raw)
if dlg.exec():
print("Success!")
else:
print("Cancel!")
#print(f'grating:{wGr.currentText()} energy:{wEn.text()}')
#print(f'geometry:{self._vlsg_geo}')
#print(f'raw motors:{self._vlsg_raw}')
def paintEvent(self, e):
p=self._param
r1=int(p['r1'])
r2=int(p['r2'])
aa=p['aa']
bb=p['bb']
cc=p['cc']
szG=p['szG']
szD=p['szD']
ctr=p['ctr']
qp = QPainter()
qp.begin(self)
qp.setRenderHints(QPainter.HighQualityAntialiasing)
#plot black background
w=int(max(szG[0],szD[0])/2)
ctr=(max(ctr[0],w+r1),max(w+r2*np.sin((aa+bb)*np.pi/180),ctr[1]))
qp.translate(ctr[0],ctr[1])
qp.setBrush(QColor(0, 0, 0))
qp.drawRect(-r1-w, -w, r1+w, 2*w)
#qp.drawEllipse(-r1-w, -w, 2*w, 2*w)
qp.drawEllipse(-w, -w, 2*w, 2*w)
qp.rotate(180-aa-bb)
qp.drawRect(-r2-w, -w, r2+w, 2*w)
#qp.drawEllipse(-r2-w, -w, 2*w, 2*w)
#plot beam path
qp.setTransform(QtGui.QTransform())
qp.translate(ctr[0],ctr[1])
qp.setCompositionMode(QtGui.QPainter.CompositionMode_Lighten)
tf0=qp.transform()
qp.setPen(QtGui.QPen(QtCore.Qt.white, 1, QtCore.Qt.SolidLine))
qp.setBrush(QColor(255, 80, 0, 128))
qp.drawEllipse(-r1-20, -10, 20, 20) # target
qp.drawLine(-r1,0,0,0) #central beam1
qp.rotate(-aa)
tf1=qp.transform()
qp.drawRect(int(-szG[0]/2), 0, szG[0], szG[1]) # grating
qp.rotate(-bb)
tf2=qp.transform()
qp.drawLine(0,0,int(r2+szD[0]/2),0) #central beam2
qp.translate(r2,0)
qp.rotate(-cc)
tf3=qp.transform()
qp.drawRect(int(-szD[0]/2),0 , szD[0], szD[1]) # detector
#beam target to vlsg
qp.setTransform(QtGui.QTransform())
p0=QtCore.QPointF(*tf0.map(-r1-10, 10))
p1=QtCore.QPointF(*tf1.map(-szG[0]/2, 0))
qp.drawLine(p0,p1)
p0=QtCore.QPointF(*tf0.map(-r1-10, -10))
p1=QtCore.QPointF(*tf1.map(szG[0]/2, 0))
qp.drawLine(p0,p1)
# beam vlsg to detector
#n=32;mode=0;alpha=120;width=3
n,mode,alpha,width=self._lutDifrBeamPaint[p['difrBeamPaint']]
scl=256/n
p0=QtCore.QPointF(*tf1.map(-szG[0]/2, 0))
p1=QtCore.QPointF(*tf1.map(szG[0]/2, 0))
if mode==0:
pen=QtGui.QPen(QtCore.Qt.black, width, QtCore.Qt.SolidLine)
col=QtGui.QColor()
for i in range(n):
p2=QtCore.QPointF(*tf3.map(szD[0]/2-szD[0]*i/(n-1),0))
col.setHsv(int(i*scl),255,255,alpha)
pen.setColor(col)
qp.setPen(pen)
qp.drawLine(p0,p2)
qp.drawLine(p1,p2)
if mode==1:
col=QtGui.QColor()
qp.setPen(QtGui.QPen(QtCore.Qt.black, 0, QtCore.Qt.SolidLine))
for i in range(n):
p2=QtCore.QPointF(*tf3.map(szD[0]/2-szD[0]*i/(n-1), 0))
col.setHsv(int(i*scl), 255, 255, alpha)
qp.setBrush(col)
qp.drawPolygon(p0, p1, p2)
if mode==2:
col=QtGui.QColor()
qp.setPen(QtGui.QPen(QtCore.Qt.black, 0, QtCore.Qt.SolidLine))
for i in range(n):
p2=QtCore.QPointF(*tf3.map(szD[0]/2-szD[0]*(i+1)/n, 0))
p3=QtCore.QPointF(*tf3.map(szD[0]/2-szD[0]*i/n, 0))
col.setHsv(int(i*scl), 255, 255, alpha)
qp.setBrush(col)
qp.drawPolygon(p0, p1, p2, p3)
qp.setCompositionMode(QtGui.QPainter.CompositionMode_SourceOver)
#draw central beam (if needed)
if mode!=0:
qp.setTransform(tf0)
qp.setPen(QtGui.QPen(QtGui.QColor(0x757780), 2, QtCore.Qt.SolidLine))
qp.drawLine(-r1,0,0,0) #central beam1
qp.setTransform(tf2)
qp.drawLine(0,0,int(r2+szD[0]/2),0) #central beam2
#draw dimensions
try:
d=self._vlsg_geo
except AttributeError:
vr1=r1; vr2=r2; vaa=aa; vbb=bb; vcc=cc
else:
vr1=d['r1']
vr2=d['r2']
vaa=90-d['aa']
vbb=90-d['bb']
vcc=d['cc']
qp.setTransform(QtGui.QTransform())
pen=QtGui.QPen(QtCore.Qt.red, 1, QtCore.Qt.SolidLine)
penTxt=QtGui.QPen(QtCore.Qt.yellow, 1, QtCore.Qt.SolidLine)
qp.setPen(pen)
p0=QtCore.QPointF(*tf0.map(-r1-10, +10))
p1=QtCore.QPointF(*tf0.map(-r1-10, 0+w))
qp.drawLine(p0,p1)
p2=QtCore.QPointF(*tf0.map(0, 0))
p3=QtCore.QPointF(*tf0.map(0, 0+w))
qp.drawLine(p2,p3)
p4=(p1+p3)/2 #text pos
p5=QtCore.QPointF(*tf2.map(0, 0+w))
qp.drawLine(p2,p5)
p6=QtCore.QPointF(*tf2.map(r2, 0))
p7=QtCore.QPointF(*tf2.map(r2, 0+w))
qp.drawLine(p6,p7)
p8=(p5+p7)/2 #text pos
p9=QtCore.QPointF(*tf1.map(0, -w))
qp.drawLine(p2,p9)
s=50
qp.drawArc(int(p2.x())-s, int(p2.y())-s, 2*s, 2*s, 180*16, int(aa*16))
s1=s*np.cos(aa*np.pi/180); s2=s*np.sin(aa*np.pi/180)
qp.drawArc(int(p2.x())-s, int(p2.y())-s, 2*s, 2*s, int(aa*16), int(bb*16))
qp.drawArc(int(p6.x())-s, int(p6.y())-s, 2*s, 2*s, int((aa+bb)*16), int(cc*16))
p10=QtCore.QPointF(*tf2.map(r2+20, 0)) #text pos
qp.setPen(penTxt)
qp.drawText(p4+QtCore.QPointF(-40,-10),f'R1={vr1:.5g}mm')
#qp.setTransform(QtGui.QTransform())
qp.translate(p8); qp.rotate(-aa-bb)
qp.drawText(-40,-10,f'R2={vr2:.5g}mm')
qp.setTransform(QtGui.QTransform())
qp.translate(p2); qp.rotate(-aa)
qp.drawText(20-int(szG[0]/2),20,f'aa={vaa:.5g}°')
qp.drawText(20,20,f'bb={vbb:.5g}°')
qp.setTransform(QtGui.QTransform())
qp.translate(p10); qp.rotate(-aa-bb)
qp.drawText(0,20,f'cc={vcc:.5g}°')
#for i,p in enumerate((p0,p1,p2,p3,p4,p5,p6,p7,p8,p9)):
# qp.drawText(p,f'P{i}')
#p5=QtCore.QPointF(*tf1.map(-r2-10, 50+w))
qp.end()
#https://www.pythonguis.com/tutorials/pyqt-dialogs/
class DlgMoveMotors(QtGui.QDialog):
def __init__(self):
super().__init__()
#self.initUI()
def initUI(self,prefix,motDst):
self._motDst=motDst
self.setWindowTitle("Move Motors:")
#QBtn=QtGui.QDialogButtonBox.Ok|QtGui.QDialogButtonBox.Cancel
#self.buttonBox=QtGui.QDialogButtonBox(QBtn)
#self.buttonBox.accepted.connect(self.accept)
#self.buttonBox.rejected.connect(self.reject)
self.buttonBox=QtGui.QDialogButtonBox()
btn=self.buttonBox.addButton('move all',QtGui.QDialogButtonBox.ActionRole)
btn.clicked.connect(self.OnMove)
self.buttonBox.addButton('stop all',QtGui.QDialogButtonBox.ActionRole)
self.layout=QtGui.QVBoxLayout()
message=QLabel("Something happened, is that OK?")
self.layout.addWidget(message)
self._wdGrpRaw=w=QtGui.QGroupBox("Motors", self)
self.layout.addWidget(w)
self._layoutGrid=lg=QtGui.QGridLayout(w)
# dev=epics.Device('SATES30-RIXS:MOT_ABL.', attrs=('VAL', 'RBV', 'DESC'))
app=QApplication.instance()
devs=app._devs
prefix='SATES30-RIXS:'
for i,(k,v) in enumerate(motDst.items()):
m='MOT_'+k.upper()
#devs[k]=dev=epics.Device(prefix+m+'.', attrs=('RBV', 'DESC'), timeout=.5) # for safty: removed 'VAL',
try:
dev=devs[k]
except KeyError:
devs[k]=dev=SimDevice(prefix+m+'.', attrs=('VAL', 'RBV', 'DESC'))
w=QtGui.QCheckBox(m,objectName=k)
lg.addWidget(w, i, 0)
if v is None:
#v="<P><b><font color='#808080'>(null)</i></b></font>"
v="<font color='#808080'>(null)</font>"
else:
rbv=dev.RBV
d=v-rbv
if d>0:
c='ff8080'
else:
c='60a060'
v=f"{v:.5g} <font color='#808080'>(old:{rbv:.5g} <font color='#{c}'> {d:.5g})</font></font>"
w.setChecked(True)
w=QLabel(v)
lg.addWidget(w, i, 1)
self.layout.addWidget(self.buttonBox)
self.setLayout(self.layout)
def OnMove(self):
app=QApplication.instance()
devs=app._devs
motDst=self._motDst
lg=self._layoutGrid
col=lg.columnCount()
for i,(k,v) in enumerate(motDst.items()):
cb=lg.itemAt(i*col).widget()
if cb.isChecked():
if v is not None:
dev=devs[k]
#print(dev)
dev.VAL=v # move motor
print(f'{cb.objectName()} {dev}')
# ->>>> https://pyepics.github.io/pyepics/devices.html >>> USE THIS
#[satesf-cons-03 ~]$ /opt/gfa/python-3.8/latest/bin/ipython3
#import CaChannel
#import epics
#capv=CaChannel.CaChannel('SATES30-RIXS:MOT_ABL.VAL') -> THIS IS REALLY BASIC...
#capv.state()
#m=epics.Motor('SATES30-RIXS:MOT_ABL')
#pv=pvm.PV('RBV')
#dev=epics.Device('SATES30-RIXS:MOT_ABL.', attrs=('VAL', 'RBV', 'DESC'))
#dev.RBV
class SimDevice():
def __init__(self, prefix='', attrs=None,
nonpvs=None, delim='', timeout=None,
mutable=True, aliases=None, with_poll=True):
self._prefix=prefix
self._pvs={}
for k in attrs:
self._pvs[k]=0
def __getattr__(self, attr):
#if self._pvs:
if '_pvs' in self.__dict__:
return self._pvs[attr]
else:
_log.debug(attr)
raise AttributeError
def __setattr__(self, attr, val):
if attr in ('_pvs','_prefix'):
self.__dict__[attr]=val
elif attr in self._pvs:
self._pvs[attr]= val
if attr=='VAL' and 'RBV' in self._pvs:
self._pvs['RBV']=val
else:
self.__dict__[attr]=val
def __repr__(self):
"string representation"
attr=[]
for k,v in self._pvs.items():
attr.append(f'{k}: {v}')
s=f"<Device: {self._prefix} ( "+', '.join(attr)+' )'
return s
# if attr in self._pvs:
# return self.get(attr)
# elif attr in self.__dict__:
# return self.__dict__[attr]
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=2)
parser.add_argument("--sim", "-s", type=lambda x: int(x,0), help="simulate devices (see bitmasks) default=0x%(default)x", default=0)
args=parser.parse_args()
_log.info('Arguments:{}'.format(args.__dict__))
app=QApplication(sys.argv)
vlsg=geometry.VLSgrating()
vlsg.setup('80meV')
app._vlsg=vlsg
app._devs=dict() # all device (grouped PVs)
if args.mode&0x01:
app._wndGirder= RIXSgirder()
if args.mode&0x02:
app._wndGrating=RIXSgrating()
sys.exit(app.exec_())
main()