OpenSesame videos
Python videos
Supported by Supported by

PyGaze (eye tracking)

About

PyGaze is a Python library for eye tracking. A set of plugins allow you to use PyGaze from within OpenSesame. For more information on PyGaze, visit:

Please cite PyGaze as:

Dalmaijer, E., Mathôt, S., & Van der Stigchel, S. (2014). PyGaze: An open-source, cross-platform toolbox for minimal-effort programming of eyetracking experiments. Behavior Research Methods. doi:10.3758/s13428-013-0422-2

Supported eye trackers

PyGaze supports the following eye trackers:

  • EyeLink — For information on how to run OpenSesame with PyLink support, see this page.
  • EyeTribe — Works out of the box.

For the following eye trackers, there is experimental support:

  • SMI — SMI support is experimental.
  • Tobii — Tobii support is experimental.

PyGaze also includes two dummy eye trackers for testing purposes:

  • Simple dummy — Does nothing.
  • Advanced dummy — Mouse simulation of eye movements.

Installing PyGaze

Windows

If you use the official Windows package of OpenSesame, PyGaze is already installed.

Ubuntu

If you use Ubuntu, you can get PyGaze from the Cogsci.nl PPA:

sudo add-apt-repository ppa:smathot/cogscinl
sudo apt-get update
sudo apt-get install python-pygaze

pip install (all platform)

You can install PyGaze with pip:

pip install python-pygaze

Install from source

On other systems, you can install PyGaze as follows:

  1. Download the PyGaze source code (.zip) from https://github.com/esdalmaijer/PyGaze.
    • Do not download the standalone Windows packages provided on the PyGaze website.
    • Verify that the version of PyGaze is compatible with your version of OpenSesame, as described here.
  2. Extract the .zip archive somewhere.
  3. Inside, you will find these folders:
    • opensesame_plugins: As the name suggests, this folder contains the OpenSesame plugins, which need to be copied to (one of) the plugin folders, as described here.
    • pygaze: This is the PyGaze Python library. You need to copy this to a folder in the Python path. On Windows, you can copy this folder to the OpenSesame program folder.
  4. Done!

PyGaze OpenSesame plugins

The following PyGaze plugins are available:

  • pygaze_init — Initializes PyGaze. This plugin is generally inserted at the start of the experiment.
  • pygaze_drift_correct — Implements a drift correction procedure.
  • pygaze_start_recording — Puts PyGaze in recording mode.
  • pygaze_stop_recording — Puts PyGaze out of recording mode.
  • pygaze_wait — Pauses until an event occurs, such as a saccade start.
  • pygaze_log — Logs experimental variables and arbitrary text.

Example

For an example of how to use the PyGaze plugins, see the PyGaze template that is included with OpenSesame.

Below is an example of how to use PyGaze in a Python inline_script:

# Create a keyboard and a canvas object
my_keyboard = Keyboard(timeout=0)
my_canvas = Canvas()
my_canvas['dot'] = Circle(x=0, y=0, r=10, fill=True)
# Loop ...
while True:
    # ... until space is pressed
    key, timestamp = my_keyboard.get_key()
    if key == 'space':
        break
    # Get gaze position from pygaze ...
    x, y = eyetracker.sample()
    # ... and draw a gaze-contingent fixation dot!
    my_canvas['dot'].x = x + my_canvas.left
    my_canvas['dot'].y = y + my_canvas.top
    my_canvas.show()

Function overview

To initialize PyGaze in OpenSesame, insert the pygaze_init plugin into your experiment. Once you have done this, an eyetracker object will be available, which offers the following functions:

class eyetracker

A generic Python library for eye tracking.

function eyetracker.calibrate()

Calibrates the eye tracking system. The actual behavior of this function depends on the type of eye tracker and is described below.

EyeLink:

This function will activate the camera-setup screen, which allows you to adjust the camera, and peform a calibration/ validation procedure. Pressing 'q' will exit the setup routine. Pressing 'escape' will first trigger a confirmation dialog and then, upon confirmation, raises an Exception.

EyeTribe:

Activates a simple calibration routine.

Returns:

Returns True if calibration succeeded, or False if not; in addition a calibration log is added to the log file and some properties are updated (i.e. the thresholds for detection algorithms).

  • Type: bool

