Issues with using eyelink and the new Builder eye tracking components

OS (e.g. Win10): Win10
PsychoPy version (e.g. 1.84.x): 2021.2.3
Standard Standalone? (y/n) yes
Hi
I am trying to run an experiment using the new build in eyetracker feature. It seems to work just fine, apart from the fact that adding “Eyetracker record” and “Region of interest” components to my experiment drastically slows down responsiveness of Psychopy while running the experiment. I am using a keyboard input to force end of routine, which normally is instantaneous in its response, but with eyetracking components added has an added delay after pressing keyboard input to force end routine, and sometimes doesn’t register the keyboard input at all and requires a second press, something that never happens without the eyetracking components added.
Running the experiment with eyetracker configured and with calibration and validation, but with “Eyetracker record” and “Region of interest” both disabled does not have this issue and behaves as normally expected.
I am using a desttop Eyelink 1000 with default setup.
Does anyone know what my issue is, and if it is fixable?

Thank you for posting the issue. These issues with the Builder integration and EyeLink were brought to our attention last week by another user. Basically the issue is that EyeLink start / stop record calls can take up to 0.5 seconds to run and we did not factor this into the design of the ETRecord functionality. Other supported trackers do not have this issue.

There is no immediate fix for the problem, so currently you can use the Builder interface to configure and calibrate the EyeLink, but can not use the ETRecord or ROI features.

Instead you will need to add custom code to the project where you want to start or stop recording by adding custom code components. To start recording add a new routine and then add the following to the begin routine tab of a custom code component in the routine:

eyetracker.setRecordingState(True)

To stop recording add a new routine and then add the following to the end routine tab of a custom code component:

eyetracker.setRecordingState(False)

Starting and stopping of recording should be done when no keyboard events are expected so if one occurs during that 0.5 second time period it is not dropped.

A proper fix for this will be available in the a future release. Sorry for any inconvience.

Hi sol

Thanks a lot for the response! I will try out your advise. any chance that there is any ressources available for how to set up ROI without the builder interface?

If you have the time, have a look at my other post I put up just a minute ago:

In it I describe what I think is a perhaps somewhat overlapping bug/behavior but this one seems to be timing irrelevant

Hi sol

Thanks again for the help! Is it possible to set up and use ROI using custom code compenent similar to what you described above with Eye Link 1000? or does the ROI component specifically need the etRecord component, and does not function with the method you described?

No, unfortunately not. As you suggested, the ROI component needs an ETRecord component, which for the EyeLink really needs to support starting and stopping recording outside the ‘trial’ routine logic so that the time it takes does not impact presentation timing.

Until the root issues are resolved, you could implement your own region of interest type functionality using some extra custom code that calls something like the following on each frame when you want to monitor eye position:

# Note: eyetracker should already be recording...

# Get last eye position
gpos = eyetracker.getLastGazePosition()

if isinstance(gpos, (tuple, list)):
    # There was an eye position available
    # Check if it is within a visual stim called 'gaze_region_stim'
    if gaze_region_stim.contains(gpos):
        # Add logic for when eye is within the gaze_region_stim
        # ...
        pass
    else:
        # Add logic for when eye is outside the gaze_region_stim
        # ...
        pass

Again, thanks a lot!
I will attempt that approach.

Hi @sol ,

Do you think it would be a good idea to add a blank text component that lasts .5 sec in the start recording routine to wait for eyelink to actually start recording? My trial loop comes right after the start recording routine.

Thanks,
Han

Hi @hanzh

Another option is to add a .5 sec ISI static component to the routine where you start recording, that seems to have worked for me

1 Like

@skjoldan, thanks for thinking of using the ISI as a work around for this particular issue.

Hi @hanzh

Did you end up getting it to work as expected?
I initially thought I had it working without dropped keys, but now the issue has shown up again, and I am now unsure if I ever actually got it working in the first place.

@skjoldan, until the fix for this issue is pulled into a release, when using eyelink, you should start / stop recording when the user is not likely to make a key press / release during the 0.5 seconds it takes to start / stop recording, for example by starting recording right after calibration and stopping recording at the end of the experiment.

Another short term work around might be to wait for the key release before starting / stopping recording so that it will not occur during this 0.5 sec period and gets lost, causing the next press of that key to be ignored because it is being considered an auto-repeat.

A final (last resort) option would be to edit the generated python script from your Builder project and move around some lines of code so that you force psychopy to use a different keyboard event handling backend when you are using the eyelink. I can provide more details on this option if the others just won’t work for your paradigm.

