Now Shipping! – The EyeLink 3; combined head and eye tracking at up to 1000 Hz.

How-To: EyeLink Data Viewer Integration Messaging Protocol
#1
When running an experiment it is important to send messages to the EyeLink Data File (EDF) file to mark the occurrence of critical trial events (such as stimulus onset / participant response). These messages are critical for most analysis scenarios, as they allow interest periods to be set, and gaze to be mapped in time with the trial events. In Experiment Builder, sending messages to the EDF can be accomplished by filling out the Message property of an Experiment Builder node or using a separate SEND_MESSAGE node. In other stimulus presentation software, messages are sent using the EyeLink API's SendMessage() command (or a variant thereof depending on which programming environment you are using).

In addition to flagging critical trial events, messages can also be used to send other types of information that are specific to our analysis software, Data Viewer. These Data Viewer Integration messages can include things like trial variables and values, the locations of Interest Areas, and paths to the particular stimuli used on a given trial for gaze overlay reconstructions. These integration messages require special formatting which is outlined in the Protocol for EyeLink Data to Viewer Integration section of the Data Viewer User Manual.

The following sections cover some of the basic messages that are essential to proper Data Viewer integration. Please see our Webinar on EyeLink Data Viewer Integration Messaging Protocol for an example of how to use these messages in task implemented in Psychtoolbox:
  1. Trial Parsing Messages

    In order for data to be parsed into separate trials special messages can be sent that correspond to the start and the end of each trial. By default Data Viewer uses TRIALID to signal the onset of a trial and TRIAL_RESULT to signal the end of a trial. In any of the examples contained in the EyeLink Developer's Kit, you will see a structure similar to the following for parsing trials (the following is an abbreviated version of the Psychtoolbox examples; note that the exact syntax will be slightly different in other programming languages):

    Code:
    % Parse the start of the trial
    Eyelink('Message', 'TRIALID');

    %% -------------
    % your task code
    %% -------------

    % Parse the end of the trial
    Eyelink('Message', 'TRIAL_RESULT 0')

  2. Trial Variables Messages

    It can be very helpful for data analysis to log the variables used in your task as well any participant responses . Rather than logging these in a separate file and then combining them with your gaze data post-hoc you can have them logged directly into your EDF file via the use of !V TRIAL_VAR messages. Any message that begins with !V will be used by Data Viewer. The TRIAL_VAR messages take in a Name and Value pair that allow you to log trial variables and their values on a trial by trial basis. These trial variables will then be available as additional columns in your Data Viewer reports and can be used to regroup trials and do aggregate analysis. For instance, to record the stimulus used on a given trial along with the participant's response, accuracy, and reaction time, TRIAL_VAR messages can be added to log each of these data points.

    Code:
    Eyelink('Message', '!V TRIAL_VAR Stimulus %s', imageFilename)       
    Eyelink('Message', '!V TRIAL_VAR Response %s', subResponse)       
    Eyelink('Message', '!V TRIAL_VAR RT %d', displayOnset-subResponseTime)       
    Eyelink('Message', '!V TRIAL_VAR Accuracy %s', subAccuracy)

    As you can see each TRIAL_VAR contains a variable label and a value for that variable for the trial. If all labels are not reused on each trial then a placeholder value (a period by default) will be used for any trial where that label was not used. Note that these messages must be sent during the trial period as parsed by the trial parsing messages above (in other words after the TRIALID message and before the TRIAL_RESULT messag). TRIAL_VAR messages recorded outside of a trial period will be ignored in Data Viewer.

  3. Image and Drawing Messages

    Data Viewer also supports a variety of image and drawing commands that allow you to represent the stimulus displayed to the participant in the Spatial Overlay and Animation Playback Views of the Trial View Window. Note that all image and drawing commands assume that the top left corner of the screen is pixel (0, 0) and the bottom right corner is the max resolution of the screen(e.g., [1919, 1079] for a resolution of 1920 x 1080).

    All image related Data Viewer Integration messages use the keyword IMGLOAD followed by a subcommand that specifies how the image should be defined. These commands typically use a relative path to specify where the overlay image is stored relative to the EDF. This allows portability between computers as long as the relative path is maintained. For instance, to display a full-screen image, you could use a message similar to the following:

    Code:
    Eyelink('Message', '!V IMGLOAD FILL ../images/myimage.jpg')

    This tells Data Viewer to load the image myImage.jpg as a full-screen image for the overlay at the time the message was received. The message above also assumes that the EDF file is stored in its own subdirectory of the project folder and that relative to the EDF file, the image can be found in an images folder that is in a folder one level up from the location of the EDF file (note, the "../" means go up a level).

    If you want to load an image which only takes up a subset of the screen, you can use the subcommand TOP_LEFT or CENTER followed by its relative path and then it's pixel location (defined either by the top left corner or the center of the image depending on which subcommand is used). Further optional arguments can be added to define the image resource's width and height. The following code will load an image and define that its top-left corner should be placed at pixel 300,300:

    Code:
    Eyelink('Message', '!V IMGLOAD TOP_LEFT ../images/ myimage .jpg 300 300')

    The following message will load the same image but resize it to 100 x 100 and center it at pixel (400, 400):

    Code:
    Eyelink('Message', '!V IMGLOAD CENTER../images/ myimage .jpg 400 400 100 100')

    If your stimuli are programmatically rendered / drawn on the fly, rather than coming from existing image files, then it may be simpler to draw a placeholder for the stimulus using simple drawing commands. The sample of code outlined below illustrates some of the various commands that could be used to draw stimuli on in the Data Viewer Trial View window.

    Code:
    Eyelink('Message', '!V CLEAR 255 255 255')
    Eyelink('Message', '!V FILLBOX 0 0 255 400 500 500 600')
    Eyelink('Message', '!V DRAWBOX 0 255 0 200 300 400 500')
    Eyelink('Message', '!V DRAWLINE 255 0 0 100 100 300 400')

    The first command clears the Trial view window to a specified RGB value (in this case white), The next command draws a solid 100 x 100 Blue box whose top left corner is positioned at pixel (400, 500) on the screen. The third command draws an open green box whose top left corner is positioned at pixel (200, 300). Finally, the last command draws a red line from pixel (100, 100) to pixel (300, 400).

    It is important that these messages are sent as close to the occurrence of the stimulus event as possible. For many programming languages having the messages immediately following the line of code that presents the stimuli is enough to synchronize events within <1 msec. However, in some programming environments this is not possible and so you must use a timing offset to shift the timing of the message to correspond with the onset of the stimulus. Section VI of this thread covers how to utilize this feature.

  4. Interest Area Messages

    While interest areas can be defined post-hoc in Data Viewer, you can also have them programmatically defined by your script by sending specially formatted messages. This allows you to automatically generate interest areas corresponding to your stimuli at the time of data collection rather than post-hoc.

    You can generate rectangular interest areas:

    Code:
    Eyelink('Message', '!V IAREA RECTANGLE 1 547 410 585 449 square')

    Elliptical interest areas:

    Code:
    Eyelink('Message', ' !V IAREA ELLIPSE 2 647 310 685 349 circle ')

    or free hand interest areas:

    Code:
    Eyelink('Message', ' !V IAREA FREEHAND 3 512,284 612,384 512,484 412,384 diamond')

    Key components to defining each interest area are the shape of the interest areas, the index, its pixel location, and the label associated with that interest area.

    For the index values used, you will want to make sure that you do not overlap index values as this can make certain types of data analysis confusing.

    For the pixel coordinates these will be defined in X,Y pairs that start at the top left corner of the area. For basic shapes, you simply need the top left and bottom right corners to define the interest area, but for freehand objects, you will need a list of points that define each unique point along the shape you wish to define.

    For the label, you will want to make sure that each interest area has a unique label that clearly outlines what is contained within the region or the category of the region.

  5. Target Position Messages

    For experiments in which a moving resource is used (e.g. pursuit tasks), it can be helpful to to keep track of the position of the resource. Data Viewer allows users specify a target via a TARGET_POS message. This message allows you to define the position of the target and give you the ability to calculate the position, velocity, and acceleration data of the target for each individual sample in the sample output report. With such messages, position, velocity, and acceleration can also be displayed in the Temporal Graph View of Data Viewer. You can define up to two targets at a time using the following syntax:

    Code:
    !V TARGET_POS <Target1 Key> <(target1 x, target1 y)> <target 1 visibility> <target 1 step> <Target2 Key> <(target2 x, target2 y)> <target 2 visibility> <target 2 step>

    Where:
    • <Target1 Key> and <Target2 Key>: the tokens to extract the position(s) of target(s);
    • <(target1 x, target1 y)>> and <(target2 x, target2 y)>: the position(s) of the targets. The coordinates must be enclosed in a pair of brackets;
    • <target 1 visibility> and <target 2 visibility>: if 1, the targets are visible; if 0, the targets are hidden;
    • <target 1 step> and <target 2 step>: if 1, the position of the target will be in steps; if 0, the position of the target is interpolated across samples.

    For example, if you wanted to map the position of a target at pixel (351, 278) in a Matlab task you could use the following message:

    Code:
    Eyelink('Message', '!V TARGET_POS TARG1 (351, 278) 1 0')

    Note that if the stimulus is continually moving, you will want to make sure to update this with each new position or at a frequency that allows the interpolation option to accurately represent the movement of the target.

  6. Messaging Offset Protocol

    Data Viewer allows you the ability to offset messages by a number of milliseconds by preceding your message with an integer a positive integer will back stamp that message the number of milliseconds from when the message was received. For instance, if the message "DISPLAY_ONSET" was received at EDF time 345623, then Data Viewer will treat this message as if it happened at that exact time. However, if the message used the text "16 DISPLAY_ONSET" then Data Viewer would back stamp that message 16 milliseconds and record it as having happened at 345607. Likewise, if you sent the message "-16 DISPLAY_ONSET," then Data Viewer would treat this message as if it happened at 345639. This gives you the ability to send messages before or after the events you want them associated with if you can accurately calculate when they should have occurred or will occur.