Core

Core components of the eye tracking simulation.

Eye

Main eye model for eye tracking simulation.

Defines the Eye class, integrating cornea, pupil, fovea displacement, and gaze mechanics for simulation and analysis.

class pyetsimul.core.eye.Eye(cornea=<factory>, fovea_displacement=True, fovea_alpha_deg=6.0, fovea_beta_deg=2.0, pupil_type='elliptical', pupil_boundary_points=None, pupil_random_seed=None, realistic_pupil_params=None, eyelid_enabled=False, decentration_config=<factory>)[source]

Bases: object

Eye model for eye tracking simulation.

Implements spherical eye model with optical axis along negative z-axis. Includes cornea, pupil, fovea displacement, and Listing’s law mechanics. Based on Böhme et al. 2008 with nodal point at cornea center.

Eye Model Components: - Cornea: Spherical surface with configurable radius and refractive index - Pupil: Elliptical aperture with configurable size and position - Fovea displacement: Visual axis offset from optical axis - Listing’s law: Eye rotation mechanics for realistic torsion

Parameters:
cornea: SphericalCornea | ConicCornea
fovea_displacement: bool = True
fovea_alpha_deg: float = 6.0
fovea_beta_deg: float = 2.0
pupil_type: str = 'elliptical'
pupil_boundary_points: int | None = None
pupil_random_seed: int | None = None
realistic_pupil_params: RealisticPupilParams | None = None
eyelid_enabled: bool = False
decentration_config: PupilDecentrationConfig
trans: TransformationMatrix
eyelid_trans: TransformationMatrix
axial_length: float
n_aqueous_humor: float
pupil: Pupil
eyelid: Eyelid | None = None
property orientation: RotationMatrix

Get/set the eye’s current orientation (3x3 rotation matrix).

set_rest_orientation(value)[source]

Set the rest orientation and initialize current orientation to match.

Establishes reference orientation for eye rotation calculations. Validates right-handed rotation matrix with determinant = +1.

Parameters:

value (RotationMatrix) – 3x3 rotation matrix (must be right-handed with determinant = +1)

Raises:

ValueError – If the matrix is not right-handed (det ≠ +1)

Return type:

None

property rest_orientation: RotationMatrix

Get the rest orientation (read-only).

Returns reference orientation for eye rotation calculations.

property current_target_point: Position3D | None

Get the current target point (read-only).

Returns the target position that was last used with look_at(), or None if the eye has not been oriented toward any target yet.

set_rest_orientation_at_target(target_position)[source]

Set rest orientation so the VISUAL axis points to the target.

Aligns the eye-local visual axis (derived from fovea angles when enabled, or equals the optical axis when disabled) with the world-space direction from eye position to target. Keeps +Y approximately aligned with world up.

Return type:

None

Parameters:

target_position (Position3D)

property position: Position3D

Get/set the eye’s position in world coordinates.

point_within_cornea(p)[source]

Check if a point lies within the corneal boundaries.

Transforms point to eye coordinates and validates against corneal geometry.

Parameters:

p (Position3D) – Point to test

Return type:

bool

Returns:

True if point lies within cornea boundaries

find_cr(light, camera)[source]

Finds the position of a corneal reflex.

Delegates to reflections module for corneal reflection calculation.

Parameters:
  • light (Light) – Light source object

  • camera (Camera) – Camera object

Return type:

Position3D | None

Returns:

Position of corneal reflex, or None if not within cornea

look_at(target_position, legacy=False)[source]

Rotates an eye to look at a given position in space.

Delegates to eye_operations module for gaze control. Updates current_target_point to track the target position.

Parameters:
  • target_position (Position3D) – Position in world coordinates to look at

  • legacy (bool) – If True, uses optical-then-kappa method for backward compatibility

Return type:

None

get_pupil()[source]

Get pupil boundary points in world coordinates.

Retrieves boundary points from pupil object and transforms to world coordinates.

Return type:

PupilData

Returns:

PupilData object with boundary_points attribute set

get_pupil_position()[source]

Get pupil center position.

Calculates pupil position based on corneal apex and depth.

Return type:

Position3D

Returns:

Pupil center position

get_pupil_radii()[source]

Get current pupil radii.

Delegates to pupil object for radius information.

Return type:

tuple[float, float]

Returns:

Tuple of (x_radius, y_radius) in mm

get_pupil_diameter()[source]

Get current pupil diameter.

Delegates to pupil object for diameter information.

Return type:

float

Returns:

Pupil diameter in mm

set_pupil_radii(x_radius, y_radius)[source]

Set pupil radii and update decentration if enabled.

Delegates to pupil object for radius modification, then applies decentration based on the new average diameter if decentration is enabled.

Parameters:
  • x_radius (float) – Pupil radius in X direction (mm)

  • y_radius (float) – Pupil radius in Y direction (mm)

Return type:

None

set_pupil_diameter(diameter)[source]

Set pupil diameter and update decentration if enabled.

Delegates to pupil object for diameter modification, then applies decentration based on the new diameter if decentration is enabled.

Parameters:

diameter (float) – Pupil diameter in mm

Return type:

None

move_pupil_position(dx, dy, dz)[source]

Move pupil position by given offset.

Parameters:
  • dx (float) – X offset in mm

  • dy (float) – Y offset in mm

  • dz (float) – Z offset in mm

Return type:

None

set_pupil_position(x, y, z)[source]

Set pupil position to absolute coordinates.

Parameters:
  • x (float) – Absolute X position in mm

  • y (float) – Absolute Y position in mm

  • z (float) – Absolute Z position in mm

Return type:

None

get_pupil_center_in_world()[source]

Get pupil center in world coordinates.

Delegates to pupil object for world coordinate transformation.

Return type:

Position3D

Returns:

Pupil center position in world coordinates

find_refracted_position(camera_position, object_position)[source]

Find where an intraocular object appears due to corneal refraction.

Calculates where camera observes intraocular object through corneal refraction, including boundary checking to ensure the refraction point lies within the cornea.

