Constraints#
Overview#
Computation of the real-space axis positions given a set of reciprocal-space
coordinates can have many solutions. One or more constraints
(Constraint
) (a.k.a, cut points), together with a choice of
operating mode, can be applied to:
limit the range of forward() solutions accepted for that positioner
declare the value to use when the positioner should be kept constant
Diffractometer constraints are described by:
|
Limitations on acceptable positions from computed forward() solutions. |
These functions manage constraints:
|
Constrain the solutions of the diffractometer's forward() computation. |
Set constraints back to initial settings. |
|
|
Print the current constraints in a table. |
Remove the current constraints additions, restore previous. |
|
|
Restore any constraints from orientation information. |
Diffractometer constraints can be exported and restored as part of a
DiffractometerConfiguration
:
|
Export configuration in a recognized format (dict, JSON, YAML, file). |
|
Restore configuration from a recognized format (dict, JSON, YAML, file). |
Tip
Constraints are implemented as cut points in other software. Similar yet not identical.
Create a constraint#
A Constraint
is defined as a Constraint
object. For
convenience, import directly from hkl.Constraint
:
hkl.Constraint(0, 90, 0, True)
Consider a diffractometer object:
from hkl import SimulatedE4CV
e4cv = SimulatedE4CV("", name="e4cv")
The default constraints for this geometry are (using e4cv.show_constraints()
):
axis |
low_limit |
high_limit |
value |
fit |
---|---|---|---|---|
omega |
-180.0 |
180.0 |
0.0 |
True |
chi |
-180.0 |
180.0 |
0.0 |
True |
phi |
-180.0 |
180.0 |
0.0 |
True |
tth |
-180.0 |
180.0 |
0.0 |
True |
Apply the constraint#
Apply a constraint just to the “tth” axis such that \(0<=2\theta<=120\):
e4cv.apply_constraints({"tth": Constraint(0, 120, 0, True)})
Show the constraints now (again, using e4cv.show_constraints()
):
axis |
low_limit |
high_limit |
value |
fit |
---|---|---|---|---|
omega |
-180.0 |
180.0 |
0.0 |
True |
chi |
-180.0 |
180.0 |
0.0 |
True |
phi |
-180.0 |
180.0 |
0.0 |
True |
tth |
0.0 |
119.99999999999999 |
0.0 |
True |
Remove the constraint#
Remove the previous constraint:
e4cv.undo_last_constraints()
e4cv.show_constraints()
Back to the defaults again:
axis |
low_limit |
high_limit |
value |
fit |
---|---|---|---|---|
omega |
-180.0 |
180.0 |
0.0 |
True |
chi |
-180.0 |
180.0 |
0.0 |
True |
phi |
-180.0 |
180.0 |
0.0 |
True |
tth |
-180.0 |
180.0 |
0.0 |
True |
Example#
Using the default sample (main), show the possible forward()
solutions for
a \((100)\) position with a hkl.geometries.E4CV
(4-circle) geometry
diffractometer with these constraints:
axis |
low_limit |
high_limit |
value |
fit |
---|---|---|---|---|
omega |
10.0 |
40.0 |
0.0 |
True |
chi |
-100.0 |
100.0 |
0.0 |
True |
phi |
-100.0 |
100.0 |
0.0 |
True |
tth |
10.0 |
92.4 |
0.0 |
True |
First, make the diffractometer (simulator) and show the default constraints:
1from hkl import SimulatedE4CV
2
3e4cv = SimulatedE4CV("", name="e4cv")
4e4cv.show_constraints()
axis |
low_limit |
high_limit |
value |
fit |
---|---|---|---|---|
omega |
-180.0 |
180.0 |
0.0 |
True |
chi |
-180.0 |
180.0 |
0.0 |
True |
phi |
-180.0 |
180.0 |
0.0 |
True |
tth |
-180.0 |
180.0 |
0.0 |
True |
Make a convenience function to show all the possible forward()
solutions in a table. The complete list of possible solutions is provided by
the low-level forward()
method:
1import pyRestTable
2
3def all_forward_solutions(hkl_position):
4 axes = e4cv.calc.physical_axis_names
5 table = pyRestTable.Table()
6 table.labels = axes
7 for sol in e4cv.calc.forward(hkl_position):
8 table.addRow([round(getattr(sol, k), 2) for k in axes])
9 print(f"solutions for forward({hkl_position}):")
10 print(table)
Show all solutions for the \((100)\) position (note the inner set of parentheses):
all_forward_solutions((1, 0, 0))
solutions for forward((1, 0, 0)):
omega |
chi |
phi |
tth |
---|---|---|---|
-30.21 |
0.0 |
-90.0 |
-60.42 |
30.21 |
0.0 |
90.0 |
60.42 |
-149.79 |
0.0 |
29.58 |
-60.42 |
-30.21 |
0.0 |
150.42 |
60.42 |
30.21 |
0.0 |
-150.42 |
-60.42 |
-149.79 |
0.0 |
-90.0 |
60.42 |
-30.21 |
180.0 |
90.0 |
-60.42 |
30.21 |
180.0 |
-90.0 |
60.42 |
-149.79 |
180.0 |
-29.58 |
-60.42 |
-30.21 |
180.0 |
-150.42 |
60.42 |
30.21 |
180.0 |
150.42 |
-60.42 |
-149.79 |
180.0 |
90.0 |
60.42 |
Next, apply the new constraints and print the revised table:
1e4cv.apply_constraints(
2 {
3 "omega": Constraint(10, 40, 0, True),
4 "chi": Constraint(-100, 100, 0, True),
5 "phi": Constraint(-100, 100, 0, True),
6 "tth": Constraint(10, 92.4, 0, True),
7 }
8)
9all_forward_solutions((1, 0, 0))
solutions for forward((1, 0, 0)):
omega |
chi |
phi |
tth |
---|---|---|---|
30.21 |
0.0 |
90.0 |
60.42 |
Only one solution satisfies these constraints.
forward()
#
Given a set of reciprocal-space coordinates (typically \(h\), \(k\), and
\(l\)), compute the different sets of real-space coordinates which match.
In the general case, the problem is over-determined. Multiple solutions are
expected. These are the forward()
computation methods:
Diffractometer
.forward()
- provides one solution, if possible(lower-level)
CalcRecip
.forward()
- provides a list of all allowed solutions
The hkl.diffract.Diffractometer.forward()
method selects the first
allowed solution from hkl.calc.CalcRecip.forward()
. This is the default
choice as defined by hkl.calc.default_decision_function()
. You can
replace it with your own function. Then, either:
(easier) set your diffractometer object’s
_decision_fcn
attribute, such as:e4cv._decision_fcn=your_function
(harder) pass it via the
decision_fcn=your_function
keyword when creating theDiffractometer
object