optiland.rays.ray_aiming.parameterization#

Local launch parameterization for iterative ray aiming.

The Newton/Broyden aiming core drives exactly two scalar parameters per ray. Historically those were global launch (x, y) for infinite conjugates and global direction (L, M) (with N held fixed) for finite ones – both of which silently assume the beam enters along global +z. For a system entered along any other direction one of those parameters points along the beam (a vanishing Jacobian column), and varying L, M at fixed N neither preserves the unit norm nor spans the transverse plane.

LaunchParameterization replaces both with two true transverse degrees of freedom (xi, eta):

  • infinite conjugate: the launch point moves in the entry-frame transverse plane, r(xi, eta) = r_seed + xi * u + eta * v, while the field direction stays fixed;

  • finite conjugate: the object point stays fixed and the direction rotates in a per-ray orthonormal tangent basis around the seed direction, k(xi, eta) = normalize(k_seed + xi * e1 + eta * e2) with e1, e2 perpendicular to k_seed, so every trial and line-search candidate is a unit direction by construction.

For the canonical +z entry the infinite-conjugate map reduces exactly to the historical (x, y) offsets (u = +x, v = +y).

The bases are stored as plain Python floats. Ray aiming is an iterative solve whose result is polished against real traces, so it never carries gradient information (same design as pupil_map.py).

Kramer Harrison, 2026

Classes

BoundLaunch(param, x, y, z, L, M, N)

A LaunchParameterization bound to per-ray seed states.

LaunchParameterization(is_infinite, u, v)

Two-parameter transverse launch model in the entry frame.

SolveReport(seed_residual, final_residual, ...)

Outcome of one Newton/Broyden aiming solve.

class BoundLaunch(param: LaunchParameterization, x, y, z, L, M, N)[source]#

A LaunchParameterization bound to per-ray seed states.

launch(0, 0) reproduces the seeds exactly. For finite conjugates the per-ray tangent basis (e1, e2) is built perpendicular to each seed direction; the basis is refreshed by re-binding whenever the seeds change meaningfully (each solve binds once).

launch(xi, eta) tuple[source]#

Physical launch states (x, y, z, L, M, N) for parameters.

Infinite conjugate: seed positions displaced by xi*u + eta*v (fixed directions). Finite conjugate: seed positions kept, unit directions normalize(k0 + xi*e1 + eta*e2).

project(x, y, z, L, M, N) tuple[source]#

Inverse map: parameters (xi, eta) of a physical launch state.

Exact inverse of launch() (used for warm starts from cached or previously solved launches). For finite conjugates the identity xi = (k . e1) / (k . k0) inverts the normalized tangent update.

class LaunchParameterization(is_infinite: bool, u: tuple[float, float, float], v: tuple[float, float, float])[source]#

Two-parameter transverse launch model in the entry frame.

Variables:
  • is_infinite (bool) – Whether the object is at infinity (position DOF) or finite (direction DOF).

  • u (tuple[float, float, float]) – First entry-frame transverse basis vector (unit, floats).

  • v (tuple[float, float, float]) – Second entry-frame transverse basis vector (unit, floats).

bind(x, y, z, L, M, N) BoundLaunch[source]#

Bind per-ray seed launch states, yielding a (xi, eta) map.

classmethod for_optic(optic: Optic, is_infinite: bool) LaunchParameterization[source]#

Build the parameterization from the optic’s entry frame.

is_infinite: bool#
u: tuple[float, float, float]#
v: tuple[float, float, float]#
class SolveReport(seed_residual: float, final_residual: float, converged: bool, iterations: int, num_rays: int, num_converged: int, fallback_used: bool = False, jacobian_refreshes: int = 0)[source]#

Outcome of one Newton/Broyden aiming solve.

A returned finite ray is not evidence of convergence; consult this report. Residuals are max-abs stop-plane errors in the stop surface’s local transverse coordinates (mm).

Variables:
  • seed_residual (float) – Residual of the initial (seed) launch.

  • final_residual (float) – Residual of the returned launch.

  • converged (bool) – Whether every ray met the solver tolerance.

  • iterations (int) – Newton/Broyden iterations executed.

  • num_rays (int) – Number of rays in the solve.

  • num_converged (int) – Number of rays that met tolerance.

  • fallback_used (bool) – True when the Newton core substituted the sign-preserving paraxial diagonal for at least one ray’s Jacobian – at initialization because the central finite difference was unusable (a perturbed ray missed a surface), or during iteration because a refreshed finite-difference Jacobian remained ill-conditioned. Populated by _solve_core from the actual conditioning path taken.

  • jacobian_refreshes (int) – Number of iteration-time central-difference Jacobian refreshes triggered by an ill-conditioned (round-off level reciprocal-condition) Newton solve.

converged: bool#
fallback_used: bool = False#
final_residual: float#
iterations: int#
jacobian_refreshes: int = 0#
num_converged: int#
num_rays: int#
seed_residual: float#