"""Light source model for eye tracking simulation.
Defines the Light class for generating corneal reflections (glints) in synthetic eye tracking setups.
"""
from dataclasses import dataclass
from pyetsimul.log import info, table
from ..types import Position3D
[docs]
@dataclass
class Light:
"""Light source for generating corneal reflections.
Represents a point light source positioned in 3D space for eye tracking.
Used to create corneal reflections (glints).
Args:
position: 3D position in world coordinates (mm)
diameter: 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
def __repr__(self) -> str:
"""String representation showing the light position."""
if self.diameter is not None:
return f"Light(position={self.position}, diameter={self.diameter})"
return f"Light(position={self.position})"
def __str__(self) -> str:
"""Basic string representation of the light."""
pos = self.position
base = f"Light(pos=({pos.x:.1f}, {pos.y:.1f}, {pos.z:.1f})mm"
if self.diameter is not None:
base += f", d={self.diameter:.1f}mm"
return base + ")"
[docs]
def pprint(self) -> None:
"""Print detailed light parameters in a formatted table."""
pos = self.position
if self.diameter is not None:
light_type = f"Extended source (diameter: {self.diameter:.3f} mm)"
else:
light_type = "Point source"
data = [
["Position (x,y,z) mm", f"({pos.x:.3f}, {pos.y:.3f}, {pos.z:.3f})"],
["Light type", light_type],
]
headers = ["Parameter", "Value"]
info("Light Source Parameters:")
table(data, headers=headers, tablefmt="grid")
[docs]
def serialize(self) -> dict:
"""Serialize to dictionary representation."""
data = {"position": self.position.serialize()}
if self.diameter is not None:
data["diameter"] = self.diameter
return data
[docs]
@classmethod
def deserialize(cls, data: dict) -> "Light":
"""Deserialize from dictionary representation."""
return cls(
position=Position3D.deserialize(data["position"]),
diameter=data.get("diameter"),
)