Optics

Optical calculations for reflections and refractions.

Optical calculations for eye tracking simulations.

Exports modules for light reflection and refraction physics, supporting ray tracing and pupil/corneal imaging.

Reflections

Light reflection calculation utilities for eye tracking simulation.

Implements geometric and optimization-based methods for finding glint positions on spherical and conic surfaces.

pyetsimul.optics.reflections.find_reflection_sphere(light_pos, camera_pos, sphere_center, sphere_radius)[source]

Find reflection point on sphere surface.

Uses optimization to find point where light ray reflects to camera position. Implements reflection law using numerical root finding.

Parameters:
  • light_pos (Position3D) – Light source position

  • camera_pos (Position3D) – Camera position

  • sphere_center (Position3D) – Sphere center position

  • sphere_radius (float) – Sphere radius

Return type:

Point3D | None

Returns:

Position of glint on sphere surface, or None if no reflection found

pyetsimul.optics.reflections.find_reflection_conic(light_pos, camera_pos, conic_center, radius, conic_constant)[source]

Find reflection point on conic surface.

Uses 2D root-finding to find the point where light ray reflects to camera. The search is parameterized by (alpha, beta) where alpha interpolates between light and camera directions and beta adds an out-of-plane component, necessary for aspherical surfaces where the reflection point may not lie in the light-center-camera plane.

Parameters:
  • light_pos (Position3D) – Light source position

  • camera_pos (Position3D) – Camera position

  • conic_center (Position3D) – Conic center position (typically corneal apex)

  • radius (float) – Radius of curvature at apex (mm)

  • conic_constant (float) – Conic constant (k < 0 for prolate, k = 0 for sphere, k > 0 for oblate)

Return type:

Point3D | None

Returns:

Position of glint on conic surface, or None if no reflection found

pyetsimul.optics.reflections.reflect_ray_circle(ray, circle_center, circle_radius)[source]

Reflect ray off circle surface.

Finds intersection point and computes reflected ray direction using reflection law. Uses 2D circle geometry in x,y plane for surface normal calculation.

Parameters:
  • ray (Ray) – Input ray with origin and direction

  • circle_center (Point3D) – Circle center (2D using x,y components)

  • circle_radius (float) – Circle radius

Return type:

tuple[IntersectionResult | None, Ray | None]

Returns:

Tuple of (intersection_result, reflected_ray) where intersection_result contains the intersection point and reflected_ray is the reflected ray. Returns (None, None) if no intersection.

pyetsimul.optics.reflections.reflect_ray_sphere(ray, sphere_center, sphere_radius)[source]

Reflect ray off sphere surface.

Finds intersection point and computes reflected ray direction using reflection law. Uses outward-pointing surface normal for proper reflection calculation.

Parameters:
  • ray (Ray) – Input ray with origin and direction

  • sphere_center (Position3D) – Sphere center position

  • sphere_radius (float) – Sphere radius

Return type:

tuple[IntersectionResult | None, Ray | None]

Returns:

Tuple of (intersection_result, reflected_ray) where intersection_result contains the intersection point and reflected_ray is the reflected ray. Returns (None, None) if no intersection.

pyetsimul.optics.reflections.reflect_ray_conic(ray, conic_center, radius, conic_constant)[source]

Reflect ray off conic surface.

Finds intersection point and computes reflected ray direction using reflection law. Uses proper conic surface normal calculation for accurate reflection.

Parameters:
  • ray (Ray) – Input ray with origin and direction

  • conic_center (Position3D) – Conic center position (typically corneal apex)

  • radius (float) – Radius parameter (R in the formula, mm)

  • conic_constant (float) – Conic constant (k < 0 for prolate, k = 0 for sphere, k > 0 for oblate)

Returns:

  • intersection_result: Contains intersection point on conic surface

  • reflected_ray: Reflected ray

Returns (None, None) if no intersection.

Return type:

Tuple of (intersection_result, reflected_ray) where

pyetsimul.optics.reflections.find_corneal_reflection(eye, light, camera)[source]

Finds the position of a corneal reflex.

Determines the point on corneal surface where light ray reflects to camera. Uses exact reflection calculation with corneal surface geometry.

Parameters:
  • eye (Eye) – Eye object

  • light (Light) – Light source object

  • camera (Camera) – Camera object

Return type:

Position3D | None

Returns:

Position3D of corneal reflex, or None if not within cornea

pyetsimul.optics.reflections.find_corneal_reflection_simple(eye, light, camera)[source]

Finds the position of a corneal reflex (simplified).

Uses paraxial approximation for faster corneal reflex calculation. Based on Morimoto, Amir and Flicker approximation method.

