Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
BCU-Vercors
ID26
id26
Commits
fbad3d7e
Commit
fbad3d7e
authored
Aug 12, 2020
by
bliss administrator
Browse files
texs controller initial commit
parent
11115dfb
Pipeline
#31200
failed
Changes
2
Pipelines
2
Expand all
Hide whitespace changes
Inline
Side-by-side
id26/controllers/test_texs.py
0 → 100644
View file @
fbad3d7e
import
numpy
as
np
import
id26.controllers.texs_calculations
as
tc
from
bliss.controllers.motor
import
CalcController
"""
Bliss controller for TEXS spectrometer
(ID26)
Author: Mauro Rovezzi (mauro.rovezzi@esrf.eu) and Blanka Detlefs (blanka.detlefs@esrf.fr)
<!-- need initialization -->
########################################################################################
# these should be configuration parameters (to be changed by a user; something like
# dcm.dcm.xtals.xtal_sel = 'Si111'
CRYST_R = 240 # Rowland radius of the CA
CRYST_MAT = 'Si'
CRYST_HKL = (1,1,1)
########################################################################################
# needed to calculate d-spacing (ie. also possible to give directly dspacing like
# dcm_xtals.dspacing (in yml config file)
# these are ID26specific instrument parameters (constants until we rebuild the machine):
dtower_rot=35.
aW = 25;
aWext = 32;
rSext = 10;
aL = 97;
bender_version = 1
bender = (40., 60., 28.);
actuator=(300, 120);
<!-- REAL MOTORS -->
<axis name="theta_B" tags="real TR" />
<axis name="table_y" tags="real TYT" />
<axis name="det_rot" tags="real DR" />
<axis name="det_long" tags="real DY" />
<axis name="det_short" tags="real DZ" />
<axis name="actuator1" tags="real sag1" /> # this one has to be calculated too!
<axis name="actuator2" tags="real sag2" /> # this one has to be calculated too!
<!-- CALCULATED MOTORS -->
<axis name="xen1" tags="xes_en_texs">
# <axis name="xythe1" tags="xy_theta_eh1">
# fine also for bliss
"""
###################################################
#these cannot be GLOBAL VARIABLES !!!!!
###################################################
# do something like Gilles Berruyer in the dcm: bragg2energy
#============= GLOBAL VARIABLES ==================
HC
=
1.2398418743309972e-06
# eV * m
ALAT_SI
=
5.431065
# Ang at 25C
ALAT_GE
=
5.6579060
# Ang at 25C
#======= for the bender_version = 1 (installed in June 2017) ==========
aW
=
25
aWext
=
32
rSext
=
10
aL
=
97
bender_version
=
1
bender
=
(
40.
,
60.
,
28.
)
actuator
=
(
300
,
120
)
dtower_rot
=
35.
#================== UTILITY FUNCTIONS =================================
def
kev2wlen
(
energy
):
""" convert photon energy (E, keV) to wavelength ($\lambda$, \AA$^{-1}$)"""
return
((
HC
/
energy
)
*
1e7
)
def
wlen2kev
(
wlen
):
""" convert photon wavelength ($\lambda$, \AA$^{-1}$) to energy (E, keV)"""
return
(
HC
/
wlen
)
*
1e7
def
theta_b
(
ene
,
d
):
"""Bragg angle (rad) given energy (keV) and d-spacing (\AA)"""
if
not
(
d
==
0
):
return
np
.
arcsin
((
kev2wlen
(
ene
))
/
(
2
*
d
))
else
:
print
(
"ERROR: d-spacing is 0"
)
return
def
bragg_kev
(
theta
,
d
):
"""energy (keV) given Bragg angle (deg) and d-spacing (\AA)"""
return
wlen2kev
(
2
*
d
*
np
.
sin
(
np
.
deg2rad
(
theta
)))
def
sqrt1over
(
d2m
):
if
(
d2m
==
0
):
return
0
else
:
return
np
.
sqrt
(
1
/
d2m
)
def
d_cubic
(
a
,
hkl
,
**
kws
):
"""d-spacing for a cubic lattice"""
#print(hkl)
[
h
,
k
,
l
]
=
hkl
.
split
(
' '
)
d2m
=
(
int
(
h
)
**
2
+
int
(
k
)
**
2
+
int
(
l
)
**
2
)
/
a
**
2
return
sqrt1over
(
d2m
)
def
get_dspacing
(
mat
,
hkl
):
"""get d-spacing for given crystal material and reflection (hkl)"""
if
mat
==
'Si'
:
dspacing
=
d_cubic
(
ALAT_SI
,
hkl
)
elif
mat
==
'Ge'
:
dspacing
=
d_cubic
(
ALAT_GE
,
hkl
)
else
:
print
(
"ERROR: available materials -> 'Si' 'Ge'"
)
dspacing
=
0
return
dspacing
#================== TEXS CALC CONTROLLER ==============================
class
ID26TEXS
(
CalcController
):
# probably first a generic TEXS and then ID26TEXS
def
__init__
(
self
,
*
args
,
**
kwargs
):
CalcController
.
__init__
(
self
,
*
args
,
**
kwargs
)
self
.
_cryst_r
=
500
self
.
_hkl
=
'1 1 1'
self
.
_material
=
'Si'
self
.
_pos_dict
=
{}
self
.
_update_rc
()
def
initialize_axis
(
self
,
axis
):
CalcController
.
initialize_axis
(
self
,
axis
)
def
_update_rc
(
self
):
self
.
rc
=
tc
.
RcHoriz
(
Rm
=
self
.
_cryst_r
,
theta0
=
35
,
d
=
get_dspacing
(
self
.
_material
,
self
.
_hkl
),
\
aW
=
aW
,
aWext
=
aWext
,
rSext
=
rSext
,
aL
=
aL
,
\
bender_version
=
bender_version
,
\
bender
=
bender
,
actuator
=
actuator
,
showInfos
=
True
)
@
property
def
cryst_r
(
self
):
return
self
.
_cryst_r
@
cryst_r
.
setter
def
cryst_r
(
self
,
value
):
print
(
"setting crystal_r"
)
self
.
_cryst_r
=
value
self
.
_update_rc
()
@
property
def
hkl
(
self
):
return
map
(
int
,
self
.
_hkl
.
split
())
@
hkl
.
setter
def
hkl
(
self
,
value
):
value_str
=
' '
.
join
(
map
(
str
,
value
))
print
(
"setting hkl"
,
value
,
value_str
)
self
.
_hkl
=
value_str
self
.
_update_rc
()
@
property
def
material
(
self
):
return
self
.
_material
@
material
.
setter
def
material
(
self
,
value
):
print
(
"setting material"
)
self
.
_material
=
value
self
.
_update_rc
()
def
calc_from_real
(
self
,
positions_dict
):
"""returns emission energy given real motors positions (only TR/ theta_Bragg used)
(INFO: method called when a real motor is moved)
"""
print
(
"----> Entering calc_from_real"
)
self
.
_pos_dict
=
positions_dict
#used to store ALL motors positions
#theta0 = positions_dict["TR"]+0.019415
theta0
=
positions_dict
[
"TR"
]
print
(
"theta0: "
,
theta0
)
print
(
"dispacing: "
,
get_dspacing
(
self
.
_material
,
self
.
_hkl
))
xes_en_texs
=
bragg_kev
(
theta0
,
get_dspacing
(
self
.
_material
,
self
.
_hkl
))
_virt_dict
=
{
"xes_en_texs"
:
xes_en_texs
}
self
.
_pos_dict
.
update
(
_virt_dict
)
print
(
" all motors positions are: "
,
positions_dict
)
print
(
"..... returning virtual motors: "
,
_virt_dict
)
return
_virt_dict
def
calc_to_real
(
self
,
positions_dict
):
"""returns real motors positions dictionary given the master value of TR
(INFO: method called when a real motor is moved)
"""
print
(
"----> Entering calc_to_real"
)
self
.
_pos_dict
=
positions_dict
#used to store ALL motors positions
xes_en
=
positions_dict
[
"xes_en_texs"
]
theta0
=
np
.
rad2deg
(
theta_b
(
xes_en
,
get_dspacing
(
self
.
_material
,
self
.
_hkl
)))
print
(
"theta0: "
,
theta0
)
# init of rc should go into the __init__ section maybe
act_mot_pos
=
[]
TYT
=
[]
DY
=
[]
DZ
=
[]
DR
=
[]
if
isinstance
(
theta0
,
np
.
ndarray
):
th0_list
=
list
(
theta0
)
elif
not
isinstance
(
theta0
,
list
):
th0_list
=
[
theta0
]
else
:
th0_list
=
theta0
for
th0
in
th0_list
:
print
(
"working with theta = "
,
th0
)
self
.
rc
.
set_theta0
(
th0
)
# now calculate actuator
pb_in
=
self
.
rc
.
get_bender_pos
(
aN
=
5
)
print
(
"pb_in: "
,
pb_in
)
act_mot_pos
.
append
(
self
.
rc
.
get_bender_mot
(
pb_in
))
print
(
"act_mot_pos: "
,
act_mot_pos
)
TYT
.
append
(
self
.
rc
.
p
)
print
(
"TYT: "
,
TYT
)
dpos
=
self
.
rc
.
get_det_pos
()
print
(
"dpos: "
,
dpos
)
dpos2
=
tc
.
det_pos_rotated
(
dpos
,
drot
=
dtower_rot
)
DY
.
append
(
dpos2
[
0
])
DZ
.
append
(
dpos2
[
1
])
print
(
"dy: "
,
DY
,
"dz: "
,
DZ
)
DR
.
append
(
2.
*
th0
)
_real_dict
=
{
"TR"
:
np
.
array
(
theta0
),
"sag1"
:
np
.
array
(
act_mot_pos
),
"sag2"
:
np
.
array
(
act_mot_pos
),
"TYT"
:
np
.
array
(
TYT
),
"DY"
:
np
.
array
(
DY
),
"DZ"
:
np
.
array
(
DZ
),
"DR"
:
np
.
array
(
DR
)
}
self
.
_pos_dict
.
update
(
_real_dict
)
print
(
"..... returning real motors:"
)
for
k
,
v
in
self
.
_pos_dict
.
items
():
print
(
f
"
{
k
}
=
{
v
}
"
)
return
_real_dict
id26/controllers/texs_calculations.py
0 → 100644
View file @
fbad3d7e
This diff is collapsed.
Click to expand it.
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment