Analysis#

lauelab.analysis contains orientation, projection, coloring, and reflection-simulation functions. The functions accept NumPy-compatible arrays and return NumPy arrays or package data classes.

Reciprocal and orientation conventions#

See the results guide for the reciprocal-basis convention. lattice_params_to_reciprocal() takes cell lengths in nm and angles in degrees.

An orientation matrix maps vectors from the reference crystal basis to the measured basis. reciprocal_to_orientation() calculates that matrix as measured.T @ inv(reference.T). crystal_direction() applies the inverse orientation to a laboratory-frame direction.

Rotation matrices have shape (3, 3) and are dimensionless. Rodrigues vectors use the dimensionless $\hat{a}\tan(\theta/2)$ convention. At the 180-degree singularity, orientation_to_rodrigues() clamps the effective angle to $\pi - 10^{-7}$ radians while retaining a deterministic rotation axis. Misorientation angles use degrees.

Lattice and orientation#

lauelab.analysis.CUBIC_SYMMETRY: numpy.ndarray#

Cubic proper rotations with shape (24, 3, 3).

lauelab.analysis.HEXAGONAL_SYMMETRY: numpy.ndarray#

Hexagonal proper rotations with shape (12, 3, 3).

lauelab.analysis.lattice_params_to_reciprocal(a, b, c, alpha_deg, beta_deg, gamma_deg, *, space_group=None)[source]#

Return the native reciprocal basis as rows in inverse input-length units.

a, b, and c must use one common length unit; the returned basis uses its inverse (normally 1/nm in the public analysis API). Angles are in degrees, and reciprocal vectors include the 2*pi factor.

The direct basis follows native setDirectRecip: c is parallel to positive z, b lies in the yz plane, and a completes a right-handed basis. When space_group is provided, native crystal-system constraints are applied before constructing the basis. For a trigonal space group, angles within the native tolerance of (90, 90, 120) select hexagonal axes; all other angles select rhombohedral axes.

lauelab.analysis.reciprocal_to_orientation(reciprocal, reference_reciprocal)[source]#

Return the orientation matrix for measured and reference lattices.

lauelab.analysis.orientation_to_rodrigues(rotation)[source]#

Convert a 3 by 3 rotation matrix to axis * tan(angle / 2).

The Rodrigues magnitude is singular at 180 degrees. Near that singularity, the axis is recovered from the rotation eigenvectors and the effective angle is clamped to pi - 1e-7 radians, with the first nonzero axis component chosen positive. Unlike the Laue Portal’s zero-vector fallback, this retains a deterministic axis and decodes to approximately 180 degrees.

lauelab.analysis.crystal_direction(rotation, lab_direction)[source]#

Express a lab-frame direction in crystal coordinates.

lauelab.analysis.symmetry_operations(symmetry)[source]#

Return proper rotations for a supported symmetry name or space group.

lauelab.analysis.symmetry_reduce_orientation(rotation, *, operations=None)[source]#

Return the symmetry-equivalent orientation nearest to identity.

lauelab.analysis.misorientation_matrix(rotation_a, rotation_b, *, operations=None)[source]#

Return the minimum-angle misorientation from rotation_b to rotation_a.

lauelab.analysis.misorientation_angle(rotation_a, rotation_b, *, operations=None)[source]#

Return the minimum misorientation angle in degrees.

lauelab.analysis.misorientation_from_reference(rotations, reference_index, *, operations=None)[source]#

Return Rodrigues vectors and angles relative to one orientation.

lauelab.analysis.pairwise_misorientation(rotations, *, indices=None, operations=None)[source]#

Return pairs and corresponding misorientation angles.

The symmetry constants and arrays returned by symmetry_operations() contain proper rotation matrices. Cubic space groups are 195 through 230. Hexagonal space groups are 168 through 194.

Pole projection#

class lauelab.analysis.SurfaceFrame(tilt, roll, normal, name=None)[source]

Right-handed orthonormal sample-surface coordinate frame.

classmethod from_vectors(*, tilt, roll, normal, name=None)[source]

Construct and normalize a frame from three vectors.

classmethod aps_34ide(name='normal')[source]

Return a named APS 34-ID-E surface frame.

lauelab.analysis.cubic_hkl_family(hkl)[source]#

Return normalized symmetry-equivalent directions for a cubic HKL.

lauelab.analysis.pole_figure_points(recip_lattices, hkl_family, *, surface=None)[source]#

Project reciprocal-lattice pole directions onto a surface frame.

lauelab.analysis.pole_color_radius(center, angle_deg)[source]#

Convert an angular color radius to a stereographic radius.

Pole-figure points have shape (n, 2) and use dimensionless stereographic coordinates. Angular inputs use degrees. SurfaceFrame vectors are dimensionless laboratory-frame directions.

Coloring#

lauelab.analysis.cubic_ipf_colors(directions)[source]#

Map crystal directions to cubic IPF RGB values in [0, 1].

lauelab.analysis.rodrigues_colors(vectors, *, max_angle_deg=None)[source]#

Map Rodrigues vectors to RGB values in [0, 1].

lauelab.analysis.hsv_position_colors(dx, dy, *, radius=1.0)[source]#

Map Cartesian offsets to an HSV wheel with white at its center.

lauelab.analysis.closest_pole_colors(points, pattern_indices, count, *, center=(0.0, 0.0), radius=1.0)[source]#

Return each pattern’s HSV color from its closest projected pole.

lauelab.analysis.cubic_ipf_key(resolution=256)[source]#

Return a cubic IPF reference triangle as a uint8 RGBA image.

lauelab.analysis.hsv_key(resolution=256)[source]#

Return a circular HSV reference key as a uint8 RGBA image.

Color functions return RGB values in [0, 1] unless the function returns a reference image. Reference images have shape (height, width, 4), dtype numpy.uint8, and RGBA channel order. Angular color limits use degrees.

Reflection simulation#

class lauelab.analysis.SimulationResult(hkl, q, detector_xy, energy_kev, relative_intensity)[source]

Immutable, aligned output from one detector reflection simulation.

Parameters:
  • hkl (numpy.ndarray) – Integer Miller indices with shape (n, 3).

  • q (numpy.ndarray) – Reciprocal vectors in 1/nm with shape (n, 3).

  • detector_xy (numpy.ndarray) – Zero-based, unbinned full-detector (x, y) pixels with shape (n, 2).

  • energy_kev (numpy.ndarray) – Photon energies in keV with shape (n,).

  • relative_intensity (numpy.ndarray) – Uncalibrated JZT-derived relative intensities with shape (n,).

Notes

All arrays are copied, normalized to 64-bit dtypes, and made read-only. Rows retain the deterministic order produced by simulate_reflections().

missing_from(indexed_hkl)[source]

Return simulated directions absent from indexed Miller indices.

Positive scalar harmonics share a direction. Opposite signed Miller indices remain distinct Friedel directions.

Parameters:

indexed_hkl (numpy.ndarray) – Integer Miller indices with shape (m, 3). A one-dimensional empty integer array is also accepted.

Returns:

SimulationResult – A new immutable result. Its rows retain their original order.

Raises:
  • TypeError – If indexed_hkl does not have an integer dtype.

  • ValueError – If indexed_hkl has the wrong shape or contains (0, 0, 0).

Return type:

SimulationResult

lauelab.analysis.simulate_reflections(crystal, reciprocal, detector, *, energy_range_kev=(6.0, 30.0), depth=0.0)[source]

Simulate a complete, deterministic on-detector reflection pattern.

reciprocal contains reciprocal basis vectors as rows in 1/nm. Energy bounds are inclusive, and depth is measured in micrometres. One strongest-intensity representative is retained per signed primitive harmonic direction. Equal intensities prefer lower energy and then lexicographically smaller HKL; final rows use the same tie-breakers after descending intensity. Floating sort keys are compared to 12 significant digits so numerical noise in symmetry-equivalent calculations reaches the integer HKL tie-breaker.

Parameters:
  • crystal (Crystal) – Package crystal description. The crystal must contain at least one atom site. Atom identity, fractional position, and occupancy enter the structure-factor calculation.

  • reciprocal (numpy.ndarray) – Finite, nonsingular reciprocal matrix with shape (3, 3). Basis vectors occupy rows in 1/nm. For Miller index row hkl, the returned reciprocal vector is hkl @ reciprocal.

  • detector (DetectorGeometry) – Metadata for one physical detector slot. Simulation uses its unbinned dimensions, physical size, translation, and rotation.

  • energy_range_kev (tuple[float, float]) – Two finite, positive, increasing energy bounds in keV. Both bounds are inclusive. The default is (6.0, 30.0).

  • depth (float) – Finite sample depth in micrometres. The default is 0.0.

Returns:

SimulationResult – Complete direction-distinct reflections that intersect the selected detector within the requested energy interval. A valid simulation with no accepted reflections returns aligned empty arrays.

Raises:
  • TypeError – If a package-owned object or numeric input has an unsupported type.

  • ValueError – If a scientific input is malformed, non-finite, or otherwise invalid.

  • RuntimeError – If the private simulation backend cannot load, execute, return valid numerical output, or complete within its private candidate limit.

Return type:

SimulationResult

Simulation uses reciprocal rows in 1/nm, photon energy in keV, sample depth in micrometres, and zero-based full-detector coordinates (x, y). See the reflection simulation reference and Simulate detector reflections for a complete workflow.