Parameters:
  • 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 valid solution

point_within_eyelid(p)[source]

Check if a point lies on eyelid skin (not the opening).

Transforms the point to canonical eye coordinates (undo rest orientation) so that the eyelid remains fixed to the face regardless of eye rotation. Returns False if eyelid is not enabled or not present.

Return type:

bool

Parameters:

p (Position3D)

point_on_visible_cornea(p)[source]

True if point lies within cornea and is not occluded by eyelid.

Return type:

bool

Parameters:

p (Position3D)

property fovea_position: Position3D

Calculate the 3D position of the fovea on the retinal surface.

Uses spherical eye model with optional fovea displacement angles. Positions fovea at axial_length/2 distance from rotation center.

Returns:

Fovea position in eye coordinate system

property angle_kappa: float

Calculate angle kappa - the angle between optical and visual axes.

Measures angle between optical axis (-Z) and visual axis (to fovea). Important for realistic gaze modeling and eye tracking accuracy.

Returns:

Angle kappa in degrees

get_pupil_in_camera_image(camera, use_refraction=True, center_method='ellipse')[source]

Projects pupil boundary points to camera image coordinates.

Handles corneal refraction effects and camera projection. Supports both refracted and direct projection modes.

Parameters:
  • camera (Camera) – Camera object to project into

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

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

Returns:

  • pupil_boundary: numpy array of boundary points (2xN)

  • pupil_center: Point2D object of pupil center, or None if invalid

Return type:

Tuple of (pupil_boundary, pupil_center) where

pprint()[source]

Print detailed eye anatomy parameters in a formatted table.

Return type:

None

serialize()[source]

Serialize eye state to a dictionary.

Returns complete eye state that can be used to perfectly reconstruct the eye object in its exact current state.

Return type:

dict

Returns:

Dictionary containing all eye parameters and current state

classmethod deserialize(data)[source]

Reconstruct eye from serialized data.

Creates a new Eye instance and restores it to the exact state captured in the serialized data.

Parameters:

data (dict) – Dictionary from serialize() method

Return type:

Eye

Returns:

Eye instance in the exact state when serialized

Camera

Pinhole camera model for eye tracking simulation.

Implements camera projection, pan-tilt, and image capture for synthetic eye tracking experiments. Supports both simple pinhole cameras and realistic cameras with distortion from OpenCV calibration.

class pyetsimul.core.camera.Camera(camera_matrix=<factory>, dist_coeffs=None, err=0.0, err_type='gaussian', glint_noise_config=None, name=None, trans=<factory>)[source]

Bases: object

Pinhole camera model for eye tracking.

Key components: - trans: Camera to world transformation matrix - rest_trans: Rest position transformation (for pan-tilt cameras) - camera_matrix: CameraMatrix with focal_length and resolution properties - dist_coeffs: OpenCV distortion coefficients (default: no distortion) - err: Random error amount (default: 0.0) - err_type: Error distribution type (‘gaussian’ or ‘uniform’) - glint_noise_config: GlintNoiseConfig for corneal reflection detection noise (default: None)

Usage: - Default pinhole: Camera() - Custom pinhole: c = Camera(); c.camera_matrix.focal_length = 1000 - Realistic camera: Camera(camera_matrix=CameraMatrix(matrix), dist_coeffs=coeffs)

Parameters:
camera_matrix: CameraMatrix
dist_coeffs: ndarray | None = None
err: float = 0.0
err_type: str = 'gaussian'
glint_noise_config: GlintNoiseConfig | None = None
name: str | None = None
trans: TransformationMatrix
rest_trans: TransformationMatrix
property orientation: RotationMatrix

Get/set the camera’s orientation (3x3 rotation matrix).

property position: Position3D

Get/set the camera’s position (3D vector).

property pointing_at: Position3D | None

Get the position that the camera is currently pointing at.

Returns None if point_at() has never been called.

project(pos)[source]

Projects points in space onto the camera’s image plane.

Transforms 3D positions to camera coordinates and projects to image plane. Adds random error based on camera settings and validates image bounds. Uses OpenCV for realistic camera projection when pinhole_mode=False.

Parameters:

pos (Position3D | list[Position3D]) – 3D positions to project. Can be: - Single Position3D object - list of Position3D objects

Returns:

  • image_points: 2xn matrix of image coordinates (NaN for invalid points)

  • distances: 1xn array of distances from camera along optical axis

  • valid_mask: 1xn boolean array indicating points within image bounds

Return type:

ProjectionResult containing

unproject(image_points, distance)[source]

Unprojects points on the image plane back into 3D space.

Reconstructs 3D positions from 2D image points at specified distance. Uses inverse projection to map image coordinates to world coordinates. Uses OpenCV for realistic camera unprojection when pinhole_mode=False.

Parameters:
  • image_points (Point2D | list[Point2D]) – 2D image points. Can be: - Single Point2D object - list of Point2D objects

  • distance (float | ndarray) – Distance from camera along optical axis

Return type:

Position3D | list[Position3D]

Returns:

Position3D object(s) in world coordinates

pan_tilt(look_at, world_frame=None)[source]

Pans and tilts a camera towards a certain location.

Orients camera to look directly at specified point in world coordinates. Modifies transformation matrix around camera’s coordinate system origin.

Parameters:
  • look_at (Position3D) – Point to look at in world coordinates

  • world_frame (RotationMatrix | None) – Optional world coordinate frame for camera orientation

Return type:

None

point_at(target_point, world_frame=None)[source]

Points camera towards a certain location.

Changes camera’s rest position to point at specified target. Updates both rest_trans and trans matrices accordingly. Differs from pan_tilt() by modifying the rest position.

Parameters:
  • target_point (Position3D) – Point to point at in world coordinates

  • world_frame (RotationMatrix | None) – Optional world coordinate frame for camera orientation

Return type:

None

point_at_binocular(left_eye_pos, right_eye_pos)[source]

Point camera at the midpoint between two eyes, rolled so the inter-eye axis is horizontal.

