So @tjmccormick5 and I are colleagues, and we got together and solved the problem, the short answer is that the Keyboard builder component needed to be removed, since it was clearing events and our event.getKeys() was then messed up.
But I would really appreciate it if @Michael or someone else could check my work on one issue and make sure the way we’ve implemented reaction time calculations is correct.
Recall that a single TextStim is shown, it displays a sentence but the each letter of the word is “covered” by dashes, and as the participant presses the space button, each successive word is “uncovered”. For example, the sentence “I like dogs” would be shown like this:
- ---- ----
They hit “space” and see:
I ---- ----
They hit space again and see:
- like ----
And after hitting space once again:
- ---- dogs
The initial code component that Tim borrowed used the routine clock to calculate the times between when each word is shown. We’re interested in the variable “iri” below:
# --- Each Frame ----
if len(keypresses) > 0:
if 'space' in keypresses:
thisResponseTime = t # the current time in the trial
#---- SKIPPING SOME CODE-----#
# calculate inter-response interval:
iri = thisResponseTime - timeOfLastResponse
timeOfLastResponse = thisResponseTime
I was worried that this measure of reaction time (inter-response interval) would be inaccurate since the word will actually only be seen on the next screen refresh, and suggested that a better measure of the reaction time would be to create our own clock (wordClock), resetting it with win.callOnFlip(wordClock.reset) after each window flip. Here’s an abbreviated example of the implementation, and the complete code components are copied below if anyone’s interested:
# ---- Begin experiment ---- #
wordClock = core.Clock()
# ----- Begin routine ------#
event.clearEvents()
wordClock.reset()
# ----- Each frame ------ #
keypresses = event.getKeys() # returns a list of keypresses
if len(keypresses) > 0: # at least one key was pushed
if 'space' in keypresses:
iri = wordClock.getTime()
win.callOnFlip(wordClock.reset)
Thanks for your time looking at this, I’m hoping I didn’t lead my friend astray.
And here’s the complete code for posterity’s sake:
Begin experiment
# now define a function which we can use here and later on to replace letters with '-':
def replaceWithdash(textList, currentWordNumber):
dashSentence = ''
for index, word in enumerate(textList): # cycle through the words and their index numbers
if index != currentWordNumber:
dashSentence = dashSentence + ' ' + '-' * len(word)# add a string of dash characters
else:
dashSentence = dashSentence + ' ' + word #for current word, but space was appearing between period and final word, so put space before each word rather than after
return dashSentence +'.' # yields the manipulated sentence
# Creating our own clock to time how reaction times
# based on screen flips (i.e. when the word was actually
# shown
wordClock = core.Clock()
Begin routine
# remove any keypresses remaining in the buffer from
# before this routine started:
event.clearEvents()
sentenceList = sentence.split()
# this breaks your sentence's single string of characters into a list of individual
# words, e.g. 'The quick brown fox.' becomes ['The', 'quick', 'brown', 'fox.']
# keep track of which word we are up to:
wordNumber = -1 # -1 as we haven't started yet
# now at the very beginning of the trial, we need to run this function for the
# first time. As the current word number is -1, it should make all words '-'.
# The name of the TextStim in the builder is "sentences"
sentences.text = replaceWithdash(sentenceList, wordNumber)
# reset our wordClock (it gets set to 0)
wordClock.reset()
# In the Builder interface, specify a "constant" value for the text content, e.g.
# 'test', so it doesn't conflict with our code.
Each frame
keypresses = event.getKeys() # returns a list of keypresses
if len(keypresses) > 0: # at least one key was pushed
if 'space' in keypresses:
thisResponseTime = t # the current time in the trial
# Saving the time based on our wordClock,
# which is reset when the next word is actually shown
rtFromFlip = wordClock.getTime()
# Tell psychopy to call the wordClock's reset() method
# the next time the window flips:
win.callOnFlip(wordClock.reset)
wordNumber = wordNumber + 1
if wordNumber < len(sentenceList):
if wordNumber == 0: # need to initialise a variable:
timeOfLastResponse = 0
# save the inter response interval for this keypress,
# in variables called IRI_0, IRI_1, etc:
# Saving our flip-based rt
thisExp.addData("IRI_" + str(wordNumber), rtFromFlip)
# Also, since you asked, we'll save the time
# since the trial started. (i.e. if the 'space' is hit
# at second 1 and 2:
# IRI_1 = 1
# IRI_2 = 1
# space_1 = 1
# space_2 = 2
thisExp.addData("space_" + str(wordNumber), thisResponseTime)
# update the text by masking all but the current word
sentences.text = replaceWithdash(sentenceList, wordNumber)
else:
continueRoutine = False # time to go on to the next trial
elif 'escape' in keypresses:
core.quit() # I think you'll need to handle quitting manually now.