diagnostics.checks#

Individual diagnostic checks.

Each check is a small function that reads an Optic and returns zero or more Diagnostic findings. Checks never mutate the Optic they inspect and never call back into it beyond reading its public attributes — the optiland.diagnostics subpackage depends on optiland.optic, never the other way around.

To add a new check: write a function matching SystemCheck and append it to CHECKS. Nothing else needs to change (open/closed).

Kramer Harrison, 2026

Functions

check_no_aperture(lens)

OPT003: no aperture is defined.

check_no_fields(lens)

OPT006: no fields are defined.

check_no_primary_wavelength(lens)

OPT002: wavelengths exist, but none is marked primary.

check_no_rays_reach_image(lens)

OPT012: a probe trace shows no rays reaching the image surface.

check_no_stop_surface(lens)

OPT004: no surface is marked as the aperture stop.

check_no_wavelengths(lens)

OPT001: no wavelengths are defined.

check_non_finite_interior_thickness(lens)

OPT008: an interior surface has a non-finite thickness or NaN radius.

check_non_positive_thickness(lens)

OPT010: a thickness has an unexpected sign, or is exactly zero.

check_object_surface_not_first(lens)

OPT007: the object surface is not at index 0.

check_stop_at_object_or_image(lens)

OPT011: the stop surface is the object or image surface.

check_too_few_surfaces(lens)

OPT005: fewer than 2 surfaces, so there is no object/image pair.

check_wavelength_outside_material_range(lens)

OPT009: a wavelength falls outside a material's dispersion data range.

check_no_aperture(lens: Optic) list[Diagnostic][source]#

OPT003: no aperture is defined.

check_no_fields(lens: Optic) list[Diagnostic][source]#

OPT006: no fields are defined.

check_no_primary_wavelength(lens: Optic) list[Diagnostic][source]#

OPT002: wavelengths exist, but none is marked primary.

check_no_rays_reach_image(lens: Optic) list[Diagnostic][source]#

OPT012: a probe trace shows no rays reaching the image surface.

Only runs once the system is complete enough to trace: it needs wavelengths, a primary wavelength, an aperture, a stop, at least two surfaces, and at least one field. Any check failure above already reports the root cause, so this is skipped rather than duplicated.

check_no_stop_surface(lens: Optic) list[Diagnostic][source]#

OPT004: no surface is marked as the aperture stop.

check_no_wavelengths(lens: Optic) list[Diagnostic][source]#

OPT001: no wavelengths are defined.

check_non_finite_interior_thickness(lens: Optic) list[Diagnostic][source]#

OPT008: an interior surface has a non-finite thickness or NaN radius.

check_non_positive_thickness(lens: Optic) list[Diagnostic][source]#

OPT010: a thickness has an unexpected sign, or is exactly zero.

A reflective surface (a mirror) flips the sign of every thickness that follows it, since propagation now runs the other way along z — see the “Sign Conventions” section of the conventions doc. The expected sign is therefore tracked by the parity of the number of reflective surfaces seen so far (including the current one), not assumed to always be positive; a two-mirror system like a Cassegrain returns to positive thicknesses after its second mirror.

check_object_surface_not_first(lens: Optic) list[Diagnostic][source]#

OPT007: the object surface is not at index 0.

check_stop_at_object_or_image(lens: Optic) list[Diagnostic][source]#

OPT011: the stop surface is the object or image surface.

check_too_few_surfaces(lens: Optic) list[Diagnostic][source]#

OPT005: fewer than 2 surfaces, so there is no object/image pair.

check_wavelength_outside_material_range(lens: Optic) list[Diagnostic][source]#

OPT009: a wavelength falls outside a material’s dispersion data range.