Computes the correct camera roll from the inter-eye vector so that both eyes appear horizontally aligned in the camera image. Delegates to point_at().

Parameters:
  • left_eye_pos (Position3D) – Position of the left eye in world coordinates.

  • right_eye_pos (Position3D) – Position of the right eye in world coordinates.

Raises:

ValueError – If the camera lies on the inter-eye line (roll is undefined).

Return type:

None

take_image(eye, lights=None, use_refraction=True, center_method='ellipse')[source]

Computes the image of an eye seen by a camera.

Generates synthetic eye image with corneal reflections and pupil detection. Uses light sources to create corneal reflections (CRs) on the cornea.

Parameters:
  • eye (Eye) – Eye object

  • lights (list[Light] | None) – list of light source objects (optional, if None no CRs are computed)

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

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

Return type:

CameraImage

Returns:

CameraImage object containing corneal reflections, pupil boundary, and pupil center

pprint()[source]

Print detailed camera parameters in a formatted table.

Return type:

None

serialize()[source]

Serialize to dictionary representation.

Return type:

dict

classmethod deserialize(data)[source]

Deserialize from dictionary representation.

Return type:

Camera

Parameters:

data (dict)

Light

Light source model for eye tracking simulation.

Defines the Light class for generating corneal reflections (glints) in synthetic eye tracking setups.

class pyetsimul.core.light.Light(position, diameter=None)[source]

Bases: object

Light source for generating corneal reflections.

Represents a point light source positioned in 3D space for eye tracking. Used to create corneal reflections (glints).

Parameters:
  • position (Position3D) – 3D position in world coordinates (mm)

  • diameter (float | None) – Physical diameter of the light source in mm (e.g., 5 for a 5mm LED). None means point source (default, backward compatible).

position: Position3D
diameter: float | None = None
pprint()[source]

Print detailed light parameters in a formatted table.

Return type:

None

serialize()[source]

Serialize to dictionary representation.

Return type:

dict

classmethod deserialize(data)[source]

Deserialize from dictionary representation.

Return type:

Light

Parameters:

data (dict)

Cornea

Cornea model definitions for eye tracking simulation.

Defines abstract and concrete cornea models (spherical, conic) for anatomical and optical simulation.

class pyetsimul.core.cornea.Cornea(center_init=None, _cornea_depth_default=3.54, _cornea_center_to_rotation_center_default=10.2)[source]

Bases: ABC

Abstract base class for different corneal models.

Defines common interface for corneal models to ensure interchangeability. Provides unified interface for intersection, reflection, and refraction calculations.

Parameters:
center_init: dataclasses.InitVar[pyetsimul.types.geometry.Position3D | None] = None
property center: Position3D

Get the cornea center position.

property cornea_center_to_rotation_center_default: float

Get the default cornea center to rotation center distance.

abstract property cornea_type: str

Return the type name of this cornea model.

abstractmethod intersect(ray)[source]

Calculates the intersection point of a light ray with the cornea.

Return type:

IntersectionResult | None

Parameters:

ray (Ray)

abstractmethod normal_at(point)[source]

Calculates the normal vector at a given point on the cornea’s surface.

Return type:

Direction3D

Parameters:

point (Point3D)

point_within_cornea(p, eye)[source]

Tests whether a point lies within the cornea boundaries.

Uses projection distance calculation to determine if point is within corneal depth.

Parameters:
  • p (Position3D) – Point to test in local eye coordinates

  • eye (Eye) – Eye object containing apex position and cornea depth

Returns:

True if point lies within cornea boundaries, False otherwise

Return type:

bool

abstractmethod find_reflection(light_pos, camera_pos, eye_transform)[source]

Finds position of a glint on the corneal surface.

Return type:

Point3D | None

Parameters:
abstractmethod find_refraction(camera_pos, object_pos, n_outside, n_cornea, eye_transform)[source]

Finds position where refraction occurs on the corneal surface.

Return type:

Point3D | None

Parameters:
pprint()[source]

Print detailed cornea parameters in a formatted table.

Return type:

None

class pyetsimul.core.cornea.SphericalCornea(center_init=None, _cornea_depth_default=3.54, _cornea_center_to_rotation_center_default=10.2, anterior_radius=7.98, refractive_index=1.376, _posterior_radius_default=6.22, _thickness_offset_default=1.15, _r_cornea_default=7.98)[source]

Bases: Cornea

Represents a cornea with dual spherical surfaces.

Uses anatomical scaling based on Boff and Lincoln [1988] parameters. Implements proportional scaling of all eye dimensions based on corneal radius.

Variables:
  • anterior_radius (float) – The radius of the anterior (outer) corneal surface.

  • posterior_radius (float) – The radius of the posterior (inner) corneal surface.

  • thickness (float) – Central corneal thickness.

  • center (Point4D) – Inherited from parent. If None, will be calculated by Eye based on anatomical scaling.

Parameters:
anterior_radius: float = 7.98
refractive_index: float = 1.376
property cornea_type: str

Return the type name of this cornea model.

property posterior_radius: float

Calculate the scaled posterior corneal radius.

Returns:

Posterior corneal radius in mm (scaled from reference)

property thickness_offset: float

Calculate the scaled thickness offset.

Returns:

Thickness offset in mm (scaled from reference)

property thickness: float

Calculate the central corneal thickness based on radii and offset.

For a dual-surface spherical cornea, the central thickness is the distance between the anterior and posterior surfaces along the optical axis.

Returns:

Central corneal thickness in mm

get_posterior_center()[source]

Calculate the center of the posterior surface based on thickness.

Return type:

Position3D

static calculate_center_position(scale, axial_length, cornea_center_to_rotation_center)[source]

Calculate the center position for spherical cornea based on anatomical parameters.

This implements the original MATLAB/Eye logic for positioning the spherical cornea center.

Parameters:
  • scale (float) – Scaling factor based on corneal radius

  • axial_length (float) – Total axial length of eye (mm)

  • cornea_center_to_rotation_center (float) – Distance from corneal center to rotation center (mm)

