I am in the process of replacing EPrime with Psychopy in my EEG lab. The EEG software I am trying to integrate with is EGI Netstation 5.3. Using “import egi.simple as egi” I can control Netstation fine and send triggers associated with stimuli. My problem is in the variability of the timing of these triggers.
To test the accuracy of the trigger timing, i.e. what is the latency delay between an image appearing onscreen and an associated trigger code being recorded in the EEG file, I have a flashing white square appearing onscreen with a photometer embedding a code at the onset of the square in the EEG. The latency of the photometer code is compared to the latency of the trigger code sent from Psychopy. Currently the mean delay is ~47ms, not a problem in itself, but the variability is very large (most values greater than 6ms from the mean), see the attached jpeg
Using exactly the same hardware and Eprime I can get the latency delay down to a mean of 17ms with an SD of 2ms. So fundamentally I know that the hardware is capable of doing what I need it to. My spec and code are detailed at the bottom of this message.
Given this situation I have the following specific questions:
- Has anyone else set up Psychopy successfully with EGI Netstation and verified the trigger latencies?
- Should I consider replacing graphics cards if I know that with EPrime the latencies are stable? When I run the benchmark wizard I do get an warning about refresh stability, see attached excel file. benchmarkReport.xlsx (10.2 KB)
- Is there anything dumb in my code that could be causing latency variability, e.g. using callonFlips or the way I have structured my loops?
- Are dual screens likely to make timing problems worse? I have sometimes found this to be the case in EPrime.
########## tech spec ##############
PC - Dell Optiplex 7020, i5,3.3Ghz, 4GB RAM
Monitor - Dell LCD E2214Hb
Graphics card - Intel HD Graphics 4600
Visual timing hardware - EGI provided photometer with DIN converter
######## code used for visual timing tests ###########
from __future__ import absolute_import, division import pandas as pd # these are for reading from excel files import random, os, glob, pylab from psychopy import visual, logging, core, event, data , sound, gui,locale_setup# import some libraries from PsychoPy from psychopy.constants import (NOT_STARTED, STARTED, PLAYING, PAUSED, STOPPED, FINISHED, PRESSED, RELEASED, FOREVER) import numpy as np # whole numpy lib is available, prepend 'np.' from numpy import (sin, cos, tan, log, log10, pi, average, sqrt, std, deg2rad, rad2deg, linspace, asarray) import os # handy system and path functions import sys # to get file system encoding import time import csv #useful for handling csv files totalloops=30 duration=10 import egi.simple as egi ms_localtime = egi.ms_localtime ns = egi.Netstation() ns.connect('10.10.10.42', 55513) # sample address and port -- change according to your network settings ns.initialize('10.10.10.42', 55513) ns.BeginSession() ns.sync() #create a window mywin = visual.Window(fullscr=True, monitor="testMonitor", units="deg", color ='black') mywin.setMouseVisible(False) whiterect = visual.Rect(mywin, width=10,height=10,pos=[0,0],fillColor='white') blackrect = visual.Rect(mywin, width=10,height=10,pos=[0,0],fillColor='black',lineColor='black') ns.StartRecording() count=0 while count < (totalloops): ns.sync() mywin.callOnFlip(ns.SendSimpleEvent,'stm-' 'stm-', timestamp=egi.ms_localtime()) for frameN in range (duration): whiterect.draw() mywin.flip() for frameN in range (duration): blackrect.draw() mywin.flip() count+=1 mywin.close ns.StopRecording() ns.EndSession()