Choose and Understand Basis Vectors#
A basis maps the three observable physical directions of the diffractometer — vertical, longitudinal, and transverse — to Cartesian unit vectors (x, y, z). The physics does not depend on which mapping you choose; the basis is purely a notational convention that determines the numerical representation of axis vectors, rotation matrices, and the UB matrix.
This page explains what a basis is, why it matters, how to choose one, and how to define a custom basis.
The three physical directions#
Every diffractometer has three mutually perpendicular directions that can be identified by looking at the instrument:
Direction |
Definition |
|---|---|
vertical |
opposite to gravitational acceleration (upward) |
longitudinal |
in the horizontal plane, conventionally along the incident beam toward the equipment |
transverse |
orthogonal to both; positive sense completes a right-handed system (vertical x longitudinal) |
These directions are physical observables — they do not depend on any coordinate convention. See Case Study: Describing a Diffractometer for the full derivation.
What a basis does#
A basis assigns each physical direction to a Cartesian axis. For example, the You (1999) convention assigns:
vertical -> +x (XHAT)
longitudinal -> +y (YHAT)
transverse -> +z (ZHAT)
The Busing & Levy (1967) convention makes a different choice:
vertical -> +z (ZHAT)
longitudinal -> +y (YHAT)
transverse -> +x (XHAT)
The NeXus convention makes a different choice:
vertical -> +y (YHAT)
longitudinal -> +z (ZHAT)
transverse -> +x (XHAT)
All are valid right-handed systems. The same physical rotation (e.g. “right-handed about the vertical axis”) has different matrix representations in each basis, but the diffraction calculation gives the same motor angles regardless.
Requirements for a valid basis#
The package validates the basis at geometry construction time. A valid basis must satisfy:
Exactly three vectors — one for each physical direction.
Each vector is 3-dimensional and non-zero.
Mutually orthogonal — every pair of vectors has zero dot product (within a tolerance of 1e-10).
Note
The package does not check right-handedness. It is the caller’s
responsibility to ensure that vertical x longitudinal = transverse
(i.e. the three vectors form a right-handed system). All pre-built
geometries satisfy this constraint; custom geometries should verify it
explicitly.
Pre-built conventions#
The package exports two basis constants used by the preset geometries:
Basis |
vertical |
longitudinal |
transverse |
Presets |
|---|---|---|---|---|
+x |
+y |
+z |
psic, sixc, kappa6c, zaxis, s2d2, fivec |
|
+z |
+y |
+x |
fourcv, fourch, kappa4cv, kappa4ch |
Other conventions exist in the broader community (e.g. NeXus, Hkl) — see Concepts for a tabulated comparison.
Defining a custom basis#
You may pass any valid basis dict to
AdHocDiffractometer. The keys
must be "vertical", "longitudinal", and "transverse"; the values
are 3-element array-like objects:
import numpy as np
import ad_hoc_diffractometer as ahd
from ad_hoc_diffractometer.stage import Stage
# NeXus convention: vertical=+y, longitudinal=+z, transverse=+x
nexus_basis = {
"vertical": np.array([0.0, 1.0, 0.0]),
"longitudinal": np.array([0.0, 0.0, 1.0]),
"transverse": np.array([1.0, 0.0, 0.0]),
}
# Use this basis with a custom geometry
g = ahd.AdHocDiffractometer(
name="my_geometry",
stages=[
Stage("omega", np.array([0.0, 1.0, 0.0]), role="sample"),
Stage("ttheta", np.array([0.0, 1.0, 0.0]), role="detector"),
],
basis=nexus_basis,
description="Minimal two-circle with NeXus basis",
)
The axis vectors on each Stage
are expressed in the same Cartesian frame as the basis — so when you
change the basis, the Stage axis vectors must change accordingly.
What changes when you change the basis#
Changing the basis changes the numerical representation of every vector quantity in the geometry:
Stage axis vectors (e.g.
+XHATvs+ZHATfor the vertical axis)Rotation matrices
The B, U, and UB matrices
Q-vectors computed by
angles_to_phi_vector()
What does not change:
Motor angles returned by
forward()and accepted byinverse()Bragg angles and d-spacings
Physical rotation directions (right-handed vs left-handed)
The number and type of solutions
The basis is a bookkeeping convention. Two geometries that describe the same physical diffractometer with different bases will produce identical motor angles for the same reflection.
Common mistakes#
Swapping vertical and transverse.
If you accidentally assign vertical -> +z and transverse -> +z (or
repeat any axis), the constructor will raise a ValueError because the
vectors are not mutually orthogonal.
Left-handed system.
If vertical x longitudinal points in the opposite direction from your
transverse vector, the system is left-handed. The package does not
detect this automatically — it will produce incorrect results silently.
Always verify: np.cross(vertical, longitudinal) should equal
transverse (not -transverse).
Mixing conventions. If you define stages using axis vectors from one convention but pass a basis dict from another, the geometry description will be internally inconsistent. The axis vectors and basis must use the same Cartesian frame.
See also#
Concepts — coordinate conventions, axis signs, and four tabulated basis mappings
Case Study: Describing a Diffractometer — the case study that defines the physical reference frame
Case Study: Coordinate Convention and UB Matrix — worked example deriving B/U/UB from a basis assignment
AdHocDiffractometer— thebasisconstructor argument