Return type:

Position3D

Returns:

Cornea center position

get_apex_position()[source]

Calculate the apex position for spherical cornea.

For spherical cornea, apex is at center + [0, 0, -radius, 0]

Return type:

Position3D

Returns:

Corneal apex position

get_scale_factor()[source]

Calculate the scaling factor for this spherical cornea.

The scale factor is used to proportionally scale all eye dimensions based on how this cornea’s radius differs from the reference radius.

Return type:

float

Returns:

Scale factor (dimensionless)

get_corneal_depth()[source]

Calculate the scaled corneal depth for this spherical cornea.

Return type:

float

Returns:

Corneal depth in mm (scaled from reference depth)

setup_eye_geometry(axial_length)[source]

Setup all sphere-specific eye geometry parameters.

This method encapsulates all the sphere-specific scaling logic that was previously scattered in the Eye class.

Parameters:

axial_length (float) – Total axial length of the eye (general eye parameter)

Return type:

dict

Returns:

Dictionary containing all calculated geometry parameters

intersect(ray)[source]

Calculates intersection for a spherical cornea.

Returns the intersection result closer to the ray origin.

Return type:

IntersectionResult | None

Parameters:

ray (Ray)

normal_at(point)[source]

Calculates the normal vector for a spherical surface.

Return type:

Direction3D

Parameters:

point (Point3D)

find_reflection(light_pos, camera_pos, eye_transform)[source]

Finds position of a glint on the spherical corneal surface.

Return type:

Point3D | None

Parameters:
find_refraction(camera_pos, object_pos, n_outside, n_cornea, eye_transform)[source]

Finds position where refraction occurs on the spherical corneal surface.

Return type:

Point3D | None

Parameters:
serialize()[source]

Serialize to dictionary representation.

Return type:

dict

classmethod deserialize(data)[source]

Deserialize from dictionary representation.

Return type:

SphericalCornea

Parameters:

data (dict)

class pyetsimul.core.cornea.ConicCornea(center_init=None, _cornea_depth_default=3.54, _cornea_center_to_rotation_center_default=10.2, anterior_radius=7.76, anterior_k=-0.1, posterior_radius=6.52, posterior_k=-0.3, thickness_offset=0.55, refractive_index=1.376)[source]

Bases: Cornea

Represents a cornea with dual conic surfaces.

Uses conic section geometry with formula: (x-cx)² + (y-cy)² + (1+k)(z-cz)² - 2*R*(z-cz) = 0 Implements absolute dimensions without scaling for mathematical consistency.

Default parameters are 30-year-old values from Goncharov & Dainty (2007).

Variables:
  • center (Point4D) – The 4D homogeneous coordinate of the conic center.

  • anterior_radius (float) – Anterior surface radius of curvature at apex in mm.

  • anterior_k (float) – Anterior surface conic constant.

  • posterior_radius (float) – Posterior surface radius of curvature at apex in mm.

  • posterior_k (float) – Posterior surface conic constant.

  • thickness (float) – Central corneal thickness.

  • refractive_index (float) – Refractive index of cornea.

  • thickness_offset (float) – Corneal thickness offset.

  • meanings (k-value) –

    • k = 0: Perfect sphere

    • k < 0: Prolate ellipsoid (typical cornea, flattens toward periphery)

    • k > 0: Oblate ellipsoid (steepens toward periphery)

Parameters:
anterior_radius: float = 7.76
anterior_k: float = -0.1
posterior_radius: float = 6.52
posterior_k: float = -0.3
property cornea_type: str

Return the type name of this cornea model.

thickness_offset: float = 0.55
refractive_index: float = 1.376
get_posterior_center()[source]

Calculate the center of the posterior surface based on conic geometry and thickness.

Return type:

Position3D

get_apex_position()[source]

Calculate the apex position for conic cornea.

For conic cornea, apex is mathematically at z = -R/(1+k) from center. This is the foremost point along the -Z axis.

Return type:

Position3D

Returns:

Corneal apex position

get_corneal_depth()[source]

Calculate the corneal depth for conic cornea.

For consistency with spherical cornea, we use the same reference depth. This ensures that point_within_cornea behaves consistently between models.

Return type:

float

Returns:

Corneal depth in mm

get_scale_factor()[source]

Get scale factor for conic cornea.

Conic cornea uses absolute dimensions, so scale factor is always 1.0.

Return type:

float

Returns:

Scale factor of 1.0 (no scaling)

static calculate_center_position(axial_length, cornea_center_to_rotation_center)[source]

Calculate the center position for conic cornea based on anatomical parameters (no scaling).

Parameters:
  • axial_length (float) – Total axial length of eye (mm)

  • cornea_center_to_rotation_center (float) – Distance from corneal center to rotation center (mm)

Return type:

Position3D

Returns:

Cornea center position

setup_eye_geometry(axial_length)[source]

Setup conic cornea geometry parameters.

Unlike spherical cornea, conic cornea does not use scaling - it uses absolute dimensions.

Parameters:

axial_length (float) – Total axial length of the eye (not used for conic cornea)

Return type:

dict

Returns:

Dictionary containing geometry parameters

intersect(ray)[source]

Calculates intersection for the anterior conic surface.

Returns the intersection result closer to the ray origin.

Return type:

IntersectionResult | None

Parameters:

ray (Ray)

normal_at(point)[source]

Calculates the normal vector for the anterior conic surface.

Return type:

Direction3D

Parameters:

point (Point3D)

find_reflection(light_pos, camera_pos, eye_transform)[source]

Finds position of a glint on the anterior conic surface.

Transforms light and camera positions into eye-local coordinates where the conic axis is aligned with the Z-axis, runs the reflection solver, then transforms the result back to world coordinates.

Return type:

Point3D | None

Parameters:
find_refraction(camera_pos, object_pos, n_outside, n_cornea, eye_transform)[source]

Finds position where refraction occurs on the anterior conic surface.

