Pupil Labs - Core

High Level Pupil Core Introduction

Pupil Core is a wearable eye tracker. The system consists of two inward-facing eye cameras and one forward-facing world camera mounted on a wearable eyeglasses-like frame.

Pupil Core provides gaze data in its world camera’s field of view, regardless of the wearer’s head position. As such, gaze can be analysed with the wearer looking and moving freely in their environment.

Pupil Core differs from remote eye trackers often used with PsychoPy®. Remote eye trackers employ cameras mounted on or near a computer monitor. They provide gaze in screen-based coordinates, and this facilitates closed-loop analyses of gaze based on the known position of stimuli on-screen and eye gaze direction.

In order to use Pupil Core for screen-based work in PsychoPy®, the screen will need to be robustly located within the world camera’s field of view, and Pupil Core’s gaze data subsequently transformed from world camera-based coordinates to screen-based coordinates. This is achieved with the use of AprilTag Markers.

Pupil Core binocular headset with high-speed scene camera

For a detailed overview of wearable vs remote eye trackers, check out this Pupil Labs blog post.

Join the Pupil Labs Discord community to share your research and/or questions.

Device, Software, and Connection Setup

Additional Software Requirements

Pupil Capture version v2.0 or newer

Platforms:

  • Windows 10

  • macOS 10.14 or newer

  • Ubuntu 16.04 or newer

Supported Models:

  • Pupil Core headset

Setting Up the Eye Tracker

  1. Follow Pupil Core’s Getting Started guide to setup the headset and Capture software

Setting Up PsychoPy®

  1. Open experiment settings in the Builder Window (cog icon in top panel)

  2. Open the Eyetracking tab

  3. Modify the properties as follows:

    • Select Pupil Labs from the Eyetracker Device drop down menu

    • Pupil Remote Address / Port - Defines how to connect to Pupil Capture. See Pupil Capture’s Network API menu to check address and port are correct. PsychoPy® will wait the amount of milliseconds declared in Pupil Remote Timeout (ms) for the connection to be established. An error will be raised if the timeout is reached.

    • Pupil Capture Recording - Enable this option to tell Pupil Capture to record the eye tracker’s raw data during the experiment. You can read more about that in Pupil Capture’s official documentation. Leave Pupil Capture Recording Location empty to record to the default

    • Gaze Confidence Threshold - Set the minimum data quality received from Pupil Capture. Ranges from 0.0 (all data) to 1.0 (highest possible quality). We recommend using the default value of 0.6.

    • Pupillometry Only - If this mode is selected you will only receive pupillometry data. No further setup is required. If you are interested in gaze data, keep this option disabled and read on below.

Pupil Core eye tracking options, part of |PsychoPy| experiment settings

Pupillometry + Gaze Mode

To receive gaze, enable Pupil Capture’s Surface Tracking plugin:

  1. Start by printing four apriltag markers and attaching them at the screen corners. Avoid occluding the screen and leave sufficient white space around the marker squares. Read more about the general marker setup here.

Subject wearing Pupil Core headset, looking at a Computer screen setup with AprilTag markers
  1. Enable the surface tracker plugin

  2. Define a surface and align its surface corners with the screen corners as good as possible

  3. Rename the surface to the name set in the Surface Name field of the eye tracking project settings (default: psychopy_iohub_surface)

  4. Run the PsychoPy® calibration component as part of your experiment

Implementation and API Overview

EyeTracker Class

Supported Event Types

The Pupil Core–PsychoPy® integration provides real-time access to monocular and binocular sample data. In pupillometry-only mode, all events will be emitted as MonocularEyeSampleEvents. In pupillometry+gaze mode, the software only emits BinocularEyeSampleEvents events if Pupil Capture is driving a binocular headset and the detection from both eyes have sufficient confidence to be paired. See this high-level overview of the Pupil Capture Data Matching algorithm for details.

The supported fields are described below.

class psychopy.iohub.devices.eyetracker.MonocularEyeSampleEvent(*args, **kwargs)[source]

