Core – EyeLink
Core EyeLink wrapper functionality.
This module provides the main interface for interacting with SR Research EyeLink eye trackers via Pylink. It includes Settings configuration and the unified EyeLink tracker interface.
- class pyelink.core.EyeLink(settings, record_raw_data=False, sample_buffer_length=0, use_sample_buffer=False, read_from_eyelink_buffer=True, event_buffer_length=0, auto_connect=True)[source]
Bases:
objectUnified EyeLink tracker interface with integrated display management.
This class provides a complete interface for interacting with SR Research EyeLink eye trackers. It combines hardware connection, display window management, recording, data access, and configuration in a single unified class.
The tracker creates and owns the display window throughout the experiment. Users can access the window directly via tracker.window (Option A) or use backend-agnostic helper methods (Option B).
Graceful shutdown: Press Ctrl+C at any time (including during calibration) to automatically stop recording, close the window, save data, and disconnect.
This class uses two-phase initialization to separate object construction from I/O operations: - __init__: Sets up the object state (no side effects) - connect(): Performs network connection, file operations, and creates display window
Example
settings = Settings(BACKEND=’pygame’, FULLSCREEN=True) tracker = EyeLink(settings) # Auto-connects and creates window
# Option A: Direct window access tracker.window.fill((128, 128, 128)) tracker.flip()
# Option B: Backend-agnostic helpers tracker.fill((128, 128, 128)) tracker.display.draw_text(“Fixate”, center=True) tracker.flip()
# Ctrl+C at any point will gracefully shut down and save data
- Dummy mode (for testing without hardware):
settings = Settings(BACKEND=’pygame’, HOST_IP=’dummy’) tracker = EyeLink(settings) # Creates window in dummy mode # Full window functionality available for development/testing
- Or use two-phase initialization:
tracker = EyeLink(settings, auto_connect=False) tracker.connect() # Connect and create window when ready
- Or use as a context manager:
- with EyeLink(settings) as tracker:
# use tracker and window pass # auto-cleanup
- Parameters:
- __init__(settings, record_raw_data=False, sample_buffer_length=0, use_sample_buffer=False, read_from_eyelink_buffer=True, event_buffer_length=0, auto_connect=True)[source]
Initialize EyeLink tracker interface.
- Parameters:
settings (
Settings) – Settings object with tracker configurationrecord_raw_data (
bool) – Set to True to record pupil/CR (raw) datasample_buffer_length (
int) – Store samples in buffer if you need more than the latestuse_sample_buffer (
bool) – Store data from buffer in RingBufferread_from_eyelink_buffer (
bool) – Use getNextData() instead of getNewestSample() (the former draws from an internal buffer and should miss fewer samples)event_buffer_length (
int) – Store events in buffer if you need more than the latestauto_connect (
bool) – If True, automatically connect during initialization. If False, you must call connect() manually (two-phase initialization).
- Return type:
None
- register_cleanup(callback)[source]
Register user cleanup function to run before exit.
Cleanup functions are called in reverse registration order (LIFO) before the program exits. This allows users to register cleanup for external resources like screen capture, logging, etc.
Example
tracker.register_cleanup(capture.stop) tracker.register_cleanup(lambda: print(“Done!”))
- connect()[source]
Connect to tracker and initialize all components.
This method performs all I/O operations including: - Network connection to tracker (or dummy mode if HOST_IP is None/’dummy’) - Opening the EDF data file - Setting tracker to offline mode - Initializing data buffers and event processors - Configuring tracker settings - Creating display window (works in both real and dummy mode)
Call this manually if auto_connect=False was used.
- Return type:
- is_connected()[source]
Check if connected to tracker.
- Return type:
- Returns:
True if connected to real tracker, False otherwise
- property window: object
Get raw backend window object for direct access (Option A).
- Returns:
pygame: pygame.Surface
psychopy: psychopy.visual.Window
pyglet: pyglet.window.Window
- Return type:
Backend-specific window
Example
# Direct pygame access tracker.window.fill((128, 128, 128)) tracker.window.blit(my_surface, (x, y))
- flip()[source]
Update display to show drawn content.
Convenience method that delegates to display.flip().
- Return type:
- fill(color)[source]
Fill window with specified RGB color.
Convenience method that delegates to display.fill().
- clear()[source]
Clear window to black.
Convenience method that delegates to display.clear().
- Return type:
- wait_for_key(key=None, timeout=None)[source]
Wait for keyboard input (Option B helper).
- Parameters:
- Return type:
- Returns:
Key name that was pressed, or None if timeout
Example
tracker.show_message(“Press SPACE to continue”) tracker.wait_for_key(‘space’)
- wait(duration)[source]
Wait for specified duration while handling UI events.
Prevents event queue buildup during delays.
Example
tracker.show_message(“Get ready…”) tracker.wait(2.0)
- show_message(text, duration=None, bg_color=(128, 128, 128), text_color=(255, 255, 255), text_size=32)[source]
Display text message centered on screen (Option B helper).
- Parameters:
text (
str) – Message to displayduration (
float|None) – Time to display in seconds, or None to display without waitingbg_color (
tuple[int,int,int]) – Background RGB color (default: gray (128, 128, 128))text_color (
tuple[int,int,int]) – Text RGB color (default: white (255, 255, 255))text_size (
int) – Font size in points (default: 32)
- Return type:
Example:
tracker.show_message("Press SPACE when ready") tracker.wait_for_key('space') # Or with auto-wait: tracker.show_message("Get ready...", duration=2.0) # Custom colors: tracker.show_message( "Error!", bg_color=(255, 0, 0), # Red background text_color=(255, 255, 255), # White text text_size=48 )
- run_trial(draw_func, trial_data=None, duration=None, record=True, on_ui_event=None)[source]
Run a trial with automatic recording and event handling (Option B helper).
This is a structured trial runner that handles the common pattern: start recording → draw loop → handle events → stop recording.
- Parameters:
draw_func (
object) – Function that draws the trial. Called as draw_func(window, trial_data). Should draw but NOT flip - flipping happens automatically.trial_data (
dict|None) – Optional dict passed to draw_funcduration (
float|None) – Maximum trial duration in seconds, or None for unlimitedrecord (
bool) – If True, start/stop recording automaticallyon_ui_event (
object|None) – Optional callback for UI events. Called as on_ui_event(event_dict, trial_data). UI events = keyboard/mouse, NOT eye-tracking events. Return True to end trial early.
- Returns:
‘duration’: Actual trial duration in seconds
’ui_events’: List of UI event dicts that occurred
’ended_by’: ‘duration’, ‘callback’, or ‘escape’
- Return type:
Example:
def draw_stimulus(window, data): # window is raw backend window (Option A access within callback) window.fill((128, 128, 128)) # ... draw your stimulus ... def handle_response(event, data): if event['type'] == 'keydown' and event['key'] == 'space': data['response_time'] = time.time() - data['trial_start'] return True # End trial return False trial_data = {'trial_start': time.time(), 'stimulus': 'image.png'} result = tracker.run_trial( draw_func=draw_stimulus, trial_data=trial_data, duration=5.0, on_ui_event=handle_response )
- send_command(command)[source]
Send a raw command to the EyeLink tracker.
This gives direct access to any EyeLink command, including those not exposed through the
Settingsclass. Commands configure tracker behavior but are not recorded in the data file.See EyeLink Commands Reference for a full list of available commands.
- Parameters:
command (
str) – EyeLink command string (same syntax as INI files on Host PC)- Return type:
Example:
# Change sample rate tracker.send_command("sample_rate = 500") # Set screen coordinates tracker.send_command("screen_pixel_coords = 0 0 1919 1079") # Configure parser thresholds tracker.send_command("select_parser_configuration 0") # Any command from the EyeLink Host PC INI files works tracker.send_command("heuristic_filter 1 2")
- send_message(message)[source]
Send a timestamped message recorded in the EDF data file.
Messages are annotations in the data file, useful for marking events during recording (trial starts, stimulus onsets, responses, etc.). Each message is timestamped by the tracker with microsecond precision.
Example:
tracker.send_message("TRIALID 1") tracker.send_message("STIMULUS_ONSET image.png") tracker.send_message(f"RESPONSE key={response} rt={rt:.3f}")
- get_tracker_version()[source]
Get the tracker version as an integer.
- Return type:
- Returns:
Tracker version as int, or 0 if not connected or parsing fails
- eye_available()[source]
Get which eye is being tracked.
- Return type:
- Returns:
0=left, 1=right, 2=binocular, -1 if not available
- get_next_data()[source]
Get next data type from the tracker buffer.
- Return type:
- Returns:
Data type code (200=sample, 4=blink, 8=fixation, 0x3F/0=no data)
- set_calibration_type(cal_type)[source]
Set calibration type (equation to use as a fit).
Sets what type of equation to use for calibration fit: - H3: horizontal-only 3-point quadratic - HV3 or 3: 3-point bilinear - HV5 or 5: 5-point bi-quadratic - HV9 or 9: 9-point bi-quadratic with corner correction - HV13: 13-point bi-cubic calibration
Notes: - HV9 should NOT be used for remote mode - HV13 works best with larger angular displays (> +/-20 degrees) - HV13 should NOT be used when accurate data is needed from corners
- calibrate(record_samples=False, mode='normal')[source]
Calibrate eye-tracker using internal display window.
Creates calibration display automatically based on settings.backend and uses the tracker’s internal window (tracker.display.window).
- Parameters:
- Return type:
Example
tracker = EyeLink(settings) tracker.calibrate() # Normal mode - both calibration and validation available tracker.calibrate(mode=”calibration-only”) # Only calibration, ‘v’ key disabled tracker.calibrate(mode=”validation-only”) # Only validation, ‘c’ key disabled
- camera_setup()[source]
Open camera setup screen for adjusting pupil/CR tracking.
This shows the live camera view with pupil and corneal reflection detection overlays.
Press Escape to exit camera setup.
- Return type:
Example
tracker.camera_setup() # Opens camera view directly
- start_recording(sendlink=False)[source]
Start recording. Waits 50ms to allow EyeLink to prepare.
- Parameters:
sendlink (
bool) – Toggle for sending eye data over the link to display computer during recording- Return type:
Note
heuristic_filter needs to be set each time recording starts as it is reset at recording stop according to the manual. It’s on per default.
- end_experiment()[source]
Comprehensive cleanup: stop recording, save EDF, and disconnect.
This is the single cleanup method that ensures all resources are properly cleaned up and the EDF file is saved. Called automatically on exit, on Ctrl+C, or can be called explicitly by the user.
Works at any point during the experiment, including during calibration.
The EDF file is saved to the directory specified in settings.filepath.
WARNING: Don’t retrieve a file using PsychoPy. Start exp program from cmd otherwise file transfer can be very slow.
- Return type:
- is_recording()[source]
Check if currently recording.
- Return type:
- Returns:
True if recording, False otherwise
- set_trial_result(rval=0, scrcol=0)[source]
Send trial result to indicate trial end in EDF.
Also clears the screen on EyeLink Display.
- set_pupil_only_mode()[source]
Set tracker in pupil only mode (no corneal reflection).
Configures the tracker to track only the pupil without requiring a corneal reflection (CR). This mode should only be used when the participant’s head is completely fixed (e.g., with a chin rest).
Commands sent: - force_corneal_reflection = OFF: Disables forcing CR mode - allow_pupil_without_cr = ON: Allows pupil detection without nearby CR - elcl_hold_if_no_corneal = OFF: Don’t freeze tracking if CR missing - elcl_search_if_no_corneal = OFF: Don’t search for new pupil/CR if CR lost - elcl_use_pcr_matching = OFF: Disables pupil-CR matching - corneal_mode = NO: Activates pupil-only tracking mode
- Return type: