Switch Diffraction Modes#
A diffraction mode is a ConstraintSet
that describes which motor stages are free, which are held at declared values,
and which are related to others (e.g. bisecting).
See Concepts for background, and
Work with Constraints and Diffraction Modes for the full constraint framework.
List available modes#
import ad_hoc_diffractometer as ahd
g = ahd.presets.fourcv()
print(list(g.modes.keys()))
# ['bisecting', 'fixed_chi', 'fixed_phi', 'fixed_omega',
# 'fixed_psi', 'double_diffraction']
Get and set the active mode#
# The default mode is set by the factory
print(g.mode_name) # 'bisecting'
# Switch to a different mode
g.mode_name = "fixed_chi"
print(g.mode_name) # 'fixed_chi'
# Clear the active mode (all stages free — forward() will raise)
g.mode_name = None
Mode reference#
Bisecting mode#
The bisecting BisectConstraint drives the
co-axial sample stage to half the detector angle, placing the sample
symmetrically between the incident and diffracted beams.
g.mode_name = "bisecting"
solutions = g.forward(1, 0, 0)
# omega = ttheta / 2 in every solution
Fixed-angle modes#
Fixed-angle modes hold one sample stage at its declared constraint value
during a single forward() call. The value is part of the ConstraintSet
definition and is constant only for the duration of that call.
# fixed_chi: factory default holds chi at 90°
g.mode_name = "fixed_chi"
solutions = g.forward(1, 0, 0)
# sol["chi"] == 90.0 for every solution
To use a different value, construct a new ConstraintSet
and assign it. The constraint persists until replaced — only reassign when
the value changes:
from ad_hoc_diffractometer import ConstraintSet, SampleConstraint
# Call 1: chi = 45°
g.modes["my_chi"] = ConstraintSet([SampleConstraint("chi", 45.0)])
g.mode_name = "my_chi"
sols_45 = g.forward(1, 0, 0) # chi = 45° this call
# Call 2: chi = 60°
g.modes["my_chi"] = ConstraintSet([SampleConstraint("chi", 60.0)])
sols_60 = g.forward(1, 0, 0) # chi = 60° this call
See Work with Constraints and Diffraction Modes for the full run-time pattern.
fixed_omega#
Holds omega at 0° (any geometry where omega is a sample stage).
g.mode_name = "fixed_omega"
solutions = g.forward(1, 0, 0)
# sol["omega"] == 0.0 for every solution
Inspect a mode’s constraints#
g = ahd.presets.fourcv()
cs = g.modes["fixed_chi"]
print(cs)
# ConstraintSet([SampleConstraint('chi', 90.0)])
print(cs.computed)
# ['omega', 'phi', 'ttheta']
print(cs.constant_stages)
# ['chi']
print(cs.is_fully_constrained(g))
# True (N - 3 = 1 constraint for N = 4 DOF)
print(cs.is_implemented(g))
# True
Check if a mode is implemented#
Some modes require a prerequisite on the geometry. For example,
fixed_psi requires g.azimuthal_reference to be set:
g.mode_name = "fixed_psi"
print(g.modes["fixed_psi"].is_implemented(g)) # False (no azimuthal_reference)
g.azimuthal_reference = (0, 0, 1)
print(g.modes["fixed_psi"].is_implemented(g)) # True
# forward() raises NotImplementedError for unimplemented modes
Clear the active mode#
g.mode_name = None # all stages free; forward() raises NotImplementedError
See also#
Work with Constraints and Diffraction Modes — full constraint framework: DOF rule, custom modes, extras