Parameters:
  • eye (Eye) – Eye object

  • light (Light) – Light source object

  • camera (Camera) – Camera object

Return type:

Position3D | None

Returns:

Position3D of corneal reflex, or None if not found

Refractions

Light refraction calculation utilities for eye tracking simulation.

Implements Snell’s law, ray-surface intersection, and optimization for refraction on spherical and conic surfaces.

pyetsimul.optics.refractions.find_refraction_sphere(camera_pos, object_pos, sphere_center, sphere_radius, n_outside, n_sphere)[source]

Find refraction point on sphere surface.

Uses optimization to find point where object ray refracts to camera position. Implements Snell’s law using numerical root finding.

Parameters:
  • camera_pos (Position3D) – Camera/observer position

  • object_pos (Position3D) – Object position inside sphere

  • sphere_center (Position3D) – Sphere center position

  • sphere_radius (float) – Sphere radius

  • n_outside (float) – Refractive index outside sphere

  • n_sphere (float) – Refractive index of sphere

Return type:

Point3D | None

Returns:

Position on sphere surface where refraction occurs, or None if not found.

pyetsimul.optics.refractions.find_refraction_conic(camera_pos, object_pos, conic_center, radius, conic_constant, n_outside, n_conic)[source]

Find refraction point on conic surface.

Uses a two-stage approach to find the point where an object ray refracts toward the camera through the conic surface:

Stage 1 (brentq): Solve the 1D in-plane Snell’s law residual with beta=0. The Snell residual is monotonic and sign-changing in alpha ∈ [0, 1], so brentq is guaranteed to find the unique correct root. This works directly on the conic surface — no spherical approximation needed.

Stage 2 (fsolve): Starting from (alpha_brentq, 0), refine with the full 2D system (Snell + coplanarity) to find the small out-of-plane beta correction needed for aspherical surfaces (k != 0).

This approach works for any conic constant k because Stage 1 is bounded (no wrong roots) and Stage 2 starts very close to the solution (won’t drift).

Parameters:
  • camera_pos (Position3D) – Camera/observer position

  • object_pos (Position3D) – Object position inside conic

  • conic_center (Position3D) – Conic center position (typically corneal apex)

  • radius (float) – Radius of curvature at apex (mm)

  • conic_constant (float) – Conic constant (k < 0 for prolate, k = 0 for sphere, k > 0 for oblate)

  • n_outside (float) – Refractive index outside conic

  • n_conic (float) – Refractive index of conic

Return type:

Point3D | None

Returns:

Position on conic surface where refraction occurs, or None if not found.

pyetsimul.optics.refractions.refract_ray_sphere(ray, sphere_center, sphere_radius, n_outside, n_sphere)[source]

Refract ray through sphere surface.

Finds intersection point and computes refracted ray direction using Snell’s law. Handles total internal reflection when critical angle is exceeded.

Parameters:
  • ray (Ray) – Input ray with origin and direction

  • sphere_center (Position3D) – Sphere center position

  • sphere_radius (float) – Sphere radius

  • n_outside (float) – Refractive index outside sphere

  • n_sphere (float) – Refractive index of sphere

Return type:

tuple[IntersectionResult | None, Ray | None]

Returns:

Tuple of (intersection_result, refracted_ray) where intersection_result contains the intersection point and refracted_ray is the refracted ray. Returns (None, None) if no intersection or total internal reflection.

pyetsimul.optics.refractions.refract_ray_conic(ray, conic_center, radius, conic_constant, n_outside, n_conic)[source]

Refract ray through conic surface.

Finds intersection point and computes refracted ray direction using Snell’s law. Uses proper conic surface normal calculation for accurate refraction. Handles total internal reflection when critical angle is exceeded.

Parameters:
  • ray (Ray) – Input ray with origin and direction

  • conic_center (Position3D) – Conic center position (typically corneal apex)

  • radius (float) – Radius parameter (R in the formula, mm)

  • conic_constant (float) – Conic constant (k < 0 for prolate, k = 0 for sphere, k > 0 for oblate)

  • n_outside (float) – Refractive index outside conic (e.g., air = 1.0)

  • n_conic (float) – Refractive index of conic (e.g., cornea = 1.376)

Returns:

  • intersection_result: Contains intersection point on conic surface

  • refracted_ray: Refracted ray

Returns (None, None) if no intersection or total internal reflection.

Return type:

Tuple of (intersection_result, refracted_ray) where

pyetsimul.optics.refractions.refract_ray_dual_surface(eye, ray_origin, ray_direction)[source]

Computes refraction through both anterior and posterior corneal surfaces.