function eyetracker.close()

Neatly closes connection to tracker. Saves data and sets self.connected to False.

function eyetracker.connected()

Checks if the tracker is connected.

Returns:

True if connection is established, False if not; sets self.connected to the same value.

  • Type: bool

function eyetracker.draw_calibration_target(x, y)

Draws a calibration target.

Arguments:

  • x -- The X coordinate
    • Type: int
  • y -- The Y coordinate
    • Type: int

function eyetracker.draw_drift_correction_target(x, y)

Draws a drift-correction target.

Arguments:

  • x -- The X coordinate
    • Type: int
  • y -- The Y coordinate
    • Type: int

function eyetracker.drift_correction(pos=None, fix_triggered=False)

Performs a drift-correction procedure. The exact behavior of this function on the type of eye tracker and is described below. Because drift correction may fail, you will generally call this function in a loop.

EyeLink:

Pressing 'q' during drift-correction will activate the camera-setup screen. From there, pressing 'q' again will cause drift correction to fail immediately. Pressing 'escape' will give the option to abort the experiment, in which case an Exception is raised.

Keywords:

  • pos -- (x, y) position of the fixation dot or None for a central fixation.
    • Type: tuple, NoneType
    • Default: None
  • fix_triggered -- Boolean indicating if drift check should be performed based on gaze position (True) or on spacepress (False).
    • Type: bool
    • Default: False

Returns:

A boolean indicating if drift check is ok (True) or not (False).

  • Type: bool

function eyetracker.fix_triggered_drift_correction(pos=None, min_samples=30, max_dev=60, reset_threshold=10)

Performs a fixation triggered drift correction by collecting a number of samples and calculating the average distance from the fixation position

Keywords:

  • pos -- (x, y) position of the fixation dot or None for a central fixation.
    • Type: tuple, NoneType
    • Default: None
  • min_samples -- The minimal amount of samples after which an average deviation is calculated.
    • Type: int
    • Default: 30
  • max_dev -- The maximal deviation from fixation in pixels.
    • Type: int
    • Default: 60
  • reset_threshold -- If the horizontal or vertical distance in pixels between two consecutive samples is larger than this threshold, the sample collection is reset.
    • Type: int
    • Default: 10

Returns:

A boolean indicating if drift check is ok (True) or not (False).

  • Type: bool

function eyetracker.get_eyetracker_clock_async()

Returns the difference between tracker time and PyGaze time, which can be used to synchronize timing

Returns:

The difference between eyetracker time and PyGaze time.

  • Type: int, float

function eyetracker.log(msg)

Writes a message to the log file.

Arguments:

  • msg -- A message.
    • Type: str, unicode

function eyetracker.log_var(var, val)

Writes a variable's name and value to the log file

Arguments:

  • var -- A variable name.
    • Type: str, unicode
  • val -- A variable value

function eyetracker.pupil_size()

Returns the newest pupil size sample; size may be measured as the diameter or the area of the pupil, depending on your setup (note that pupil size mostly is given in an arbitrary units).

Returns:

Returns pupil size for the eye that is currently being tracked (as specified by self.eye_used) or -1 when no data is obtainable.

  • Type: int, float

function eyetracker.sample()

Returns newest available gaze position.

Returns:

An (x,y) tuple or a (-1,-1) on an error.

  • Type: tuple

function eyetracker.send_command(cmd)

Directly sends a command to the eye tracker (not supported for all brands; might produce a warning message if your setup does not support direct commands).

Arguments:

  • cmd -- The command to be sent to the eye tracker.
    • Type: str, unicode

function eyetracker.set_detection_type(eventdetection)

Set the event detection type to either PyGaze algorithms, or native algorithms as provided by the manufacturer (only if available: detection type will default to PyGaze if no native functions are available)

Arguments:

  • eventdetection -- A string indicating which detection type should be employed: either 'pygaze' for PyGaze event detection algorithms or 'native' for manufacturers algorithms (only if available; will default to 'pygaze' if no native event detection is available)
    • Type: str, unicode

Returns:

Detection type for saccades, fixations and blinks in a tuple, e.g. ('pygaze','native','native') when 'native' was passed, but native detection was not available for saccade detection.

  • Type: tuple

function eyetracker.set_draw_calibration_target_func(func)

