I have an experiment where the basic flow is that the participants are shown a word for 2 seconds, then they see a picture and have to make a sentence using that word that also describes the picture (with the option to press the space bar to end the trial early, otherwise it is displayed for 12 seconds and that’s how long they have to say their sentence), and then they see a fixation cross at the end before the trial loop repeats. These 3 events are all separate routines (this was originally made in builder and then converted to code to add some other things that aren’t part of this loop).
This works fine and does exactly what I want it to do, although if the participant ever finishes right on the 12 second mark and actually presses the space on the fixation cross (or if they were to ever press it on the verb) the next picture skips, and then the entire experiment starts to slow down and the space key press to move to the next picture stops working from that point forward in the experiment, and the recording audio files get messed up too.
I’ve tried a few things to prevent participants from being able to press the space at any point other than right after the picture, such as turning the keyboard off for any point other than when the picture is displayed, and also clearing the keyboard events / clearing all events right before the picture routine starts, or after the fixation cross routine ends, and a few other points, but nothing seems to work and it just always skips the next picture.
I’ve been able to modify how I give the instructions to the participant when I’m with them in the lab, but it still happens every now and again, and I’d love to find a solution that still allows them to have the ability to end the microphone recording when they’ve finished their sentence, even though that will be at varying timepoints for each picture/sentence.
Since I would have thought either clearing the events or turning off the keyboard would have worked, I’m also wondering if I’m either doing those wrong in the code (the lines are included but commented out) or if the keypress isn’t the actual problem and it’s something else I’m not considering - especially since the verb and fixation cross trials aren’t set up to expect a keypress of any sort, so maybe something is happening at a point I’m not considering.
I’ve included the code for the image loop with the parts I’ve added in bold, non-bold is what the builder experiment was written to when I had it converted to python code, and also I’ve included the entire code file in case that is helpful as well.
# set up handler to look after randomisation of conditions etc
trials = data.TrialHandler(nReps=1.0, method='sequential',
extraInfo=expInfo, originPath=-1,
trialList=data.importConditions(LISTNAME, selection=pseudo_2),
seed=None, name='trials')
thisExp.addLoop(trials) # add the loop to the experiment
thisTrial = trials.trialList[0] # so we can initialise stimuli with some values
# abbreviate parameter names if possible (e.g. rgb = thisTrial.rgb)
if thisTrial != None:
for paramName in thisTrial:
exec('{} = thisTrial[paramName]'.format(paramName))
for thisTrial in trials:
currentLoop = trials
# abbreviate parameter names if possible (e.g. rgb = thisTrial.rgb)
if thisTrial != None:
for paramName in thisTrial:
exec('{} = thisTrial[paramName]'.format(paramName))
#defaultKeyboard.clearEvents()
# --- Prepare to start Routine "give_verb" ---
continueRoutine = True
routineForceEnded = False
**#defaultKeyboard.clearEvents()**
# update component parameters for each repeat
verb_text.setText(Verb)
# keep track of which components have finished
give_verbComponents = [verb_text]
for thisComponent in give_verbComponents:
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")
frameN = -1
# --- Run Routine "give_verb" ---
while continueRoutine and routineTimer.getTime() < 2.0:
# get current time
t = routineTimer.getTime()
tThisFlip = win.getFutureFlipTime(clock=routineTimer)
tThisFlipGlobal = win.getFutureFlipTime(clock=None)
frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
# update/draw components on each frame
# *verb_text* updates
if verb_text.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
# keep track of start time/frame for later
verb_text.frameNStart = frameN # exact frame index
verb_text.tStart = t # local t and not account for scr refresh
verb_text.tStartRefresh = tThisFlipGlobal # on global time
win.timeOnFlip(verb_text, 'tStartRefresh') # time at next scr refresh
# add timestamp to datafile
thisExp.timestampOnFlip(win, 'verb_text.started')
verb_text.setAutoDraw(True)
if verb_text.status == STARTED:
# is it time to stop? (based on global clock, using actual start)
if tThisFlipGlobal > verb_text.tStartRefresh + 2.0-frameTolerance:
# keep track of stop time/frame for later
verb_text.tStop = t # not accounting for scr refresh
verb_text.frameNStop = frameN # exact frame index
# add timestamp to datafile
thisExp.timestampOnFlip(win, 'verb_text.stopped')
verb_text.setAutoDraw(False)
# 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
routineForceEnded = True
break
continueRoutine = False # will revert to True if at least one component still running
for thisComponent in give_verbComponents:
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()
#defaultKeyboard.clearEvents()
# --- Ending Routine "give_verb" ---
for thisComponent in give_verbComponents:
if hasattr(thisComponent, "setAutoDraw"):
thisComponent.setAutoDraw(False)
# using non-slip timing so subtract the expected duration of this Routine (unless ended on request)
if routineForceEnded:
routineTimer.reset()
else:
routineTimer.addTime(-2.000000)
**#defaultKeyboard.clearEvents()**
# --- Prepare to start Routine "trial" ---
continueRoutine = True
routineForceEnded = False
# update component parameters for each repeat
# Run 'Begin Routine' code from code
trial_ori = ori.pop() #takes the orientation, either LR or RL
thisExp.addData('ORIENTATION' , trial_ori)
if trial_ori == "RL":
IMG = IMG_FILE_RL
if trial_ori == "LR":
IMG = IMG_FILE_LR
nme = str(IMG)[:-4]+".wav" #to name the audio file based off the image name
print(nme)
stimulus.setImage(IMG)
key_resp_end_mic.keys = []
key_resp_end_mic.rt = []
_key_resp_end_mic_allKeys = []
# keep track of which components have finished
trialComponents = [stimulus, key_resp_end_mic, mic]
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")
frameN = -1
#defaultKeyboard.clearEvents()
# --- Run Routine "trial" ---
while continueRoutine and routineTimer.getTime() < 15.5:
# get current time
t = routineTimer.getTime()
tThisFlip = win.getFutureFlipTime(clock=routineTimer)
tThisFlipGlobal = win.getFutureFlipTime(clock=None)
frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
# update/draw components on each frame
# *stimulus* updates
if stimulus.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
# keep track of start time/frame for later
stimulus.frameNStart = frameN # exact frame index
stimulus.tStart = t # local t and not account for scr refresh
stimulus.tStartRefresh = tThisFlipGlobal # on global time
win.timeOnFlip(stimulus, 'tStartRefresh') # time at next scr refresh
# add timestamp to datafile
thisExp.timestampOnFlip(win, 'stimulus.started')
stimulus.setAutoDraw(True)
if stimulus.status == STARTED:
# is it time to stop? (based on global clock, using actual start)
if tThisFlipGlobal > stimulus.tStartRefresh + 15.5-frameTolerance:
# keep track of stop time/frame for later
stimulus.tStop = t # not accounting for scr refresh
stimulus.frameNStop = frameN # exact frame index
# add timestamp to datafile
thisExp.timestampOnFlip(win, 'stimulus.stopped')
stimulus.setAutoDraw(False)
# *key_resp_end_mic* updates
waitOnFlip = False
if key_resp_end_mic.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
# keep track of start time/frame for later
key_resp_end_mic.frameNStart = frameN # exact frame index
key_resp_end_mic.tStart = t # local t and not account for scr refresh
key_resp_end_mic.tStartRefresh = tThisFlipGlobal # on global time
win.timeOnFlip(key_resp_end_mic, 'tStartRefresh') # time at next scr refresh
# add timestamp to datafile
thisExp.timestampOnFlip(win, 'key_resp_end_mic.started')
key_resp_end_mic.status = STARTED
# keyboard checking is just starting
waitOnFlip = True
win.callOnFlip(key_resp_end_mic.clock.reset) # t=0 on next screen flip
win.callOnFlip(key_resp_end_mic.clearEvents, eventType='keyboard') # clear events on next screen flip
if key_resp_end_mic.status == STARTED:
# is it time to stop? (based on global clock, using actual start)
if tThisFlipGlobal > key_resp_end_mic.tStartRefresh + 15.5-frameTolerance:
# keep track of stop time/frame for later
key_resp_end_mic.tStop = t # not accounting for scr refresh
key_resp_end_mic.frameNStop = frameN # exact frame index
# add timestamp to datafile
thisExp.timestampOnFlip(win, 'key_resp_end_mic.stopped')
key_resp_end_mic.status = FINISHED
if key_resp_end_mic.status == STARTED and not waitOnFlip:
theseKeys = key_resp_end_mic.getKeys(keyList=['space'], waitRelease=False)
_key_resp_end_mic_allKeys.extend(theseKeys)
if len(_key_resp_end_mic_allKeys):
key_resp_end_mic.keys = _key_resp_end_mic_allKeys[-1].name # just the last key pressed
key_resp_end_mic.rt = _key_resp_end_mic_allKeys[-1].rt
#look into clearing the keypresses at the beginning of the routine
#psychopy.event.clearEvents(eventType=None)[source]
#Clears all events currently in the event buffer.
#Optional argument, eventType, specifies only certain types to be cleared.
#Parameters
#eventTypeNone, ‘mouse’, ‘joystick’, ‘keyboard’
#If this is not None then only events of the given type are cleared
# mic updates
if mic.status == NOT_STARTED and t >= 0.0-frameTolerance:
# keep track of start time/frame for later
mic.frameNStart = frameN # exact frame index
mic.tStart = t # local t and not account for scr refresh
mic.tStartRefresh = tThisFlipGlobal # on global time
win.timeOnFlip(mic, 'tStartRefresh') # time at next scr refresh
# add timestamp to datafile
thisExp.addData('mic.started', t)
# start recording with mic
mic.start()
mic.status = STARTED
if mic.status == STARTED:
# update recorded clip for mic
mic.poll()
**if mic.status == STARTED:**
** if event.getKeys(['space']):**
** mic.stop()**
** mic.status == FINISHED**
** continueRoutine = False**
if mic.status == STARTED:
# is it time to stop? (based on global clock, using actual start)
if tThisFlipGlobal > mic.tStartRefresh + 15.0-frameTolerance:
# keep track of stop time/frame for later
mic.tStop = t # not accounting for scr refresh
mic.frameNStop = frameN # exact frame index
# add timestamp to datafile
thisExp.addData('mic.stopped', t)
# stop recording with mic
mic.stop()
mic.status = FINISHED
# 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
routineForceEnded = True
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()
# --- Ending Routine "trial" ---
for thisComponent in trialComponents:
if hasattr(thisComponent, "setAutoDraw"):
thisComponent.setAutoDraw(False)
# check responses
if key_resp_end_mic.keys in ['', [], None]: # No response was made
key_resp_end_mic.keys = None
trials.addData('key_resp_end_mic.keys',key_resp_end_mic.keys)
if key_resp_end_mic.keys != None: # we had a response
trials.addData('key_resp_end_mic.rt', key_resp_end_mic.rt)
# tell mic to keep hold of current recording in mic.clips and transcript (if applicable) in mic.scripts
# this will also update mic.lastClip and mic.lastScript
tag = data.utils.getDateStr()
#audio files were not saving properly, found this way to save them from other forum code
**audioClip = mic.getRecording()**
** print(audioClip.duration)**
** print(os.path.join(micRecFolder, '%s_%s.wav' % (TRIALCOUNTER,nme)))**
** audioClip.save(os.path.join(micRecFolder, '%s_%s.wav' % (TRIALCOUNTER, nme)))**
** TRIALCOUNTER += 1**
trials.addData('mic.clip', os.path.join(micRecFolder, 'recording_mic_%s.wav' % tag))
# the Routine "trial" was not non-slip safe, so reset the non-slip timer
if routineForceEnded:
routineTimer.reset()
else:
routineTimer.addTime(-12.500000)
# --- Prepare to start Routine "break_2" ---
continueRoutine = True
routineForceEnded = False
# update component parameters for each repeat
key_resp8.keys = []
key_resp8.rt = []
_key_resp8_allKeys = []
# keep track of which components have finished
break_2Components = [key_resp8, polygon]
for thisComponent in break_2Components:
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")
frameN = -1
**#defaultKeyboard.clearEvents()**
# --- Run Routine "break_2" ---
while continueRoutine and routineTimer.getTime() < 1.5:
# get current time
t = routineTimer.getTime()
tThisFlip = win.getFutureFlipTime(clock=routineTimer)
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_resp8* updates
waitOnFlip = False
if key_resp8.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
# keep track of start time/frame for later
key_resp8.frameNStart = frameN # exact frame index
key_resp8.tStart = t # local t and not account for scr refresh
key_resp8.tStartRefresh = tThisFlipGlobal # on global time
win.timeOnFlip(key_resp8, 'tStartRefresh') # time at next scr refresh
# add timestamp to datafile
thisExp.timestampOnFlip(win, 'key_resp8.started')
key_resp8.status = STARTED
# keyboard checking is just starting
waitOnFlip = True
win.callOnFlip(key_resp8.clock.reset) # t=0 on next screen flip
win.callOnFlip(key_resp8.clearEvents, eventType='keyboard') # clear events on next screen flip
if key_resp8.status == STARTED and not waitOnFlip:
theseKeys = key_resp8.getKeys(keyList=['p'], waitRelease=False)
_key_resp8_allKeys.extend(theseKeys)
if len(_key_resp8_allKeys):
key_resp8.keys = _key_resp8_allKeys[-1].name # just the last key pressed
key_resp8.rt = _key_resp8_allKeys[-1].rt
# a response ends the routine
#continueRoutine = False
**if event.getKeys(['p']):**
** time.sleep(20)**
# *polygon* updates
if polygon.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
# keep track of start time/frame for later
polygon.frameNStart = frameN # exact frame index
polygon.tStart = t # local t and not account for scr refresh
polygon.tStartRefresh = tThisFlipGlobal # on global time
win.timeOnFlip(polygon, 'tStartRefresh') # time at next scr refresh
# add timestamp to datafile
thisExp.timestampOnFlip(win, 'polygon.started')
polygon.setAutoDraw(True)
if polygon.status == STARTED:
# is it time to stop? (based on global clock, using actual start)
if tThisFlipGlobal > polygon.tStartRefresh + 1.5-frameTolerance:
# keep track of stop time/frame for later
polygon.tStop = t # not accounting for scr refresh
polygon.frameNStop = frameN # exact frame index
# add timestamp to datafile
thisExp.timestampOnFlip(win, 'polygon.stopped')
polygon.setAutoDraw(False)
# 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
routineForceEnded = True
break
continueRoutine = False # will revert to True if at least one component still running
for thisComponent in break_2Components:
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()
# --- Ending Routine "break_2" ---
for thisComponent in break_2Components:
if hasattr(thisComponent, "setAutoDraw"):
thisComponent.setAutoDraw(False)
# check responses
if key_resp8.keys in ['', [], None]: # No response was made
key_resp8.keys = None
trials.addData('key_resp8.keys',key_resp8.keys)
if key_resp8.keys != None: # we had a response
trials.addData('key_resp8.rt', key_resp8.rt)
# the Routine "break_2" was not non-slip safe, so reset the non-slip timer
routineTimer.reset()
thisExp.nextEntry()
# completed 1.0 repeats of 'trials'
dativeversion_FINAL_WORKING_BREAKTIMER_ONTIMER.py (59.1 KB)
.