Computer Programming
For Psychologists

Getting started with the Tobii Pro Fusion


Getting started

The past few days I got the opportunity to unpack and set up an experiment with the new Tobii Pro Fusion eye tracker! The eye tracker is delivered in a nice looking case that also contained several magnetic plates that can be attached to a computer monitor. If you have recent computer with a USB-C port, all you have to do is connect the eyetracker and you are ready to go. If you do not have a USB-C port, the package also contains a USB adapter as well as a power cable with different power socket adapters. The latter is needed because older USB ports are not able to deliver the power needed to operate the eye tracker.

tobii_pro_fusion.jpg
Figure 1: The Tobii Pro Fusion

Tobii Pro Eye Tracker Manager

Before you can use the eye tracker on your computer, you need to install the Tobii Pro Eye Tracker Manager. This is a convenient software tool that allows you to configure in combination with the system that you are using. In addition, it provides an intuitive interface that allows you to quickly callibrate new participants.

eye_tracker_manager.png

Figure 2: After configuring the eye tracker we are ready to go!

Using the eyetracker in Python

Although I have not used it myself, Tobii offers another software tool called Tobii Pro Lab. This can be used to design experiments that use the eye tracker. Since we had already programmed the experiment in PsychoPy (using the Anaconda Python distribution with PsychoPy installed as a module), we planned to use the eyetracker from within Python.

Overall, this was not too difficult to achieve. Tobii has developed two modules (part of the Tobii Pro SDK) that greatly facilitate the work of interacting with the eyetracker. The tobii_research module is used to collect data from the eyetracker. The tobii_research_addons module can be used to validate calibration results.

The only thing that took me a while to figure out (probably because I did not read the Tobii documentation properly) is that the Tobii modules are not compatible with Python versions > 3.6. When setting up a computer for an experiment I always start with a fresh intallation of all the tools, which means my Python version was 3.8.5. This lead to the following error when trying to import the Tobii modules (which was resolved by reverting to Python 3.6.12):

    from tobiiresearch.interop.python3 import tobii_research_interop

ImportError: DLL load failed while importing tobii_research_interop: The specified module could not be found.

The documentation on the Tobii website is an excellent resource with many examples that help you get started. 

Recording data

To collect data, Tobii requires that you define a callback function. This is a function that has the following signature:

def gaze_data_received(gaze_data):
   # Do stuff with gaze data

When setting up the eyetracker, the eyetracker is first defined using its address (which can be found in the Eye Tracker Manager). To collect data, you have to subscribe to the EYETRACKER_GAZE_DATA and provide the name of the callback function that you defined. Optionally you can configure that the values in each data sample are coded as a dictionary. I found this a useful option because I could not find a good overview of the actual data that you get for each sample.

import tobii_research as tr

eyetracker_address = 'tobii-prp://TPFC2-010200146384'
eyetracker = tr.EyeTracker(eyetracker_address)
eyetracker.subscribe_to(tr.EYETRACKER_GAZE_DATA, gaze_data_callback, as_dictionary=True)

Using the above code, the gaze_data variable in the callback function will contain a lot of data for each sample. After inspecting the content of the gaze_data variable, I decided to retain the following keys:

device_time_stamp  
system_time_stamp  
left_gaze_point_on_display_area  
left_gaze_point_validity  
left_pupil_diameter  
left_pupil_validity  
right_gaze_point_on_display_area  
right_gaze_point_validity  
right_pupil_diameter  
right_pupil_validity  


Saving data

To save eye tracking data to a file, I used the following approach:

1. Define an eyetracker_datastream variable, which I initially set to None. 

2. In the experiment, whenever I need to record data I create a file handle using the eyetracker_datastream variable. As soon as I have completed data collection I set this variable back to None

3. In the callback function, I refer to the global eyetracker_datastream variable. If it is not set to None, I know that it is now a file handle and I can write incoming samples to this file stream.

# Variable for creating file handle
eyetracker_datastream = None

# Definition of the callback function
def gaze_data_callback(gaze_data):
    global eyetracker_datastream
    
    if eyetracker_datastream is not None:
        eyetracker_datastream.write(gaze_data['left_gaze_point_on_display_area'][0])


# If data is needed in the experiment, use the following code
# The filename should be different each time so that it doesn't overwrite
eyetracker_datastream = open('eyetracker_data.csv', 'w')

# When done, close the file handle and set the variable back to None
eyetracker_datastream.close()
eyetracker_datastream = None

One downside of using the Tobii Pro SDK to record data is that you only get access to the raw data. This means that you will have to further process the data yourself if you want to extract measures such as fixations.