Hi everyone
OS : Windows 10
PsychoPy version (e.g. 1.84.x): 2021.2.3
Standard Standalone? If not then what?: Y
What are you trying to achieve?:
I’m creating an eye-tracking experiment with two screens, one for
the participants, and one for the experimenters to monitor.
The whole experiment would freeze after a successful Calibration routine. In other words, when I press the space key to end the calibration, the participant screen would turn black immediately.
The psychopy program seems still working, but not responding to any key press, even I pressing the ‘escape’ key to abort the experiment.
What did you try to make it work?:
Everything is good when there was only one screen.
In order to create a two-screen experiment, I used Builder to create the whole experiment and used Coder to add second screen codes. I used “MouseGaze” to test, but I also tried setting eye-tracker to Eyelink without really attaching to the machine, and the problem is still there.
In addition, I tried to set “screen = 1 & screen = 2” and “screen = 0 & screen = 1” respectively. Sometimes the program works successfully when I just change it, but will fail again soon.
Here is the code.
# Start Code - component code to be run after the window creation
# Setup the Window
win = visual.Window(
size=[1280, 1024], fullscr=True, screen=1,
winType='pyglet', allowGUI=False, allowStencil=False,
monitor='testMonitor', color=[0,0,0], colorSpace='rgb',
blendMode='avg', useFBO=True,
units='height')
win2 = visual.Window(
size=[960, 768], fullscr=False, screen=2,
winType='pyglet', allowGUI=False, allowStencil=False,
monitor='testMonitor', color=[0,0,0], colorSpace='rgb',
blendMode='avg', useFBO=True,
units='height')
# store frame rate of monitor if we can measure it
expInfo['frameRate'] = win.getActualFrameRate()
if expInfo['frameRate'] != None:
frameDur = 1.0 / round(expInfo['frameRate'])
else:
frameDur = 1.0 / 60.0 # could not measure, so guess
# Setup eyetracking
ioDevice = 'eyetracker.hw.mouse.EyeTracker'
ioConfig = {
ioDevice: {
'name': 'tracker',
'controls': {
'move': [],
'blink':('MIDDLE_BUTTON',),
'saccade_threshold': 0.5,
}
}
}
ioSession = '1'
if 'session' in expInfo:
ioSession = str(expInfo['session'])
ioServer = io.launchHubServer(window=win, experiment_code='dual_eyetrackerSetup', session_code=ioSession, datastore_name=filename, **ioConfig)
eyetracker = ioServer.getDevice('tracker')
# create a default keyboard (e.g. to check for escape)
defaultKeyboard = keyboard.Keyboard()
# Initialize components for Routine "trial"
trialClock = core.Clock()
key_resp = keyboard.Keyboard()
text = visual.TextStim(win=win, name='text',
text='Success',
font='Open Sans',
pos=(0, 0), height=0.1, wrapWidth=None, ori=0.0,
color='white', colorSpace='rgb', opacity=None,
languageStyle='LTR',
depth=-1.0);
text_sup = visual.TextStim(win=win2, name='text_sup',
text='support',
font='Open Sans',
pos=(0, 0), height=0.1, wrapWidth=None, ori=0.0,
color='white', colorSpace='rgb', opacity=None,
languageStyle='LTR',
depth=-2.0);
# Create some handy timers
globalClock = core.Clock() # to track the time since experiment started
routineTimer = core.CountdownTimer() # to track time remaining of each (non-slip) routine
# -------Run Routine 'calibration'-------
# define target for calibration
calibrationTarget = visual.TargetStim(win,
name='calibrationTarget',
radius=0.01, fillColor='', borderColor='black', lineWidth=2.0,
innerRadius=0.0035, innerFillColor='green', innerBorderColor='black', innerLineWidth=2.0,
colorSpace='rgb', units=None
)
# define parameters for calibration
calibration = hardware.eyetracker.EyetrackerCalibration(win,
eyetracker, calibrationTarget,
units=None, colorSpace='rgb',
progressMode='time', targetDur=1.5, expandScale=1.5,
targetLayout='THREE_POINTS', randomisePos=True,
movementAnimation=True, targetDelay=1.0
)
# run calibration
calibration.run()
# clear any keypresses from during calibration so they don't interfere with the experiment
defaultKeyboard.clearEvents()
# the Routine "calibration" was not non-slip safe, so reset the non-slip timer
routineTimer.reset()
# -------Run Routine 'validation'-------
# define target for validation
validationTarget = visual.TargetStim(win,
name='validationTarget',
radius=0.01, fillColor='', borderColor='black', lineWidth=2.0,
innerRadius=0.0035, innerFillColor='green', innerBorderColor='black', innerLineWidth=2.0,
colorSpace='rgb', units=None
)
# define parameters for validation
validation = iohub.ValidationProcedure(win,
target=validationTarget,
gaze_cursor='green',
positions='THREE_POINTS', randomize_positions=True,
expand_scale=1.5, target_duration=1.5,
enable_position_animation=True, target_delay=1.0,
progress_on_key=None,
show_results_screen=True, save_results_screen=False,
color_space='rgb', unit_type=None
)
# run validation
validation.run()
# clear any keypresses from during validation so they don't interfere with the experiment
defaultKeyboard.clearEvents()
# the Routine "validation" was not non-slip safe, so reset the non-slip timer
routineTimer.reset()
# ------Prepare to start Routine "trial"-------
continueRoutine = True
# update component parameters for each repeat
key_resp.keys = []
key_resp.rt = []
_key_resp_allKeys = []
# keep track of which components have finished
trialComponents = [key_resp, text, text_sup]
for thisComponent in trialComponents:
thisComponent.tStart = None
thisComponent.tStop = None
thisComponent.tStartRefresh = None
thisComponent.tStopRefresh = None
if hasattr(thisComponent, 'status'):
thisComponent.status = NOT_STARTED
# reset timers
t = 0
_timeToFirstFrame = win.getFutureFlipTime(clock="now")
trialClock.reset(-_timeToFirstFrame) # t0 is time of first possible flip
frameN = -1
# -------Run Routine "trial"-------
while continueRoutine:
# get current time
t = trialClock.getTime()
tThisFlip = win.getFutureFlipTime(clock=trialClock)
tThisFlipGlobal = win.getFutureFlipTime(clock=None)
frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
# update/draw components on each frame
# *key_resp* updates
waitOnFlip = False
if key_resp.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
# keep track of start time/frame for later
key_resp.frameNStart = frameN # exact frame index
key_resp.tStart = t # local t and not account for scr refresh
key_resp.tStartRefresh = tThisFlipGlobal # on global time
win.timeOnFlip(key_resp, 'tStartRefresh') # time at next scr refresh
key_resp.status = STARTED
# keyboard checking is just starting
waitOnFlip = True
win.callOnFlip(key_resp.clock.reset) # t=0 on next screen flip
win.callOnFlip(key_resp.clearEvents, eventType='keyboard') # clear events on next screen flip
if key_resp.status == STARTED and not waitOnFlip:
theseKeys = key_resp.getKeys(keyList=['space'], waitRelease=False)
_key_resp_allKeys.extend(theseKeys)
if len(_key_resp_allKeys):
key_resp.keys = _key_resp_allKeys[-1].name # just the last key pressed
key_resp.rt = _key_resp_allKeys[-1].rt
# a response ends the routine
continueRoutine = False
# *text* updates
if text.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
# keep track of start time/frame for later
text.frameNStart = frameN # exact frame index
text.tStart = t # local t and not account for scr refresh
text.tStartRefresh = tThisFlipGlobal # on global time
win.timeOnFlip(text, 'tStartRefresh') # time at next scr refresh
text.setAutoDraw(True)
# *text_sup* updates
if text_sup.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
# keep track of start time/frame for later
text_sup.frameNStart = frameN # exact frame index
text_sup.tStart = t # local t and not account for scr refresh
text_sup.tStartRefresh = tThisFlipGlobal # on global time
win.timeOnFlip(text_sup, 'tStartRefresh') # time at next scr refresh
text_sup.setAutoDraw(True)
# check for quit (typically the Esc key)
if endExpNow or defaultKeyboard.getKeys(keyList=["escape"]):
core.quit()
# check if all components have finished
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 trialComponents:
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()
win2.flip()
# -------Ending Routine "trial"-------
for thisComponent in trialComponents:
if hasattr(thisComponent, "setAutoDraw"):
thisComponent.setAutoDraw(False)
# check responses
if key_resp.keys in ['', [], None]: # No response was made
key_resp.keys = None
thisExp.addData('key_resp.keys',key_resp.keys)
if key_resp.keys != None: # we had a response
thisExp.addData('key_resp.rt', key_resp.rt)
thisExp.addData('key_resp.started', key_resp.tStartRefresh)
thisExp.addData('key_resp.stopped', key_resp.tStopRefresh)
thisExp.nextEntry()
thisExp.addData('text.started', text.tStartRefresh)
thisExp.addData('text.stopped', text.tStopRefresh)
thisExp.addData('text_sup.started', text_sup.tStartRefresh)
thisExp.addData('text_sup.stopped', text_sup.tStopRefresh)
# the Routine "trial" was not non-slip safe, so reset the non-slip timer
routineTimer.reset()
# Flip one final time so any remaining win.callOnFlip()
# and win.timeOnFlip() tasks get executed before quitting
win.flip()
win2.flip()
# these shouldn't be strictly necessary (should auto-save)
thisExp.saveAsWideText(filename+'.csv', delim='auto')
thisExp.saveAsPickle(filename)
logging.flush()
# make sure everything is closed down
thisExp.abort() # or data files will save again on exit
win.close()
win2.close()
core.quit()
Thank you for spending time answering my questions, any help would be greatly appreciated.