ForeshorteningCalibration#
- class pypillometry.ForeshorteningCalibration(eye, theta, phi, experimental_setup, spline_coeffs, spline_knots, spline_degree=3, fit_intervals=None, fit_metrics=None)[source]#
Bases:
objectContainer for foreshortening correction calibration parameters.
This class stores the fitted camera geometry and temporal pupil model needed to correct pupil size measurements for viewing angle effects. It is usually created by
fit_foreshortening().- Parameters:
eye (
str) – Which eye (‘left’ or ‘right’)theta (
float) – Fitted camera polar angle from the z-axis in radians (the fit constrains it to [0, pi/2])phi (
float) – Fitted camera azimuthal angle in the x-y plane in radians (the fit constrains it to [-pi, pi])experimental_setup (
ExperimentalSetup) – Experimental setup containing known geometry; its camera distance r and eye-to-screen distance d are used for the correctionspline_coeffs (
ndarray) – B-spline coefficients for true pupil size A0(t)spline_knots (
ndarray) – Knot vector for B-spline (time in ms)spline_degree (
int) – Degree of B-spline (3 for cubic)fit_intervals (
Optional[Intervals]) – Intervals used for fitting, if anyfit_metrics (
Optional[Dict]) – Fit quality metrics;fit_foreshortening()stores ‘r2’, ‘rmse’, ‘n_samples’, ‘loss’, ‘n_iterations’ and ‘converged’. Default is an empty dict.
- Attributes:
- eyestr
Which eye (‘left’ or ‘right’)
- thetafloat
Fitted camera polar angle in radians
- phifloat
Fitted camera azimuthal angle in radians
- experimental_setupExperimentalSetup
Experimental setup containing known geometry (r, d, screen info)
- spline_coeffsnp.ndarray
B-spline coefficients for true pupil size A0(t)
- spline_knotsnp.ndarray
Knot vector for B-spline
- spline_degreeint
Degree of B-spline (typically 3 for cubic)
- fit_intervalsIntervals or None
Intervals used for fitting, if any
- fit_metricsdict
Fit quality metrics (R², RMSE, etc.)
Examples
>>> import numpy as np >>> from pypillometry.eyedata import ExperimentalSetup >>> from pypillometry.eyedata.foreshortening_calibration import ForeshorteningCalibration >>> >>> # Create experimental setup >>> setup = ExperimentalSetup( ... screen_resolution=(1920, 1080), ... physical_screen_size=("52 cm", "29 cm"), ... eye_to_screen_center="70 cm", ... camera_spherical=("85 deg", "-90 deg", "60 cm"), ... ) >>> >>> # Create a calibration object with fitted parameters >>> theta = np.radians(85) # fitted angle >>> phi = np.radians(-90) # fitted angle >>> knots = np.array([0]*4 + [50] + [100]*4) >>> coeffs = np.array([3.5, 3.7, 3.6, 3.8, 3.5]) >>> >>> cal = ForeshorteningCalibration( ... eye='left', ... theta=theta, ... phi=phi, ... experimental_setup=setup, ... spline_coeffs=coeffs, ... spline_knots=knots, ... spline_degree=3, ... fit_metrics={'r2': 0.95, 'rmse': 0.12} ... ) >>> >>> # Get correction factor at screen center (using pixel coordinates) >>> correction = cal.get_correction_factor(960, 540) # screen center in pixels >>> print(f"Correction factor: {correction:.3f}")
Methods
Evaluate true pupil size A0(t) at given time point(s).
Compute correction factor 1/cos(alpha) with quality control thresholding.
Details
- evaluate_spline(t)[source]#
Evaluate true pupil size A0(t) at given time point(s).
- Parameters:
- Return type:
- Returns:
A0 (float or array) – True pupil size(s)
Examples
>>> A0_at_t50 = cal.evaluate_spline(50.0) >>> A0_trace = cal.evaluate_spline(np.linspace(0, 100, 100))
- get_correction_factor(x, y, threshold=0.15, from_pixels=True)[source]#
Compute correction factor 1/cos(alpha) with quality control thresholding.
When cos(alpha) is very small (extreme viewing angles), the correction factor becomes very large and amplifies measurement noise. This method returns a masked array where values below threshold are masked.
- Parameters:
x (
Union[float,ndarray]) – Gaze x-coordinate(s) in screen pixels (default) or in mm relative to screen center (if from_pixels is False)y (
Union[float,ndarray]) – Gaze y-coordinate(s) in screen pixels (default) or in mm relative to screen center (if from_pixels is False)threshold (
float) – Minimum cos(alpha) for reliable correction (0.15 corresponds to ~81° viewing angle)from_pixels (
bool) – If True (default), x and y are in pixels and are converted to mm withpixels_to_mm()(centered, positive y = up; as infit_foreshortening()). If False, x and y are already in mm relative to screen center. Requires experimental_setup to have screen info when True.
- Return type:
- Returns:
correction_factor (numpy.ma.MaskedArray) – Correction factor(s), with values masked where cos(alpha) < threshold.
- Raises:
ValueError – If from_pixels is True and the setup has no screen info, or if the setup has no camera position or eye-to-screen distance (r and d are taken from experimental_setup).
Notes
To apply correction: A0_corrected = A_measured * correction_factor
Only the monocular model is used (no eye offset), and screen offset and tilt in experimental_setup are not taken into account.
Masked arrays multiply cleanly with other masked arrays, combining masks automatically (union of masks).
Examples
>>> # Using pixel coordinates (typical use case - default) >>> correction = cal.get_correction_factor(960, 540) >>> corrected_pupil = measured_pupil * correction >>> >>> # Using mm coordinates (relative to screen center) >>> correction = cal.get_correction_factor(0, 0, from_pixels=False) >>> corrected_pupil = measured_pupil * correction