Orient a Crystal#
This guide shows how to compute the U and UB matrices from orienting reflections. See Concepts for background on what B, U, and UB mean.
Overview#
Crystal orientation requires:
A geometry with a wavelength set
A sample with a lattice defined
One, two, or three measured reflections with known (hkl) and motor angles
Set up the geometry and sample#
import ad_hoc_diffractometer as ahd
g = ahd.presets.fourcv()
g.wavelength = 1.5406 # Å (Cu Kα)
g.sample.lattice = ahd.Lattice(a=5.431) # cubic silicon
Add orienting reflections#
# Add the primary reflection at its measured motor angles
g.sample.reflections.add("or1", hkl=(0, 0, 4),
angles={"ttheta": 69.13, "omega": 34.56,
"chi": 90.0, "phi": 0.0})
# Add a second reflection 90° away in phi
g.sample.reflections.add("or2", hkl=(2, 2, 0),
angles={"ttheta": 47.30, "omega": 23.65,
"chi": 35.26, "phi": 90.0})
# Designate which reflections to use for the UB calculation
g.sample.reflections.setor0("or1")
g.sample.reflections.setor1("or2")
Compute UB from two reflections (Busing & Levy 1967)#
UB = ahd.ub_from_two_reflections_bl1967(g.sample)
print("UB =\n", UB)
This is the standard method for most beamline work.
Compute UB from one reflection#
When only one reflection is available, a provisional UB can be computed by specifying a reference crystal direction and a reference stage:
UB = ahd.ub_from_one_reflection(
g.sample,
reflection=g.reflections["or1"],
reference_hkl=(0, 0, 1), # crystal direction to align
reference_stage="chi", # stage axis to align it along
)
Compute UB from three reflections (direct method)#
For unknown lattices, UB can be determined directly from three reflections without prior knowledge of the unit cell:
g.sample.reflections.add("or3", hkl=(1, 1, 3),
angles={"ttheta": 56.12, "omega": 28.06,
"chi": 58.0, "phi": 45.0})
UB = ahd.ub_from_three_reflections_bl1967(
g.sample,
g.sample.reflections["or1"],
g.sample.reflections["or2"],
g.sample.reflections["or3"],
)
Use an identity U matrix#
For a perfectly aligned crystal (crystal axes parallel to diffractometer axes), use the identity orientation:
ahd.ub_identity(g.sample)
Verify the orientation — direction check#
Check that UB @ h points in the same direction as the observed Q:
import numpy as np
def direction_check(geometry, name):
r = geometry.sample.reflections[name]
q_phi = ahd.orientation.angles_to_phi_vector(geometry, **r.angles)
ub_h = geometry.sample.UB @ r.hkl
cos_theta = np.dot(q_phi, ub_h) / (np.linalg.norm(q_phi) * np.linalg.norm(ub_h))
angle_deg = np.degrees(np.arccos(np.clip(cos_theta, -1, 1)))
print(f"{name}: {angle_deg:.3f}° discrepancy")
direction_check(g, "or1")
direction_check(g, "or2")
0.0° means perfect agreement.
Full worked example#
See the Align a Four-Circle Diffractometer (fourcv) notebook for a complete step-by-step crystal alignment on a real instrument.