Models complete corneal optical path by calculating refraction at both: 1. Anterior surface: air (n=1.0) → cornea (n=1.376) 2. Posterior surface: cornea (n=1.376) → aqueous humor (n=1.336)

This provides more accurate modeling of light rays passing through the cornea compared to single-surface refraction which only considers the anterior surface.

Parameters:
  • eye (Eye) – Eye object containing corneal geometry and refractive indices

  • ray_origin (Point3D) – Ray origin (Position3D)

  • ray_direction (Direction3D) – Ray direction (3D vector)

Returns:

  • anterior_point: Point where ray strikes anterior corneal surface

  • posterior_point: Point where ray strikes posterior corneal surface

  • final_direction: Direction of ray after exiting posterior surface

Returns (None, None, None) if ray doesn’t intersect with cornea.

Return type:

Tuple of (anterior_point, posterior_point, final_direction) where

pyetsimul.optics.refractions.find_refraction_point(cornea, eye_transform, camera_position, object_position)[source]

Computes observed position of intraocular objects through corneal refraction.

Pure function that calculates where camera observes intraocular object through corneal refraction. Determines corneal surface point where object ray refracts to camera.

Note: This function does not check corneal boundaries - that should be done by the caller if needed (e.g., using Eye.point_within_cornea()).

Parameters:
  • cornea (Cornea) – Cornea object with find_refraction method

  • eye_transform (TransformationMatrix) – Eye transformation matrix

  • camera_position (Position3D) – Camera position (Position3D)

  • object_position (Position3D) – Object position inside eye (Position3D)

Return type:

Position3D | None

Returns:

Position3D on corneal surface where refraction occurs, or None if no solution exists

Pupil Imaging

Pupil imaging functions extracted from the Eye class.

This module contains pupil imaging operations that were previously part of the Eye class, extracted for better modularity and testability.

pyetsimul.optics.pupil_imaging.get_pupil_boundary_image(eye, camera, use_refraction=True)[source]

Computes image of pupil boundary.

Projects pupil boundary to camera image with corneal refraction. Accounts for camera error and visibility constraints.

Parameters:
  • eye (Eye) – Eye object

  • camera (Camera) – Camera object

  • use_refraction (bool) – Whether to apply corneal refraction (default True)

Return type:

PupilData

Returns:

PupilData object with boundary points in camera image

pyetsimul.optics.pupil_imaging.get_pupil_ellipse_image(eye, camera, use_refraction=True)[source]

Determines pupil ellipse in camera image.

Fits ellipse to pupil boundary points to find center. Uses least-squares ellipse fitting for robust center estimation.

Parameters:
  • eye (Eye) – Eye object

  • camera (Camera) – Camera object

  • use_refraction (bool) – Whether to use refraction model (default True)

Return type:

PupilData

Returns:

PupilData object containing boundary points and ellipse center

pyetsimul.optics.pupil_imaging.get_pupil_center_mass_image(eye, camera, use_refraction=True)[source]

Determines pupil center using center of mass calculation.

Creates binary mask from boundary points and calculates centroid. Provides alternative to ellipse fitting for center estimation.

Parameters:
  • eye (Eye) – Eye object

  • camera (Camera) – Camera object

  • use_refraction (bool) – Whether to use refraction model (default True)

Return type:

PupilData

Returns:

PupilData object containing boundary points and center of mass

pyetsimul.optics.pupil_imaging.calculate_pupil_center_from_boundary(boundary_points, camera_resolution, center_method='ellipse')[source]

Calculate pupil center from boundary points using specified method.

Parameters:
  • boundary_points (list[Point2D]) – List of Point2D boundary points in image coordinates

  • camera_resolution (Point2D) – Camera resolution as Point2D

  • center_method (str) – Method to use for center detection (“ellipse” or “center_of_mass”)

Return type:

Point2D | None

Returns:

Point2D with pupil center coordinates, or None if calculation fails

Raises:

ValueError – If center_method is not recognized

pyetsimul.optics.pupil_imaging.calculate_pupil_center_methods(eye, camera, use_refraction=True, center_method='ellipse')[source]

Gets pupil boundary and center in camera image using specified method.

Provides unified interface for different pupil center detection methods. Supports ellipse fitting and center of mass calculations.

Parameters:
  • eye (Eye) – Eye object

  • camera (Camera) – Camera object

  • use_refraction (bool) – Whether to use refraction model (default True)

  • center_method (str) – Method to use for pupil center detection (default “ellipse”) Options: “ellipse”, “center_of_mass”

Return type:

PupilData

Returns:

PupilData object containing boundary points and center using specified method

Raises:

ValueError – If center_method is not recognized