Transforms positions into eye-local coordinates where the conic axis is aligned with the Z-axis, runs the refraction solver, then transforms the result back to world coordinates.

Return type:

Point3D | None

Parameters:
serialize()[source]

Serialize to dictionary representation.

Return type:

dict

classmethod deserialize(data)[source]

Deserialize from dictionary representation.

Return type:

ConicCornea

Parameters:

data (dict)

pyetsimul.core.cornea.create_cornea(cornea_model_type, center, **kwargs)[source]

Factory function to create a cornea object of specified type.

Provides unified interface for creating different corneal models. Supports both spherical and conic corneal geometries.

Parameters:
  • cornea_model_type (str) – The type of cornea model to create. Supported types: “spherical”, “conic”.

  • center (Point4D) – The center of the cornea.

  • **kwargs (float) – Additional parameters required for the specific cornea model. For “spherical”: anterior_radius, refractive_index For “conic”: anterior_radius, anterior_k, posterior_radius, posterior_k, refractive_index, thickness_offset

Returns:

An instance of the specified Cornea subclass.

Return type:

Cornea

Raises:

ValueError – If an unsupported cornea_model_type is provided.

Pupil

Pupil model definitions for eye tracking simulation.

Defines abstract and concrete pupil models (elliptical, realistic) for boundary generation and anatomical accuracy.

class pyetsimul.core.pupil.Pupil(pos_pupil, x_pupil, y_pupil, n=100)[source]

Bases: ABC

Abstract base class for pupil representations.

Defines common interface for different pupil models (elliptical, realistic, etc.). Provides unified interface for boundary point generation and radius management.

Parameters:
  • pos_pupil (Position3D) – Center position

  • x_pupil (Direction3D) – Vector defining X-axis radius/direction

  • y_pupil (Direction3D) – Vector defining Y-axis radius/direction

  • n (int)

__init__(pos_pupil, x_pupil, y_pupil, n=100)[source]

Initialize elliptical pupil.

Parameters:
  • pos_pupil (Position3D) – Center position of pupil

  • x_pupil (Direction3D) – X-axis radius/direction vector

  • y_pupil (Direction3D) – Y-axis radius/direction vector

  • n (int) – Number of boundary points

Return type:

None

abstractmethod get_boundary_points(n=None)[source]

Generate pupil boundary points.

Parameters:

n (int | None) – Number of boundary points (defaults to self.n if not provided)

Return type:

ndarray

Returns:

4xn matrix of points on pupil boundary (homogeneous coordinates)

abstractmethod get_radii()[source]

Get pupil radii from both axes.

Return type:

tuple[float, float]

Returns:

Tuple of (x_radius, y_radius) in mm

abstractmethod set_radii(x_radius, y_radius)[source]

Set pupil radii and update geometry.

Parameters:
  • x_radius (float) – Pupil radius in X direction (mm)

  • y_radius (float) – Pupil radius in Y direction (mm)

Return type:

None

abstractmethod set_diameter(diameter)[source]

Set pupil diameter and update geometry.

Parameters:

diameter (float) – Pupil diameter in mm

Return type:

None

abstractmethod get_diameter()[source]

Get pupil diameter.

Return type:

float

Returns:

Pupil diameter in mm

abstractmethod serialize()[source]

Serialize to dictionary representation.

Return type:

dict

get_center_world_coords(eye_transform)[source]

Get pupil center in world coordinates.

Transforms pupil center from eye coordinates to world coordinates.

Parameters:

eye_transform (TransformationMatrix) – 4x4 transformation matrix from eye to world coordinates

Return type:

Position3D

Returns:

Pupil center position in world coordinates

get_noncircularity()[source]

Calculate noncircularity.

Default implementation returns 0.0 (perfect circle). Subclasses can override for more sophisticated calculations.

Return type:

float

Returns:

Noncircularity value (0.0 for perfect circle)

pprint()[source]

Print detailed pupil parameters in a formatted table.

Return type:

None

class pyetsimul.core.pupil.EllipticalPupil(pos_pupil, x_pupil, y_pupil, n=100)[source]

Bases: Pupil

Elliptical pupil implementation using parametric representation.

Implements simple elliptical pupil model using parametric formula. Uses cos(α)*x_pupil + sin(α)*y_pupil for boundary generation. # noqa: RUF002

Parameters:
  • pos_pupil (Position3D) – Center position

  • x_pupil (Direction3D) – Vector defining X-axis radius/direction

  • y_pupil (Direction3D) – Vector defining Y-axis radius/direction

  • n (int)

get_boundary_points(n=None)[source]

Generate elliptical pupil boundary points using parametric representation.

Parameters:

n (int | None) – Number of boundary points (defaults to self.n if not provided)

Return type:

ndarray

Returns:

4xn matrix of points on pupil boundary (homogeneous coordinates)

get_radii()[source]

Get pupil radii from both axes.

Return type:

tuple[float, float]

Returns:

Tuple of (x_radius, y_radius) in mm

set_radii(x_radius, y_radius)[source]

Set pupil radii and update geometry.

Parameters:
  • x_radius (float) – Pupil radius in X direction (mm)

  • y_radius (float) – Pupil radius in Y direction (mm)

Return type:

None

set_diameter(diameter)[source]

Set pupil diameter and update geometry.

Parameters:

diameter (float) – Pupil diameter in mm

Return type:

None

get_diameter()[source]

Get pupil diameter.

For elliptical pupils, returns average diameter.

Return type:

float

Returns:

Pupil diameter in mm

serialize()[source]

Serialize to dictionary representation.

Return type:

dict

classmethod deserialize(data)[source]

Deserialize from dictionary representation.

Return type:

EllipticalPupil

Parameters:

data (dict)

class pyetsimul.core.pupil.RealisticPupilParams(base_radius=2.5, noncircularity=0.0166, ellipse_contribution=0.5, major_axis_angle=0.0, pupil_offset_from_limbus=(0.27, 0.2), n_harmonics=6, age=35.8, random_seed=None)[source]

