Diffractometer Axis Names#
In hklpy2, the names of diffractometer axes (pseudos and reals) are not required to match any particular Solver library. Users are free to use any names allowed by ophyd.
User-defined axis names#
Let’s see examples of diffractometers built with user-defined names.
Diffractometer Creator with automatic mapping
Custom Diffractometer with additional axes with directed mapping
Diffractometer Creator#
The creator()
function constructs a diffractometer object using the
supplied reals={} to define their names. These are mapped to the names used
by the Solver. Let’s show this cross-reference map with just a few commands:
>>> import hklpy2
>>> twoc = hklpy2.creator(
name="twoc",
geometry="TH TTH Q",
solver="th_tth",
reals={"sample": None, "detector": None},
)
>>> twoc.core.axes_xref
{'q': 'q', 'sample': 'th', 'detector': 'tth'}
>>> twoc.wh()
q=0
wavelength=1.0
sample=0, detector=0
Custom Diffractometer class#
Construct a 2-circle diffractometer, one axis for the sample and one axis for the detector.
In addition to defining the diffractometer axes, we name the Solver to use
with our diffractometer. The th_tth
Solver has a
ThTthSolver
with a "TH TTH Q"
geometry
that fits our design. We set that up in the __init__()
method of our new
class.
The TH TTH Q geometry has real axes named
th
and tth
. Even though we are using different names, it is not
necessary to define _real
(as shown in Custom Diffractometer with additional axes)
as long as:
We define the same number of pseudos as the solver expects.
We define the same number of reals as the solver expects.
We specify each in the order expected by the solver.
1import hklpy2
2from hklpy2.diffract import Hklpy2PseudoAxis
3from ophyd import Component, SoftPositioner
4
5class S1D1(hklpy2.DiffractometerBase):
6
7 q = Component(Hklpy2PseudoAxis, "", kind=H_OR_N)
8
9 sample = Component(SoftPositioner, init_pos=0)
10 detector = Component(SoftPositioner, init_pos=0)
11
12 # Alias 'sample' to 'th', 'detector' to 'tth'
13 _real = ["sample", "detector"]
14
15 def __init__(self, *args, **kwargs):
16 super().__init__(
17 *args,
18 solver="th_tth", # solver name
19 geometry="TH TTH Q", # solver geometry
20 **kwargs,
21 )
Create a Python object that uses this class:
twoc = S1D1(name="twoc")
Tip
Use the hklpy2.geom.creator()
instead:
twoc = hklpy2.creator(
name="twoc",
geometry="TH TTH Q",
solver="th_tth",
reals=dict(sample=None, detector=None)
)
Show the mapping between user-defined axes and axis names used by the Solver:
>>> print(twoc.core.axes_xref)
{'q': 'q', 'sample': 'th', 'detector': 'tth'}
Custom Diffractometer with additional axes#
Consider this example for a two-circle class (with additional axes).
The "TH TTH Q"
Solver geometry expects q
as
the only pseudo axis and th
and tth
as the two real axes
(no extra axes).
We construct this example so that we’ll need to override the automatic
assignment of axes (lots of extra pseudo and real axes, none of them in the
order expected by the solver). Look for the _pseudo=["q"]
and
_real=["theta", "ttheta"]
parts where we define the mapping.
1import hklpy2
2from hklpy2.diffract import Hklpy2PseudoAxis
3from ophyd import Component, SoftPositioner
4
5class MyTwoC(hklpy2.DiffractometerBase):
6
7 # sorted alphabetically for this example
8 another = Component(Hklpy2PseudoAxis)
9 horizontal = Component(SoftPositioner, init_pos=0)
10 q = Component(Hklpy2PseudoAxis)
11 theta = Component(SoftPositioner, init_pos=0)
12 ttheta = Component(SoftPositioner, init_pos=0)
13 vertical = Component(SoftPositioner, init_pos=0)
14
15 _pseudo = ["q"]
16 _real = ["theta", "ttheta"]
17
18 def __init__(self, *args, **kwargs):
19 super().__init__(
20 *args,
21 solver="th_tth",
22 geometry="TH TTH Q",
23 **kwargs
24 )
Create the diffractometer:
twoc = MyTwoC(name="twoc")
What are the axes names used by this diffractometer?
>>> twoc.pseudo_axis_names
['another', 'q']
>>> twoc.real_axis_names
['horizontal', 'theta', 'ttheta', 'vertical']
Show the twoc
diffractometer’s Solver:
>>> twoc.core.solver
ThTthSolver(name='th_tth', version='0.0.14', geometry='TH TTH Q')
What are the axes expected by this Solver?
>>> twoc.core.solver.pseudo_axis_names
['q']
>>> twoc.core.solver.real_axis_names
['th', 'tth']
>>> twoc.core.solver.extra_axis_names
[]
Show the cross-reference mapping from diffractometer to Solver axis names (as defined in our MyTwoC class above):
>>> twoc.core.axes_xref
{'q': 'q', 'theta': 'th', 'ttheta': 'tth'}