psychopy.org | Reference | Downloads | Github

Rating scale nested within timed while loop

Hi all

I’m trying to create an encoding task. For each trial, I want to show a word for a fixed amount of time (e.g., 4 seconds). During that time, I want participants to rate the word on-screen (i.e., on pleasantness). I used a rating scale to collect the rating.

The problem I am having is that the while loop I created for the rating scale does not seem to adhere to the outer while loop I created for the timer. If no response is given to the rating scale, the word never changes to the next. I want that to happen. I want the timer to run to completion, regardless of whether a participant makes a response. The word should appear for 4 seconds on-screen every time. I have solved a problem in a similar way before, so I don’t understand why it won’t work now.

Here is my code:

from psychopy import visual,core
win = visual.Window([900, 700], 
    color=('black'),
    colorSpace='rgb',
    fullscr=False,
    allowGUI=False,
    winType='pyglet',
    monitor="testMonitor",
    units="pix") #create window
centWord= visual.TextStim(win,
    text = "", 
    font = 'Courier New',
    height = 50,
    opacity = 1.0,
    wrapWidth=40, 
    pos = [0,0],
    color=('white'),
    colorSpace = 'rgb')

ratingScale = visual.RatingScale(win, scale = "extremely unpleasant ... extremely pleasant", disappear = True)

words = ['apple','blueberry','banana','pear','orange','strawberry','snozberry'] #list of stim for encoding

for i,j in enumerate(words):  # loop over trials
    centWord.text = j #set the word to encode
    time = 4 #How long the recall task should last
    timer = core.CountdownTimer(time) #Starts a timer that lasts the length of the recall task
    while timer.getTime() > 0: #until the timer runs out
        win.flip() #show the word
        centWord.draw() #continuously draw the word to be encoded
        while ratingScale.noResponse: #until a response to the rating scale is made; disappear after rating
            centWord.draw() #draw the word to encode
            ratingScale.draw() #draw the rating scale
            win.flip() #show both

    rating = ratingScale.getRating() #save rating
    decisionTime = ratingScale.getRT() #save RT to rating
    #print(rating, decisionTime)
    ratingScale.reset()  # reset between repeated uses of the same rating scale
core.quit()

I have tried putting an if-statement inside the inner while loop, but that didn’t solve the problem. I have reproduced the code here:

for i,j in enumerate(words):  # loop over trials
    centWord.text = j #set the word to encode
    time = 4 #How long the recall task should last
    timer = core.CountdownTimer(time) #Starts a timer that lasts the length of the recall task
    while timer.getTime() > 0: #until the timer runs out
        win.flip() #show the word
        centWord.draw() #continuously draw the word to be encoded
        while ratingScale.noResponse: #until a response to the rating scale is made; disappear after rating
            centWord.draw() #draw the word to encode
            ratingScale.draw() #draw the rating scale
            win.flip() #show both
            if timer < 0: #if time runs out before P. makes rating
                break #get out of the while Loop onto the next word
    rating = ratingScale.getRating() #save rating
    decisionTime = ratingScale.getRT() #save RT to rating
    #print(rating, decisionTime)
    ratingScale.reset()  # reset between repeated uses of the same rating scale

If anyone can help, I would appreciate that.

Zared

Your code logic looks entirely correct. The problem is likely simply the typo in this line:

if timer < 0: 

timer here is a clock object, not a number, so this test will never evaluate to True.

You need to test against timer.getTime() instead.

Aha! Right you are.

Thanks for catching that, Michael! I didn’t know if there was some oddity of the rating scale at play (some colleagues of mine have had some issues with it).