Bases: object

Parameters for realistic human pupil shape generation.

Contains parameters for generating non-circular human pupil shapes based on Wyatt (1995). Implements Fourier series representation of pupil boundary shapes.

Key findings from Wyatt (1995): - No truly circular pupils exist in humans - Average noncircularity: 0.0166 in both light and dark conditions - Elliptical component contributes ~50% of shape deviation - Individual shape signatures remain stable over time - Pupils are consistently displaced nasal and superior to limbus center

Based on: Wyatt, H.J. (1995). “The Form of the Human Pupil.” Vision Research, 35(14), 2021-2036.

Variables:
  • base_radius – Average pupil radius in mm

  • noncircularity – Measure of deviation from circularity (0 = perfect circle)

  • ellipse_contribution – Fraction of noncircularity from elliptical component

  • major_axis_angle – Orientation of ellipse major axis in radians (0=vertical)

  • pupil_offset_from_limbus – (nasal, superior) displacement from limbus center in mm

  • n_harmonics – Number of Fourier harmonics to include in shape generation

  • age – Subject age in years (affects noncircularity and pupil size)

  • random_seed – Random seed for reproducible shape generation (None for random)

Parameters:
base_radius: float = 2.5
noncircularity: float = 0.0166
ellipse_contribution: float = 0.5
major_axis_angle: float = 0.0
pupil_offset_from_limbus: tuple[float, float] = (0.27, 0.2)
n_harmonics: int = 6
age: float = 35.8
random_seed: int | None = None
class pyetsimul.core.pupil.RealisticPupil(pos_pupil, x_pupil, y_pupil, params=None, n=360)[source]

Bases: Pupil

Realistic human pupil implementation using Fourier series representation.

Generates non-circular human pupil boundaries based on Wyatt (1995) analysis. Implements Fourier series: R(θ) = r_ave + Σ r_n cos(n(θ - φ_n)). Uses paper’s noncircularity formula: NC² = (1/2) Σ(r_n/r_ave)² for n=2 to N.

Based on: Wyatt, H.J. (1995). “The Form of the Human Pupil.” Vision Research, 35(14), 2021-2036.

Parameters:
__init__(pos_pupil, x_pupil, y_pupil, params=None, n=360)[source]

Initialize realistic pupil.

Parameters:
  • pos_pupil (Position3D) – Center position

  • x_pupil (Direction3D) – Vector defining X-axis radius/direction

  • y_pupil (Direction3D) – Vector defining Y-axis radius/direction

  • params (RealisticPupilParams | None) – Parameters for realistic pupil shape generation

  • n (int) – Number of boundary points

Return type:

None

harmonics: dict[int, dict[str, float]]
set_diameter(diameter)[source]

Set pupil diameter and automatically determine shape characteristics.

Parameters:

diameter (float) – Pupil diameter in mm

Return type:

None

get_boundary_points(n=None)[source]

Generate realistic pupil boundary points using Fourier series.

Parameters:

n (int | None) – Number of boundary points (defaults to self.n if not provided)

Return type:

ndarray

Returns:

4xn matrix of points on pupil boundary (homogeneous coordinates)

get_radii()[source]

Get pupil radii from both axes.

For realistic pupil, returns effective radii based on current parameters.

Return type:

tuple[float, float]

Returns:

Tuple of (x_radius, y_radius) in mm

set_radii(x_radius, y_radius)[source]

Set pupil radii and update geometry.

Parameters:
  • x_radius (float) – Pupil radius in X direction (mm)

  • y_radius (float) – Pupil radius in Y direction (mm)

Return type:

None

get_diameter()[source]

Get pupil diameter.

Return type:

float

Returns:

Pupil diameter in mm (2 * base_radius)

get_noncircularity()[source]

Calculate actual noncircularity using Wyatt (1995) exact formula.

Returns:

NC² = (1/2) * Σ(rₙ/r_ave)² for n=2 to N

Return type:

Noncircularity value using paper’s formula

serialize()[source]

Serialize to dictionary representation.

Return type:

dict

classmethod deserialize(data)[source]

Deserialize from dictionary representation.

Return type:

RealisticPupil

Parameters:

data (dict)

pyetsimul.core.pupil.create_pupil(pupil_type, pos_pupil, x_pupil, y_pupil, **kwargs)[source]

Factory function to create pupil instances.

Provides unified interface for creating different pupil models. Supports elliptical and realistic pupil geometries.

Parameters:
  • pupil_type (str) – Type of pupil (“elliptical” or “realistic”)

  • pos_pupil (Position3D) – Center position

  • x_pupil (Direction3D) – Vector defining X-axis radius/direction

  • y_pupil (Direction3D) – Vector defining Y-axis radius/direction

  • **kwargs (float) – Additional parameters for specific pupil types - n: Number of boundary points (default: 100 for elliptical, 360 for realistic) - params: RealisticPupilParams for realistic pupil (including random_seed for deterministic shapes)

Return type:

Pupil

Returns:

Pupil instance of the requested type

Raises:

ValueError – If pupil_type is not supported

Eye Tracker

Eye tracker module.

This module provides the EyeTracker class that represents a complete eye tracking system with cameras, lights, calibration points, and algorithm functions.

class pyetsimul.core.eye_tracker.EyeTracker(cameras=<factory>, lights=<factory>, calib_points=<factory>, state=<factory>, use_refraction=True, pupil_center_method='ellipse', failed_calibration_points=<factory>, use_legacy_look_at=False)[source]

Bases: ABC

Abstract base class for eye tracking systems.

Provides unified interface for different eye tracking algorithms. Manages cameras, lights, calibration points, and measurement collection. Implements common workflow for calibration and gaze estimation.

Parameters:
cameras: list[Camera]
lights: list[Light]
calib_points: list[Position3D]
state: dict[str, Any]
use_refraction: bool = True
pupil_center_method: str = 'ellipse'
failed_calibration_points: list[tuple[int, Position3D, str]]
use_legacy_look_at: bool = False
abstract property algorithm_name: str

