Hello,
I have set up an reaction-time + eye-tracking experiment using iohub. Everything is working well except for my data output - I get eye data and keyboard data sync'd and sent to the hdf5 file, but my stimulus information only appears in the log file (along with the keyboard data).
So I am wondering how to include my stimulus information (ie time and type of display) along with the keyboard and eye data using iohub?
Just as an aside - I thought of comparing keyboard times between the hdf5 file and the log file (and if there was a constant difference to simply subtract that from the stimulus times in the log file), but the difference in timing was not constant - and varied from 0 to 33 ms (which is long enough to be problematic). I suspect the timing of iohub to be more accurate than the log file, but I wonder how I can verify that?
Thank you,
Silvia
PS, Here are some relevant snippets of my code:
...
## stuff relevant to setting up eyetracker & iohub ##
eyetracker = True
if eyetracker:
try:
from psychopy.iohub import EventConstants,ioHubConnection,load,Loader
from psychopy.iohub.util import NumPyRingBuffer
from psychopy.data import getDateStr
# Load the specified iohub configuration file converting it to a python dict.
io_config=load(file('SRR_eyelink_std.yaml','r'), Loader=Loader)
# Add / Update the session code to be unique. Here we use the psychopy getDateStr() function for session code generation
session_info=io_config.get('data_store').get('session_info')
session_info.update(code="S_%s"%(getDateStr()))
# Create an ioHubConnection instance, which starts the ioHubProcess, and informs it of the requested devices and their configurations.
io=ioHubConnection(io_config)
iokeyboard=io.devices.keyboard
mouse=io.devices.mouse
experiment = io.devices.experiment
if io.getDevice('tracker'):
eyetracker=io.getDevice('tracker')
win.winHandle.minimize()
eyetracker.runSetupProcedure() ##setup and calibration are here
win.winHandle.activate()
win.winHandle.maximize()
except Exception, e:
import sys
print "!! Error starting ioHub: ",e," Exiting..."
sys.exit(1)
display_gaze=False
x,y=0,0
...
## stuff relevant to looping through the stimulus table ##
startTime = globalClock.getTime()
t=0; DisplayClock.reset()
frameN=-1
trialCount = 0
i = 0;
if eyetracker:
heldFixation = True #unless otherwise
io.clearEvents('all')
eyetracker.setRecordingState(True)
for i in xrange(0, len(stimulus_table)):
stim = stimulus_table[i];
txt = "%d" % stim
cue.setText(txt)
isi = 60 # mask time
ISI = 72 #total time
DisplayComponents=[]#to keep track of which have finished
DisplayComponents.append(mask)
DisplayComponents.append(circle)
for thisComponent in DisplayComponents:
if hasattr(thisComponent,'status'): thisComponent.status = NOT_STARTED
#-------Start Routine "Display"-------
continueRoutine = True
while continueRoutine:
# get current time
t = DisplayClock.getTime()
frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
# update/draw components on each frame
#*cue* updates
if frameN>=0 and cue.status==NOT_STARTED:
#keep track of start time/frame for later
cue.tStart=t#underestimates by a little under one frame
cue.frameNStart=frameN#exact frame index
cue.setAutoDraw(True)
elif cue.status==STARTED and frameN>=(cue.frameNStart+12):
cue.setAutoDraw(False)
#*mask* updates
if (cue.status==FINISHED) and mask.status==NOT_STARTED:
#keep track of start time/frame for later
mask.tStart=t#underestimates by a little under one frame
mask.frameNStart=frameN#exact frame index
mask.setAutoDraw(True)
elif mask.status==STARTED and frameN>=(mask.frameNStart+isi):
mask.setAutoDraw(False)
if not continueRoutine: # a component has requested a forced-end of Routine
break
continueRoutine = False # will revert to True if at least one component still running
for thisComponent in DisplayComponents:
if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
continueRoutine = True
break # at least one component has not yet finished
# refresh the screen
if continueRoutine: # don't flip if this routine is over or we'll get a blank screen
win.flip()
trialCount=trialCount + 1
for thisComponent in DisplayComponents:
endTime=globalClock.getTime()
logging.flush() #store info to log
if hasattr(thisComponent,"setAutoDraw"): thisComponent.setAutoDraw(False)
if eyetracker:
eyetracker.setRecordingState(False)
io.quit()
win.close()
core.quit()