Files
EsfRixsApps/graphExample.py
2022-11-08 07:21:52 +01:00

397 lines
13 KiB
Python
Executable File

#!/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
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):
def __init__(self):
super().__init__()
self._param={'ctr':(200, 300), # location of big chamber
'aa':45, # RIXS arm angle
'cc':45, # UNSUSED
}
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)
w=QtGui.QGroupBox("Drawing",self)
w.move(10,10)
l=QtGui.QVBoxLayout(w)
sld={}
for key,rng,tk,pos in (('aa',(0,180),5,20),('cc',(0,180),5,40),):
sl=QtGui.QSlider(QtCore.Qt.Horizontal)
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):
print(key,val)
self._param[key]=val
self.update()
def paintEvent(self, e):
p=self._param
ctr=p['ctr']
aa=p['aa']
qp = QPainter()
qp.begin(self)
qp.translate(ctr[0],ctr[1])
qp.setPen(QtGui.QPen(QtCore.Qt.black, 2, QtCore.Qt.SolidLine))
qp.setBrush(QColor(255, 80, 0, 128))
rCmb=100 # radius of chamber
rTrg=10 # radius of target
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(-aa)
qp.drawRect(-50, 100, 100, 300) # girder
qp.drawEllipse(-50, 100+150, 20, 20) #pusher left
qp.drawEllipse( 50-20, 100+150, 20, 20) #pusher right
qp.drawEllipse(-50, 100+250, 20, 20) #air pad left
qp.drawEllipse( 50-20, 100+250, 20, 20) #air pad right
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':(400,400), # location of vlsg
'r1':314,#distance probe grating
'r2':447,#distance grating detector
'aa':22, #grating angle
'cc':58, #detector angle
#'geo':(8,8,5,5,1), # scaling: r1,r2,aa,bb,cc
'szG':(200,5), #size VLS grating
'szD':(150,5), #size detector
'energy':300, # input energy in eV
}
self.initUI()
def initUI(self):
#p=self.palette()
#p.setColor(self.backgroundRole(), QtCore.Qt.black)
#self.setPalette(p)
self.setGeometry(300, 300, 850, 800)
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)
for i,t in enumerate(('Energy',)):
w=QLabel(t)
lg.addWidget(w, i,0)
w=QtGui.QLineEdit(t,objectName=t)
lg.addWidget(w, i,1)
w=QtGui.QPushButton('calc geometry')
i+=1;lg.addWidget(w, i, 1)
sld={}
for key,rng,tk,pos in (('energy',(200,1500),50,60),):
sl=QtGui.QSlider(QtCore.Qt.Horizontal)
sl.setFixedWidth(200);sl.setMinimum(rng[0]);sl.setMaximum(rng[1])
sl.setValue(self._param[key])
sl.setTickPosition(QtGui.QSlider.TicksBelow);sl.setTickInterval(tk)
lv.addWidget(sl)
sl.valueChanged.connect(lambda val,key=key: self.sldChanged(key,val))
sld[key]=sl
self._wdGrpGeometry=w=QtGui.QGroupBox("Geometry",self)
w.move(250,10)
#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(tl,objectName=t)
l.addWidget(w, i,1)
w=QtGui.QPushButton('calc raw motors')
l.addWidget(w, i+1, 1)
w=QtGui.QGroupBox("Drawing",self)
w.move(10,160)
l=QtGui.QVBoxLayout(w)
sld={}
for key,rng,tk,pos in (('r1',(50,800),50,60),('r2',(50,800),50,80),('aa',(0,90),5,20),('cc',(0,180),5,40),):
sl=QtGui.QSlider(QtCore.Qt.Horizontal)
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):
print(key,val)
if key=='energy':
app=QApplication.instance()
wEnergy=self._wdGrpEnergy.findChild(QtGui.QLineEdit,'Energy')
wGeo=self._wdGrpGeometry
wR1=wGeo.findChild(QtGui.QLineEdit,'R1')
wR2=wGeo.findChild(QtGui.QLineEdit,'R2')
wAA=wGeo.findChild(QtGui.QLineEdit,'aa')
wBB=wGeo.findChild(QtGui.QLineEdit,'bb')
wCC=wGeo.findChild(QtGui.QLineEdit,'cc')
wEnergy.setText(f'{val:.4g}')
vlsg=app._vlsg
(r1,r2,aa,bb,cc)=vlsg.energy2geometry(val)
wR1.setText(f'{r1:.4g}')
wR2.setText(f'{r2:.4g}')
wAA.setText(f'{aa:.4g}')
wBB.setText(f'{bb:.4g}')
wCC.setText(f'{cc:.4g}')
p=self._param
p['r1']=r1
p['r2']=r2
p['aa']=(90-aa)
p['bb']=(90-bb)
p['cc']=(90-cc)
else:
self._param[key]=val
#print(v)
self.update()
def paintEvent(self, e):
p=self._param
r1=p['r1']
r2=p['r2']
aa=p['aa']
bb=aa*1.5
cc=p['cc']
szG=p['szG']
szD=p['szD']
ctr=p['ctr']
#scl=p['scl']
qp = QPainter()
qp.begin(self)
#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, r1, 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, r2, 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) #beam
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,r2,0) #beam
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=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
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(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(i*scl, 255, 255, alpha)
qp.setBrush(col)
qp.drawPolygon(p0, p1, p2, p3)
qp.setCompositionMode(QtGui.QPainter.CompositionMode_SourceOver)
pen=QtGui.QPen(QtCore.Qt.red, 3, QtCore.Qt.SolidLine)
qp.setPen(pen)
p0=QtCore.QPointF(*tf0.map(-r1-10, +10))
p1=QtCore.QPointF(*tf0.map(-r1-10, 50+w))
qp.drawLine(p0,p1)
p2=QtCore.QPointF(*tf0.map(0, 0))
p3=QtCore.QPointF(*tf0.map(0, 50+w))
qp.drawLine(p2,p3)
p4=(p1+p3)/2
qp.drawText(p4,f'R1={r1:.5g}mm')
p5=QtCore.QPointF(*tf2.map(0, 50+w))
qp.drawLine(p2,p5)
p6=QtCore.QPointF(*tf2.map(r2, 0))
p7=QtCore.QPointF(*tf2.map(r2, 50+w))
qp.drawLine(p6,p7)
p8=(p5+p7)/2
qp.drawText(p8,f'R2={r2:.5g}mm')
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.drawText(p2+QtCore.QPointF(-s1,s2+20),f'aa={aa:.5g}°')
qp.drawArc(int(p2.x())-s, int(p2.y())-s, 2*s, 2*s, int(aa*16), int(bb*16))
qp.drawText(p2+QtCore.QPointF(s1,-s2+20),f'bb={bb:.5g}°')
qp.drawArc(int(p6.x())-s, int(p6.y())-s, 2*s, 2*s, int(180+aa+bb*16), int(cc*16))
p10=QtCore.QPointF(*tf2.map(r2+20, 0))
qp.drawText(p10,f'cc={cc:.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()
if __name__ == '__main__':
def main():
app=QApplication(sys.argv)
vlsg=geometry.VLSgrating()
vlsg.setup('80meV')
app._vlsg=vlsg
# ex = RIXSgirder()
ex=RIXSgrating()
sys.exit(app.exec_())
main()