Algorithm name identifier - must be implemented by subclasses.

add_camera(camera)[source]

Add a camera to the eye tracker.

Manages camera collection for multi-camera eye tracking setups.

Return type:

None

Parameters:

camera (Camera)

add_light(light)[source]

Add a light to the eye tracker.

Manages light collection for corneal reflection detection.

Return type:

None

Parameters:

light (Light)

add_calibration_point(point)[source]

Add a calibration point to the eye tracker.

Builds calibration grid for gaze tracking accuracy.

Return type:

None

Parameters:

point (Position3D)

set_calibration_points(points)[source]

Set all calibration points at once.

Replaces entire calibration grid with new point collection.

Return type:

None

Parameters:

points (list[Position3D])

run_calibration(eye)[source]

Run the complete calibration workflow.

Manages data collection and algorithm-specific calibration. Collects measurements at all calibration points and calls algorithm calibration.

Parameters:

eye (Eye) – Eye object to calibrate with

Return type:

EyeTracker

Returns:

Self for method chaining

estimate_gaze_at(eye, look_at_pos)[source]

Estimate gaze position when eye looks at a target.

Implements complete gaze estimation pipeline: eye movement → camera → prediction. Delegates to algorithm-specific prediction method.

Parameters:
  • eye (Eye) – Eye object

  • look_at_pos (Point3D) – 3D position where eye should look

Return type:

GazePrediction | None

Returns:

GazePrediction with estimated gaze and intermediate values

calculate_gaze_error(eye, look_at_pos)[source]

Calculate gaze estimation error.

Evaluates gaze tracking accuracy by comparing prediction to known target. Returns error in mm or NaN if estimation fails.

Parameters:
  • eye (Eye) – Eye object

  • look_at_pos (Point3D) – 3D position where eye should look

Return type:

tuple[float, float]

Returns:

Tuple of (u, v) gaze error in mm, or (NaN, NaN) if estimation fails

abstractmethod calibrate(calibration_measurements)[source]

Calibrate the eye tracker using collected data.

Abstract interface for algorithm-specific calibration implementation. Each eye tracker type must implement its specific calibration algorithm.

Parameters:

calibration_measurements (list[EyeMeasurement]) – List of eye measurements collected at each calibration point

Return type:

None

test_calibration_fit(eye)[source]

Test calibrated polynomial by predicting each calibration point.

Validates calibration quality by testing full pipeline on known targets. Tests: target → eye movement → camera → polynomial → prediction.

Parameters:

eye (Eye) – Eye object to use for measurements

Return type:

list[tuple[Position3D, GazePrediction | None]]

Returns:

List of (target_position, prediction) tuples for each calibration point

abstractmethod predict_gaze(measurement)[source]

Predict gaze position from eye measurement.

Abstract interface for algorithm-specific gaze prediction implementation. Each eye tracker type must implement its specific gaze prediction algorithm.

Parameters:

measurement (EyeMeasurement) – EyeMeasurement containing pupil and corneal reflection data

Return type:

GazePrediction | None

Returns:

GazePrediction with estimated gaze position or None if prediction fails

pprint(eye=None)[source]

Print detailed eye tracker parameters in a formatted table.

Parameters:

eye (Eye | None) – Optional Eye instance to include eye position in the summary.

Return type:

None

Default Configs

Centralized default parameters for PyEtSimul core components.

Defaults for anatomical and hardware parameters.

class pyetsimul.core.default_configs.EyeAnatomyDefaults(AXIAL_LENGTH=24.75, PUPIL_RADIUS=3.0, N_AQUEOUS_HUMOR=1.336, FOVEA_ALPHA_DEG=6.0, FOVEA_BETA_DEG=2.0, EYELID_OPENNESS=1.0)[source]

Bases: object

Anatomical parameters based on Böhme et al. 2008, Boff & Lincoln 1988.

Parameters:
AXIAL_LENGTH: float = 24.75
PUPIL_RADIUS: float = 3.0
N_AQUEOUS_HUMOR: float = 1.336
FOVEA_ALPHA_DEG: float = 6.0
FOVEA_BETA_DEG: float = 2.0
EYELID_OPENNESS: float = 1.0
class pyetsimul.core.default_configs.CorneaDefaults(ANTERIOR_RADIUS=7.98, POSTERIOR_RADIUS=6.22, REFRACTIVE_INDEX=1.376, THICKNESS_OFFSET=1.15, CORNEA_DEPTH=3.54, CENTER_TO_ROTATION=10.2, CONIC_ANTERIOR_RADIUS=7.76, CONIC_ANTERIOR_K=-0.1, CONIC_POSTERIOR_RADIUS=6.52, CONIC_POSTERIOR_K=-0.3, CONIC_THICKNESS_OFFSET=0.55)[source]

Bases: object

Corneal parameters from Böhme et al. 2008, Goncharov & Dainty 2007.

Parameters:
  • ANTERIOR_RADIUS (float)

  • POSTERIOR_RADIUS (float)

  • REFRACTIVE_INDEX (float)

  • THICKNESS_OFFSET (float)

  • CORNEA_DEPTH (float)

  • CENTER_TO_ROTATION (float)

  • CONIC_ANTERIOR_RADIUS (float)

  • CONIC_ANTERIOR_K (float)

  • CONIC_POSTERIOR_RADIUS (float)

  • CONIC_POSTERIOR_K (float)

  • CONIC_THICKNESS_OFFSET (float)