Specifies a custom function to draw the calibration target. This will function will override the default [draw_calibration_target].

Arguments:

  • func -- The function to draw a calibration target. This function should accept two parameters, for the x and y coordinate of the target.
    • Type: function

function eyetracker.set_draw_drift_correction_target_func(func)

Specifies a custom function to draw the drift-correction target. This function will override the default [draw_drift_correction_target].

Arguments:

  • func -- The function to draw a drift-correction target. This function should accept two parameters, for the x and y coordinate of the target.
    • Type: function

function eyetracker.set_eye_used()

Logs the eye_used variable, based on which eye was specified (if both eyes are being tracked, the left eye is used). Does not return anything.

function eyetracker.start_recording()

Starts recording. Sets self.recording to True when recording is successfully started.

function eyetracker.status_msg(msg)

Sends a status message to the eye tracker, which is displayed in the tracker's GUI (only available for EyeLink setups).

Arguments:

  • msg -- A string that is to be displayed on the experimenter PC, e.g.: "current trial: %d" % trialnr.
    • Type: str, unicode

function eyetracker.stop_recording()

Stops recording. Sets self.recording to False when recording is successfully stopped.

function eyetracker.wait_for_event(event)

Waits for an event.

Arguments:

  • event -- An integer event code, one of the following:

  • 3 = STARTBLINK

  • 4 = ENDBLINK
  • 5 = STARTSACC
  • 6 = ENDSACC
  • 7 = STARTFIX
  • 8 = ENDFIX
    • Type: int

Returns:

A self.wait_for_* method is called, depending on the specified event; the return value of corresponding method is returned.

function eyetracker.wait_for_fixation_end()

Returns time and gaze position when a fixation has ended; function assumes that a 'fixation' has ended when a deviation of more than self.pxfixtresh from the initial fixation position has been detected (self.pxfixtresh is created in self.calibration, based on self.fixtresh, a property defined in self.init). Detection based on Dalmaijer et al. (2013) if EVENTDETECTION is set to 'pygaze', or using native detection functions if EVENTDETECTION is set to 'native' (NOTE: not every system has native functionality; will fall back to ;pygaze' if 'native' is not available!)

Returns:

A time, gazepos tuple. Time is the end time in milliseconds (from expstart), gazepos is a (x,y) gaze position tuple of the position from which the fixation was initiated.

  • Type: tuple

function eyetracker.wait_for_fixation_start()

Returns starting time and position when a fixation is started; function assumes a 'fixation' has started when gaze position remains reasonably stable (i.e. when most deviant samples are within self.pxfixtresh) for five samples in a row (self.pxfixtresh is created in self.calibration, based on self.fixtresh, a property defined in self.init). Detection based on Dalmaijer et al. (2013) if EVENTDETECTION is set to 'pygaze', or using native detection functions if EVENTDETECTION is set to 'native' (NOTE: not every system has native functionality; will fall back to ;pygaze' if 'native' is not available!)

Returns:

A time, gazepos tuple. Time is the starting time in milliseconds (from expstart), gazepos is a (x,y) gaze position tuple of the position from which the fixation was initiated.

  • Type: tuple

function eyetracker.wait_for_saccade_end()

Returns ending time, starting and end position when a saccade is ended; based on Dalmaijer et al. (2013) online saccade detection algorithm if EVENTDETECTION is set to 'pygaze', or using native detection functions if EVENTDETECTION is set to 'native' (NOTE: not every system has native functionality; will fall back to ;pygaze' if 'native' is not available!)

Returns:

An endtime, startpos, endpos tuple. Endtime in milliseconds (from expbegintime); startpos and endpos are (x,y) gaze position tuples.

  • Type: tuple

function eyetracker.wait_for_saccade_start()

Returns starting time and starting position when a saccade is started; based on Dalmaijer et al. (2013) online saccade detection algorithm if EVENTDETECTION is set to 'pygaze', or using native detection functions if EVENTDETECTION is set to 'native' (NOTE: not every system has native functionality; will fall back to ;pygaze' if 'native' is not available!)

Returns:

An endtime, startpos tuple. Endtime in milliseconds (from expbegintime); startpos is an (x,y) gaze position tuple.

  • Type: tuple
Supported by Supported by