Thank you

hi @sol

Thanks again for your assistance, it has been invaluable!
Incasing both start and stop recording in 0.5 sec ISI both prior and after running the code has again solved the issue, I think the problem was as you described an auto repeat issue. This work around has solved it for now.

Hi, @sol

I also have encounter the same problem.

My experiment asks the participants to read a few articles (no time limit). They can press the left or right arrow key to flip through pages if there are multiple pages in an article. After finishing reading, they can then press the space key to go forward and enter the next article.

Everything is ok until I add the eye-tracking components in the reading session. Because of this bug I need to press the button twice to get what I need, which would probably affect the experimental results. I have tried adding a 0.5 s ISI before all calibration/recording, as well as after the final article as mentioned in the post, but it does not work well.

My experiment requires keyboard inputs during the Eyelink recording, and adding a 0.5 s ISI before/after each press is not possible as the button pressing events can be quite random. Do you have other suggestions for solving the problem?

PS. Does this bug happen only with keyboard inputs? What if I use mouse clicks as inputs instead?

hi @AliceHsiao
It is not quite clear from your description, but if you haven’t, try and add 0.5 sec ISI before AND after both start and stop recording code. see if this maybe fixes it? does the trick in my case.

Your experiment will need to move the start / stop recording calls to parts of the experiment where you do not expect to get keyboard events. For example, right after calibration and then at the end of the experiment. You can do this by starting / stopping recording using code components.

This issue is already fixed in the dev branch of the psychopy source. The fix will be included in the next major release, targeted for January 2022. Sorry for the hack work arounds required until then.

Mouse clicks (via a Builder experiment) should work since Builder experiment mouse events do not use iohub.

Hi @sol @skjoldan

Thanks for your help!

Mouse click works good, but I still want to solve this bug and use keyboard input to control my experiment.

I tried to add 0.5 ISI before calibration, before the trials and before the end of the whole experiment, but it didn’t work.

The way I used to add 0.5 ISI was created a routine that contain a 1 sec text and add a static component (start: 0, stop: 0.5), then inserted it in my experiment.

I think that I used the wrong way to add the 0.5 ISI / static components, and I don’t know how to use code components to add 0.5 ISI, too.

Could you explain more?
It would be great that if you show some example code. :blush:

Thank you very much!!!

hi @AliceHsiao

You want to add the 0.5 sec ISI before and after a custom code component that starts and stops the recording. Note that you cannot use built in etRecord, as it currently doesn’t work properly.
the code you need to use to start and stop recording is
eyetracker.setRecordingState(True)
eyetracker.setRecordingState(False)
respectively.
What have worked for me is to have two routines whenever I start and stop recording. The first of these two routines only has a ISI with a duration of 0.5 sec. The second routine then has a custom code component with “eyetracker.setRecordingState(True)” in the “Begin routine” tab, and then furthermore has a 0.5 sec ISI component as well. After the trial / whole experiment (depending on whether you start and stop recording for every individual trial, or just once for the whole experiment) I then have the same but with “eyetracker.setRecordingState(False)” instead. Thus you have ensured that the start/stop code will run 0.5 sec after the last command, and have at least 0.5 sec before anything else is run after the code.
Hope this makes sense :slight_smile:

1 Like

Hi @skjoldan , Thanks for your help!

About the etRecord components, what kind of issue in it?
I had add etRecord and ROI components in my Reading and Next routine, since I want to record every eye movement after the calibration/validation.

Should I remove both of it then add the ISI routines as you suggested? Or just keep those components and add routines?

Thank you very much!:smiling_face:

Since you are using mutiple routines in a row, you definately do not want to use the current etRecord component. It will start and stop recording in both the Reading and Next routine, when what you probably want is to start at the beginning of reading and stop at the end of Next.

So for now I would suggest using custom code to start / stop recording, something like what @skjoldan has suggested.

PS: We are already in the process of improving etRecord so you can start recording in one routine and stop recording in another. This functionality will not be available until the first official release in 2022.

Hi @sol , Thanks for your help!

I will remove the etRecord component and add ISI routines as you suggested, but do I need to add any other code to make sure the eyelink data would be store in hdf5 files properly?

If I just replace the etRecord component with custom ISI routines and other components remain the same (calibration/validation/ROI), could the eye-tracking record work normally?

I must complete this experiment as soon as possible, so I can’t wait until the official version is updated. :disappointed:

I would try add custom code to fix the keyboard input bug, or I just have to use mouse click to control my experiment.

Thank you very much😊