I have created a simple RSVP paradigm that flashes images at a given rate, but I am getting a latency between calling win.flip() and the time when the screen actually updates of ~85ms with a jitter/variance of ~7ms at best. Is there anything I can do to reduce this latency, or at least decrease the jitter? Is this similar to the values anyone else gets with your devices? How do you typically deal with latencies?
RSVP for Latency Code
from __future__ import division from psychopy import visual, event, core from psychopy.hardware import keyboard from pylsl import StreamInfo, StreamOutlet import os import xlrd import numpy import time import psychopy.iohub ### INPUTS xpix=1600 #your screen width in pixels ypix=900 #your screen height in pixels #how many trials npics=100 #how long you want each image to show t=.5 #seconds #LSL Setup info = StreamInfo('PyMarkerStream', 'Markers', 1, 0, 'string', 'myuidw43536') outlet = StreamOutlet(info) #initialize markers markernames=['s','b','w','k','e','E'] #start, black, white, keypress,end,escape #give you time to start lab recorder t2start=5 print("you have ",t2start," seconds to start lab recorder") time.sleep(t2start) ### #Initialize window win =visual.Window(size=[xpix, ypix],units="pix",fullscr=True, waitBlanking=True,#after a flip wait for the blank before continuing mouseVisible=False) #Initialize image stimulus black_img=visual.ImageStim(win=win,units="pix",size=[1200,800],image="*\black.png",name='black') white_img=visual.ImageStim(win=win,units="pix",size=[1200,800],image="*\white.jpg",name='white') imgs=[black_img, white_img] #list of images mkrs=[1,2] #Initialize a text stimulus to display beginning, end, and breaks txt= visual.TextStim(win=win, pos=(0,0)) #Initialize a Keyboard to check for escape key to end experiment kbend = keyboard.Keyboard() kbpress=keyboard.Keyboard() #Initialize timer to track trials trialtimer=core.CountdownTimer() ###RSVP Experiment Begins outlet.push_sample(markernames)#push start marker print("Starting Experiment") core.wait(1) for j in range(0,npics): #go through each image, start at 1 bc title of column trialtimer.reset() trialtimer.add(t) #adds time to the countdown imgs[j%2].draw()#if even draw black if odd draw white #send marker win.callOnFlip(outlet.push_sample, markernames[int(mkrs[j%2])]) win.flip() while trialtimer.getTime()>0: #keep it on screen for said time #end experiment if escape was pressed if kbend.getKeys(keyList=['escape']): outlet.push_sample(markernames[-1]) win.close() core.quit() #send marker for any other keypress keys=kbpress.getKeys() if keys!=: #if a key was pressed outlet.push_sample(markernames) #push end marker outlet.push_sample(markernames) print("End of Experiment") win.close() core.quit()
To test the latency of the paradigm I changed the images to black and white, sent markers from psychopy to LSL after calling win.flip() and used a photodetector (also sending markers to LSL via arduino serial port) to determine when the screen actually changed. I subtracted the marker time from the time the screen flip was detected. Here’s an example of the results from a gaming computer with a NVIDIA GeForce GTX 1080 with Max-Q Design graphics card:
As you can see, the marker is actually being sent ~85ms early.
Things I have already tried (not exhaustive)
- moving win.flip() before and after sending the marker
- simplifying the code in the for loop and eliminating the keyboard component
- tested timing of arduino/photodetector (consistently takes only 126µs to read and send the value)
- all of the things mentioned on the millisecond precision page, (turning off triple buffer, 100% scaling, adjusting other graphics card settings, etc.)
The only thing that affected the latency was running the exact same experiment on a gaming computer vs another laptop with Intel UHD Graphics 630 and NVIDIA Quadro P620 graphics cards. On the other computer, both cards led to a worse average latency of ~110ms and similar jitter of ~10ms. Is there anything else I can try?