A MonocularEyeSampleEvent represents the eye position and eye attribute data collected from one frame or reading of an eye tracker device that is recoding from only one eye, or is recording from both eyes and averaging the binocular data.

Event Type ID: EventConstants.MONOCULAR_EYE_SAMPLE

Event Type String: ‘MONOCULAR_EYE_SAMPLE’

device_time: float

time of gaze measurement, in sec.msec format, using Pupil Capture clock

logged_time: float

time at which the sample was received in PsychoPy®, in sec.msec format, using PsychoPy clock

time: float

time of gaze measurement, in sec.msec format, using PsychoPy clock

confidence_interval: float = -1.0

currently not supported, always set to -1.0

delay: float

The difference between logged_time and time, in sec.msec format

eye: int = 21 or 22

psychopy.iohub.constants.EyeTrackerConstants.RIGHT_EYE (22) or psychopy.iohub.constants.EyeTrackerConstants.LEFT_EYE (21)

gaze_x: float

x component of gaze location in display coordinates. Set to float("nan") in pupillometry-only mode.

gaze_y: float

y component of gaze location in display coordinates. Set to float("nan") in pupillometry-only mode.

gaze_z: float = 0 or float("nan")

z component of gaze location in display coordinates. Set to float("nan") in pupillometry-only mode. Set to 0.0 otherwise.

eye_cam_x: float

x component of 3d eye model location in undistorted eye camera coordinates

eye_cam_y: float

y component of 3d eye model location in undistorted eye camera coordinates

eye_cam_z: float

z component of 3d eye model location in undistorted eye camera coordinates

angle_x: float

phi angle / horizontal rotation of the 3d eye model location in radians. -pi/2 corresponds to looking directly into the eye camera

angle_y: float

theta angle / vertical rotation of the 3d eye model location in radians. pi/2 corresponds to looking directly into the eye camera

raw_x: float

x component of the pupil center location in normalized coordinates

raw_y: float

y component of the pupil center location in normalized coordinates

pupil_measure1: float

Major axis of the detected pupil ellipse in pixels

pupil_measure1_type: int = psychopy.iohub.constants.EyeTrackerConstants.PUPIL_MAJOR_AXIS
pupil_measure2: float | None

Diameter of the detected pupil in mm or None if not available

pupil_measure2_type: int = psychopy.iohub.constants.EyeTrackerConstants.PUPIL_DIAMETER_MM
class psychopy.iohub.devices.eyetracker.BinocularEyeSampleEvent(*args, **kwargs)[source]

The BinocularEyeSampleEvent event represents the eye position and eye attribute data collected from one frame or reading of an eye tracker device that is recording both eyes of a participant.

Event Type ID: EventConstants.BINOCULAR_EYE_SAMPLE

Event Type String: ‘BINOCULAR_EYE_SAMPLE’

device_time: float

time of gaze measurement, in sec.msec format, using Pupil Capture clock

logged_time: float

time at which the sample was received in PsychoPy, in sec.msec format, using PsychoPy clock

time: float

time of gaze measurement, in sec.msec format, using PsychoPy clock

confidence_interval: float = -1.0

currently not supported, always set to -1.0

delay: float

The difference between logged_time and time, in sec.msec format

left_gaze_x: float

x component of gaze location in display coordinates. Set to float("nan") in pupillometry-only mode. Same as right_gaze_x.

left_gaze_y: float

y component of gaze location in display coordinates. Set to float("nan") in pupillometry-only mode. Same as right_gaze_y.

left_gaze_z: float = 0 or float("nan")

z component of gaze location in display coordinates. Set to float("nan") in pupillometry-only mode. Set to 0.0 otherwise. Same as right_gaze_z.

left_eye_cam_x: float

x component of 3d eye model location in undistorted eye camera coordinates

left_eye_cam_y: float

y component of 3d eye model location in undistorted eye camera coordinates

left_eye_cam_z: float

z component of 3d eye model location in undistorted eye camera coordinates

left_angle_x: float

phi angle / horizontal rotation of the 3d eye model location in radians. -pi/2 corresponds to looking directly into the eye camera

