169 lines
7.6 KiB
Python
169 lines
7.6 KiB
Python
#!/usr/bin/env python
|
|
# *-----------------------------------------------------------------------*
|
|
# | |
|
|
# | Copyright (c) 2022 by Paul Scherrer Institute (http://www.psi.ch) |
|
|
# | |
|
|
# | Author Thierry Zamofing (thierry.zamofing@psi.ch) |
|
|
# *-----------------------------------------------------------------------*
|
|
'''
|
|
coordinate systems, optical center, xray axis, pixel sizes etc.
|
|
|
|
ppm= pixel per mm
|
|
update_pix2pos
|
|
|
|
modes:
|
|
0x01: update_pix2pos
|
|
0x02: update_optical_center
|
|
'''
|
|
import logging
|
|
_log=logging.getLogger(__name__)
|
|
|
|
import numpy as np
|
|
from scipy.optimize import fsolve
|
|
from RIXScfg import Config
|
|
|
|
|
|
|
|
class VLSgrating: #Gratings with Variable Line Density
|
|
def __init__(self):
|
|
pass
|
|
|
|
def setup(self,key):
|
|
self._param=Config._lutProbes[key]
|
|
|
|
# ---------- eugenio calculation functions ----------
|
|
def solve_focus_equ(self, eV):
|
|
esp=self._param['esp']
|
|
p0=esp['lut'][0][1:] # fsolve starting values for [r1, r2, alpha]
|
|
esp['En']=eV # Update the dictionary with the energy at which I want to calculate the positions
|
|
esp['Lam_nm']=1239.842/eV # Convert energy to wavelength
|
|
pn=fsolve(self.equations, p0, maxfev=100000000)
|
|
#es['r1'], es['r2'], es['alpha']=pn
|
|
return pn
|
|
|
|
def equations(self, pn): # system of 3 equations for 3 parameters
|
|
return (self.Eq1(*pn), self.Eq2(*pn), self.Eq4(*pn))
|
|
|
|
def Eq1(self, r1, r2, alpha):
|
|
p=self._param;esp=p['esp']
|
|
a1, R, a0, k, Lam_nm=p['a1'], p['R'], p['a0'], esp['k'], esp['Lam_nm']
|
|
beta=self.beta(r1, r2, alpha)
|
|
return np.cos(alpha)**2/r1+np.cos(beta)**2/r2-\
|
|
(np.cos(alpha)+np.cos(beta))/R-a1*k*Lam_nm/1e6
|
|
|
|
def Eq2(self, r1, r2, alpha):
|
|
p=self._param;esp=p['esp']
|
|
a0, a1, a2, R, k, Lam_nm=p['a0'], p['a1'], p['a2'], p['R'], esp['k'], esp['Lam_nm']
|
|
beta=self.beta(r1, r2, alpha)
|
|
return np.sin(alpha)/r1*(np.cos(alpha)**2/r1-np.cos(alpha)/R)-\
|
|
np.sin(beta)/r2*(
|
|
np.cos(beta)**2/r2-np.cos(beta)/R)+2*a2*k*Lam_nm/1e6/3
|
|
|
|
def Eq4(self, r1, r2, alpha):
|
|
p=self._param;esp=p['esp']
|
|
a3, R, k, Lam_nm, a0=p['a3'], p['R'], esp['k'], esp['Lam_nm'], p['a0']
|
|
beta=self.beta(r1, r2, alpha)
|
|
return 4*np.sin(alpha)**2/r1**2*(np.cos(alpha)**2/r1-np.cos(alpha)/R)\
|
|
-1/r1*(np.cos(alpha)**2/r1-np.cos(alpha)/R)**2+1/R**2*(1/r1-np.cos(alpha)/R)\
|
|
+4*np.sin(beta)**2/r2**2*(
|
|
np.cos(beta)**2/r2-np.cos(beta)/R)\
|
|
-1/r2*(np.cos(beta)**2/r2-np.cos(beta)/R)**2\
|
|
+1/R**2*(1/r2-np.cos(beta)/R)-2*a3*k*Lam_nm/1e6
|
|
|
|
def beta(self, r1, r2, alpha): # calculate beta as a function of alpha, energy, and diffraction order (k)
|
|
p=self._param;esp=p['esp']
|
|
a0, k, Lam_nm=p['a0'], esp['k'], esp['Lam_nm']
|
|
return np.arcsin(np.sin(alpha)-a0*k*Lam_nm/1e6)
|
|
|
|
def gamma(self, r1, r2, alpha): # compute detector lean angle in respect of the r2 arm
|
|
p=self._param;esp=p['esp']
|
|
R, a0, a1=p['R'], p['a0'], p['a1']
|
|
beta=self.beta(r1, r2, alpha)
|
|
return np.arctan(np.cos(beta)/(2*np.sin(beta)-r2*(np.tan(beta)/R+a1/a0)))
|
|
|
|
|
|
def energy2geometry(self, energy,probe):
|
|
# mode raytrace or interpolate lut
|
|
# prec precision requitements (precision iteration)
|
|
# returns R1,R2,aa,bb,cc
|
|
pn=self.solve_focus_equ(energy)
|
|
r1, r2, alpha=pn
|
|
beta=self.beta(*pn)
|
|
gamma=self.gamma(*pn)
|
|
geo={'r1':r1,'r2':r2,'aa':np.rad2deg(alpha), 'bb':np.rad2deg(beta), 'cc':np.rad2deg(gamma)}
|
|
return geo
|
|
|
|
if __name__=="__main__":
|
|
import argparse
|
|
|
|
logging.basicConfig(level=logging.DEBUG, format='%(levelname)s:%(module)s:%(lineno)d:%(funcName)s:%(message)s ')
|
|
|
|
#(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'
|
|
parser=argparse.ArgumentParser(epilog=epilog, formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
parser.add_argument("-m", "--mode", type=lambda x: int(x,0), help="mode (see bitmasks) default=0x%(default)x", default=0xff)
|
|
|
|
args=parser.parse_args()
|
|
_log.info('Arguments:{}'.format(args.__dict__))
|
|
|
|
np.set_printoptions(suppress=True)
|
|
np.set_printoptions(linewidth=196)
|
|
|
|
if args.mode&0x01:
|
|
|
|
|
|
vlsg=VLSgrating()
|
|
print(f'{"grating":>7s} | {"energy(eV)":>10s} | {"r1(mm)":>8s} | {"r2(mm)":>8s} | {"aa(°)":>5s} | {"bb(°)":>5s} | {"cc(°)":>5s}')
|
|
for gr,eV in (
|
|
('g80_1',500),
|
|
('g80_2',500),
|
|
('g80_3',500),
|
|
('gtst_1',500),
|
|
):
|
|
vlsg.setup(gr)
|
|
geo=vlsg.energy2geometry(eV)
|
|
print('{gr:>7s} | {eV:10.4g} | {r1:8.2f} | {r2:8.2f} | {aa:5.2f} | {bb:5.2f} | {cc:5.2f}'.format(gr=gr,eV=eV,**geo))
|
|
#print(g, vlsg.energy2geometry(e))
|
|
|
|
vlsg.setup('g80_1')
|
|
Es=np.arange(250, 1550, 50)
|
|
print('')
|
|
print(f'{"energy(eV)":>10s} | {"r1(mm)":>8s} | {"r2(mm)":>8s} | {"aa(°)":>5s} | {"bb(°)":>5s} | {"cc(°)":>5s}')
|
|
for eV in Es:
|
|
geo=vlsg.energy2geometry(eV)
|
|
print('{eV:10.4g} | {r1:8.2f} | {r2:8.2f} | {aa:5.2f} | {bb:5.2f} | {cc:5.2f}'.format(eV=eV,**geo))
|
|
#pn=vlsg.solve_focus_equ(eV)
|
|
#r1, r2, alpha=pn
|
|
#beta=vlsg.beta(*pn)
|
|
#gamma=vlsg.gamma(*pn)
|
|
#print(f'{eV:10.4g} | {r1:8.2f} | {r2:8.2f} | {np.rad2deg(alpha):5.2f} | {np.rad2deg(beta):5.2f} | {np.rad2deg(gamma):5.2f}')
|
|
|
|
|
|
#vlsg.setup('80meV')
|
|
#[[ 250. 1137.32196015 4269.702359 88.0898184 83.55888668 36.27529716]
|
|
# [ 300. 1193.65841126 4127.21279026 88.10217759 84.07300885 31.7396222 ]
|
|
# [ 350. 1247.36978781 4010.83457789 88.10391338 84.46686259 28.55391769]
|
|
# [ 400. 1299.07861098 3914.08632128 88.0986373 84.77926418 26.23765458]
|
|
# [ 450. 1349.21078537 3832.65392519 88.08846973 85.03343956 24.51153466]
|
|
# [ 500. 1398.0721341 3763.52172859 88.0747408 85.24424965 23.20495827]
|
|
# [ 550. 1445.89064959 3704.49942068 88.05832818 85.42170416 22.20901965]
|
|
# [ 600. 1492.84122971 3653.94623698 88.03983478 85.57282519 21.45157952]
|
|
# [ 650. 1539.06120728 3610.60137571 88.01968853 85.70270455 20.88341654]
|
|
# [ 700. 1584.66050296 3573.4750186 87.9982015 85.8151371 20.47018758]
|
|
# [ 750. 1629.72855701 3541.77572852 87.9756065 85.91301734 20.18757719]
|
|
# [ 800. 1674.33907781 3514.86055917 87.95208076 85.99859726 20.01827307]
|
|
# [ 850. 1718.5535488 3492.19987783 87.92776146 86.07365932 19.95002982]
|
|
# [ 900. 1762.42379391 3473.35198496 87.90275638 86.13963571 19.97440536]
|
|
# [ 950. 1805.9938836 3457.94443997 87.87715139 86.19769259 20.08592919]
|
|
# [1000. 1849.30170875 3445.66007701 87.85101563 86.24879078 20.28155755]
|
|
# [1050. 1892.37950222 3436.22635374 87.82440571 86.29373053 20.5603321 ]
|
|
# [1100. 1935.25594973 3429.40718162 87.79736786 86.33318446 20.92317777]
|
|
# [1150. 1977.95569753 3424.99649949 87.76994068 86.36772314 21.37282654]
|
|
# [1200. 2020.5004814 3422.81321829 87.74215652 86.39783427 21.91383066]
|
|
# [1250. 2062.90951189 3422.6972001 87.71404265 86.42393782 22.55267071]
|
|
# [1300. 2105.19981239 3424.50599743 87.6856223 86.44639783 23.29795403]
|
|
# [1350. 2147.38653997 3428.11221941 87.6569154 86.46553179 24.16071358]
|
|
# [1400. 2189.48325951 3433.40137902 87.62793911 86.4816182 25.15482162]
|
|
# [1450. 2231.50212122 3440.27009676 87.59870838 86.49490264 26.29753817]
|
|
# [1500. 2273.45406713 3448.62463224 87.56923627 86.50560273 27.61022401]] |