optiland.rays.ray_aiming.pupil_map#
Pupil Map Module
This module implements the per-field affine launch model used by the
chief-ray calibrated robust ray aimer (see robust.py), together with a
warm-start cache keyed by (Hx, Hy, wavelength).
The pupil map is a cheap seed generator only: it is exact at the chief ray
and four cardinal edge probes, and a good linear approximation elsewhere.
The final Newton/Broyden polish (in iterative.py) makes every ray exact,
so the map never needs to carry gradient information – it is stored as
plain Python floats, which are inherently detached from any autograd graph.
Kramer Harrison, 2026
Functions
|
Extract a plain Python float from a scalar or length-1 backend array. |
Classes
|
Per-field affine launch model in local transverse coordinates. |
|
Warm-start cache of |
- class PupilMap(base: tuple[float, float, float, float, float, float], A: tuple[tuple[float, float], tuple[float, float]], param: LaunchParameterization)[source]#
Per-field affine launch model in local transverse coordinates.
seed(Px, Py)evaluates(xi, eta) = A @ [Px, Py]and maps the result through the chief ray’s boundLaunchParameterization: for infinite conjugates the launch point moves in the entry-frame transverse plane around the chief launch (fixed field direction); for finite conjugates the object point is fixed and the direction rotates in the tangent basis around the chief direction, staying unit-norm. The stored coordinates are local transverse offsets, never global(x, y)– a system entered off the z axis seeds correctly.- Variables:
base – Chief launch state
(x, y, z, L, M, N)as plain floats.A – Affine matrix
((a11, a12), (a21, a22))mapping normalized pupil coordinates to(xi, eta).param – The launch parameterization (entry-frame basis, conjugate mode) the offsets are expressed in.
- A#
- base#
- param#
- class PupilMapCache(precision: int = 6)[source]#
Warm-start cache of
PupilMap, keyed by(Hx, Hy, wavelength).The cache is never cleared on a system change. Instead, a lightweight fingerprint of the aiming-relevant system state is tracked per entry: a cache hit is only “fresh” (reusable without recomputation) if the fingerprint at store time still matches the current one. A stale or missing entry is always still usable as a warm-start seed for a fresh calibration – correctness never depends on the cache, only speed.
- fingerprint(optic: Optic) Any[source]#
Compute a lightweight hash of aiming-relevant system state.
Only surfaces up to and including the stop matter for aiming, so post-stop surfaces (and unrelated optic metadata) are excluded to keep this cheap enough to call on every aiming request.
- get_fresh(Hx: float, Hy: float, wl: float) PupilMap | None[source]#
Return the cached map only if the system hasn’t changed since it was stored – an exact-reuse hit that skips recalibration entirely.
- get_stale(Hx: float, Hy: float, wl: float) PupilMap | None[source]#
Return the map for this exact key regardless of freshness.