left_angle_y: float

theta angle / vertical rotation of the 3d eye model location in radians. pi/2 corresponds to looking directly into the eye camera

left_raw_x: float

x component of the pupil center location in normalized coordinates

left_raw_y: float

y component of the pupil center location in normalized coordinates

left_pupil_measure1: float

Major axis of the detected pupil ellipse in pixels

left_pupil_measure1_type: int = psychopy.iohub.constants.EyeTrackerConstants.PUPIL_MAJOR_AXIS
left_pupil_measure2: float | None

Diameter of the detected pupil in mm or None if not available

pupil_measure2_type: int = psychopy.iohub.constants.EyeTrackerConstants.PUPIL_DIAMETER_MM
right_gaze_x: float

x component of gaze location in display coordinates. Set to float("nan") in pupillometry-only mode. Same as left_gaze_x.

right_gaze_y: float

y component of gaze location in display coordinates. Set to float("nan") in pupillometry-only mode. Same as left_gaze_y.

right_gaze_z: float = 0 or float("nan")

z component of gaze location in display coordinates. Set to float("nan") in pupillometry-only mode. Set to 0.0 otherwise. Same as left_gaze_z.

right_eye_cam_x: float

x component of 3d eye model location in undistorted eye camera coordinates

right_eye_cam_y: float

y component of 3d eye model location in undistorted eye camera coordinates

right_eye_cam_z: float

z component of 3d eye model location in undistorted eye camera coordinates

right_angle_x: float

phi angle / horizontal rotation of the 3d eye model location in radians. -pi/2 corresponds to looking directly into the eye camera

right_angle_y: float

theta angle / vertical rotation of the 3d eye model location in radians. pi/2 corresponds to looking directly into the eye camera

right_raw_x: float

x component of the pupil center location in normalized coordinates

right_raw_y: float

y component of the pupil center location in normalized coordinates

right_pupil_measure1: float

Major axis of the detected pupil ellipse in pixels

right_pupil_measure1_type: int = psychopy.iohub.constants.EyeTrackerConstants.PUPIL_MAJOR_AXIS
right_pupil_measure2: float | None

Diameter of the detected pupil in mm or None if not available

right_pupil_measure2_type: int = psychopy.iohub.constants.EyeTrackerConstants.PUPIL_DIAMETER_MM

Default Device Settings

eyetracker.hw.pupil_labs.pupil_core.EyeTracker:
    # Indicates if the device should actually be loaded at experiment runtime.
    enable: True

    # The variable name of the device that will be used to access the ioHub Device class
    # during experiment run-time, via the devices.[name] attribute of the ioHub
    # connection or experiment runtime class.
    name: tracker

    device_number: 0

    #####

    model_name: Pupil Core

    model_number: "0"

    serial_number: N/A

    manufacturer_name: Pupil Labs

    software_version: N/A

    hardware_version: N/A

    firmware_version: N/A

    #####

    monitor_event_types: [MonocularEyeSampleEvent, BinocularEyeSampleEvent]

    # Should eye tracker events be saved to the ioHub DataStore file when the device
    # is recording data ?
    save_events: True

    # Should eye tracker events be sent to the Experiment process when the device
    # is recording data ?
    stream_events: True

    # How many eye events (including samples) should be saved in the ioHub event buffer before
    # old eye events start being replaced by new events. When the event buffer reaches
    # the maximum event length of the buffer defined here, older events will start to be dropped.
    event_buffer_length: 1024

    # Do not change this value.
    auto_report_events: False

    device_timer:
        interval: 0.005

    #####

    runtime_settings:
        pupil_remote:
            ip_address: 127.0.0.1
            port: 50020
            timeout_ms: 1000
        pupil_capture_recording:
            enabled: True
            location: Null # Use Pupil Capture default recording location
        # Subscribe to pupil data only, does not require calibration or surface setup
        pupillometry_only: False
        confidence_threshold: 0.6
        # Only relevant if pupillometry_only is False
        surface_name: psychopy_iohub_surface

Last Updated: February, 2022


Back to top