Masked self-paced reading with time limit (code inside Builder)

Hi,

Since 2015, and with Michael’s precious help (https://groups.google.com/forum/#!topic/psychopy-users/sjX7_Oa_WXc), I’ve been using this self-paced moving window paradigm successfully, but now I want to add a time limit of 2 seconds (for instance).

The original Script is this:

# Insert a code component within the relevant routine.
# at "begin routine" tab, put some code something like this:

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 define a function which we can use here and later on to replace letters with 'x':

def replaceWithX(textList, currentWordNumber):
   
    xSentence = ''
    for index, word in enumerate(textList): # cycle through the words and their index numbers
        if index != currentWordNumber:
            xSentence = xSentence + 'x' * len(word) + ' ' # add a string of x characters
        else:
            xSentence = xSentence + word # except for the current word

    return xSentence # yields the manipulated sentence

# 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 'x'.
# Use the actual name of your Builder text component here:

yourTextComponentName.text = replaceWithX(sentenceList, wordNumber)

# In the Builder interface, specify a "constant" value for the text content, e.g.
# 'test', so it doesn't conflict with our code.


# Then in the "Every frame" tab, put in some code like this so that you check the keyboard every time the screen is refreshed (at typically 60 Hz), and alter the text stimulus appropriately:

keypresses = event.getKeys() # returns a list of keypresses

if len(keypresses) > 0: # at least one key was pushed

    if 'space' in keypresses:

        wordNumber = wordNumber + 1
        yourTextComponentName.text = replaceWithX(sentenceList, wordNumber)

    elif 'esc' in keypresses:

        core.quit() # I think you'll need to handle quitting manually now.

I’d like to change the script as to allow something like: the participant either presses the SPACE or (if not), after 2 seconds, the word/segment disappears and the next word appears. Is it possible?

Thank you for your time.

Hi Paula,

Glad to see that code is still in use!

If I understand you correctly, then we need to be monitoring the time since the last keypress, and if more than 2.0 seconds has elapsed, then advance to the next word regardless?

If so, then in the “begin routine” tab, insert this:

# start timing intervals between keypresses:
last_keypress_timer = core.Clock()

And modify the “each frame” tab code to be something like:

keypresses = event.getKeys() # returns a list of keypresses
elapsed_time = last_keypress_timer.getTime()

if len(keypresses) > 0 or elapsed_time >= 2.0:
    if 'space' in keypresses or elapsed_time >= 2.0:
        last_keypress_timer.reset() # reset the clock
        wordNumber = wordNumber + 1
        yourTextComponentName.text = replaceWithX(sentenceList, wordNumber)
    elif 'escape' in keypresses:
        core.quit()

Also, keyboard checking has improved greatly since that code was written. If the accuracy of the keypress reaction times is important, it would be worth upgrading from calls to event.getKeys() to use the .getKeys() method of the new Keyboard class instead:

https://www.psychopy.org/api/hardware/keyboard.html

Hi Michael,

Thank you so much (again!!!). It works perfectly.

I’m copying the complete code I’m using:

“begin routine”: just add the information you suggested at the top of the script (first line).

“each frame”:


yourTextComponentName.text = replaceWithX(sentenceList, wordNumber)


# In the Builder interface, specify a "constant" value for the text content, e.g.
# 'test', so it doesn't conflict with our code.


keypresses = event.getKeys() # returns a list of keypresses

elapsed_time = last_keypress_timer.getTime()


if len(keypresses) > 0 or elapsed_time >= 3.0:

    if 'space' in keypresses or elapsed_time >= 3.0:

        last_keypress_timer.reset() # reset the clock

        thisResponseTime = t # the current time in the trial
        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:
            thisExp.addData('IRI_3_' + str(wordNumber), thisResponseTime - timeOfLastResponse)
            timeOfLastResponse = thisResponseTime

            # update the text by masking all but the current word
           yourTextComponentName.text = replaceWithX(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.

I needed to register the time spent on each word (if it was less than 3 seconds).

I’ll have a look at the `` .getKeys()´´´, as you suggested. I tried to change it, but I got an error. I have to read about it.

Thank you very much for your help and for your time!