ANTERIOR_RADIUS: float = 7.98
POSTERIOR_RADIUS: float = 6.22
REFRACTIVE_INDEX: float = 1.376
THICKNESS_OFFSET: float = 1.15
CORNEA_DEPTH: float = 3.54
CENTER_TO_ROTATION: float = 10.2
CONIC_ANTERIOR_RADIUS: float = 7.76
CONIC_ANTERIOR_K: float = -0.1
CONIC_POSTERIOR_RADIUS: float = 6.52
CONIC_POSTERIOR_K: float = -0.3
CONIC_THICKNESS_OFFSET: float = 0.55
class pyetsimul.core.default_configs.PupilDefaults(BOUNDARY_POINTS_ELLIPTICAL=100, BOUNDARY_POINTS_FACTORY=20, BOUNDARY_POINTS_REALISTIC=360, BASE_RADIUS=2.5, NONCIRCULARITY=0.0166, ELLIPSE_CONTRIBUTION=0.5, MAJOR_AXIS_ANGLE=0.0, OFFSET_FROM_LIMBUS=(0.27, 0.2), N_HARMONICS=6, REFERENCE_AGE=35.8)[source]

Bases: object

Pupil parameters based on Wyatt 1995.

Parameters:
  • BOUNDARY_POINTS_ELLIPTICAL (int)

  • BOUNDARY_POINTS_FACTORY (int)

  • BOUNDARY_POINTS_REALISTIC (int)

  • BASE_RADIUS (float)

  • NONCIRCULARITY (float)

  • ELLIPSE_CONTRIBUTION (float)

  • MAJOR_AXIS_ANGLE (float)

  • OFFSET_FROM_LIMBUS (tuple[float, float])

  • N_HARMONICS (int)

  • REFERENCE_AGE (float)

BOUNDARY_POINTS_ELLIPTICAL: int = 100
BOUNDARY_POINTS_FACTORY: int = 20
BOUNDARY_POINTS_REALISTIC: int = 360
BASE_RADIUS: float = 2.5
NONCIRCULARITY: float = 0.0166
ELLIPSE_CONTRIBUTION: float = 0.5
MAJOR_AXIS_ANGLE: float = 0.0
OFFSET_FROM_LIMBUS: tuple[float, float] = (0.27, 0.2)
N_HARMONICS: int = 6
REFERENCE_AGE: float = 35.8
class pyetsimul.core.default_configs.CameraDefaults(FOCAL_LENGTH=2880.0, PRINCIPAL_POINT_X=640.0, PRINCIPAL_POINT_Y=512.0, RESOLUTION_WIDTH=1280, RESOLUTION_HEIGHT=1024, MEASUREMENT_ERROR=0.0)[source]

Bases: object

Camera parameters for typical eye tracking configurations.

Parameters:
  • FOCAL_LENGTH (float)

  • PRINCIPAL_POINT_X (float)

  • PRINCIPAL_POINT_Y (float)

  • RESOLUTION_WIDTH (int)

  • RESOLUTION_HEIGHT (int)

  • MEASUREMENT_ERROR (float)

FOCAL_LENGTH: float = 2880.0
PRINCIPAL_POINT_X: float = 640.0
PRINCIPAL_POINT_Y: float = 512.0
RESOLUTION_WIDTH: int = 1280
RESOLUTION_HEIGHT: int = 1024
MEASUREMENT_ERROR: float = 0.0
class pyetsimul.core.default_configs.EyelidDefaults(LOWER_CAP_FRACTION=0.5, ELLIPSE_WIDTH_TO_HEIGHT=1.5, ELLIPSE_WIDTH_MULTIPLIER=2.0, HEIGHT_MULTIPLIER=2.0, BISECTION_ITERATIONS_PHI1=80, BISECTION_ITERATIONS_PHI2=100, BISECTION_ITERATIONS_AREA=120)[source]

Bases: object

Eyelid shape and numerical parameters.

Parameters:
  • LOWER_CAP_FRACTION (float)

  • ELLIPSE_WIDTH_TO_HEIGHT (float)

  • ELLIPSE_WIDTH_MULTIPLIER (float)

  • HEIGHT_MULTIPLIER (float)

  • BISECTION_ITERATIONS_PHI1 (int)

  • BISECTION_ITERATIONS_PHI2 (int)

  • BISECTION_ITERATIONS_AREA (int)

LOWER_CAP_FRACTION: float = 0.5
ELLIPSE_WIDTH_TO_HEIGHT: float = 1.5
ELLIPSE_WIDTH_MULTIPLIER: float = 2.0
HEIGHT_MULTIPLIER: float = 2.0
BISECTION_ITERATIONS_PHI1: int = 80
BISECTION_ITERATIONS_PHI2: int = 100
BISECTION_ITERATIONS_AREA: int = 120
class pyetsimul.core.default_configs.PupilDecentrationDefaults(RIGHT_EYE_X_COEFF=-0.03, RIGHT_EYE_X_STD=0.07, RIGHT_EYE_Y_COEFF=-0.04, RIGHT_EYE_Y_STD=0.06, LEFT_EYE_X_COEFF=0.03, LEFT_EYE_X_STD=0.04, LEFT_EYE_Y_COEFF=-0.05, LEFT_EYE_Y_STD=0.12, BASELINE_DIAMETER=4.75)[source]

Bases: object

Pupil decentration parameters from Wildenmann & Schaeffel (2013).

Reference: Wildenmann U & Schaeffel F. Variations of pupil centration and their effects on video eye tracking. Ophthalmic Physiol Opt 2013, 33, 634-641.

Parameters:
RIGHT_EYE_X_COEFF: float = -0.03
RIGHT_EYE_X_STD: float = 0.07
RIGHT_EYE_Y_COEFF: float = -0.04
RIGHT_EYE_Y_STD: float = 0.06
LEFT_EYE_X_COEFF: float = 0.03
LEFT_EYE_X_STD: float = 0.04
LEFT_EYE_Y_COEFF: float = -0.05
LEFT_EYE_Y_STD: float = 0.12
BASELINE_DIAMETER: float = 4.75
pyetsimul.core.default_configs.pprint_anatomical_defaults()[source]

Print anatomical default values in formatted table.

Return type:

None

pyetsimul.core.default_configs.pprint_hardware_defaults()[source]

Print hardware default values in formatted table.

Return type:

None

pyetsimul.core.default_configs.pprint_all_defaults()[source]

Print all default parameters in formatted tables.

Return type:

None