Final item not displaying in self-paced reading

URL of experiment: https://gitlab.pavlovia.org/smithle9/

Description of the problem: I’m working on a self-paced reading experiment in which participants read a sentence one word at a time, advancing to the new word by pressing SPACE. In the current code, the last word of each sentence does not appear. The experiment otherwise works great. Here is the Python in the “Every Frames” tab of the code component.

if len(kb) > 0:
        if 'space' in kb[0]:
            try:
                nextWord = word_list.pop(0)
                text.setText(nextWord)
            except IndexError:
                rtList.append(kb[0][1])
                break
        rtList.append(kb[0][1])

if len(word_list) == 0:
    continueRoutine = False

Here is the JS:

kb = event.getKeys({"timeStamped": true});
if ((kb.length > 0)) {
    if (_pj.in_es6("space", kb[0])) {
        try {
            nextWord = word_list.shift();
            text.text = nextWord;
        } catch(e) {
            if ((e instanceof IndexError)) {
                rtList.append(kb[0][1]);
            } else {
                throw e;
            }
        }
    }
    rtList.append(kb[0][1]);
}
if ((word_list.length == 0)) {
    continueRoutine = false;
}

I’m think I’m having problems defining the .shift function properly to display each word.

Any advice would be greatly appreciated!

I think the issue is above: if this is the last word, then you pop it from the list and text.setText(nextWord) but now the list is empty, so you immediately exit the routine. At a guess, you should shift continueRoutine = False into your exception handler, so it triggers after the last word has been extracted and displayed. e.g. something like:

except IndexError:
    rtList.append(kb[0][1])
    continueRoutine = False
    break

i.e. don’t exit the routine as soon as the list becomes empty, but when the space bar has been pressed and the list is already empty.

Hi Michael,

Thank you for your suggestion! It works now and displays each word.

However, now I have the same issue I discussed in a previous post; that is, after the words display, a blank screen appears. I think this means that the routine is not ending, so the following “image” routine which is supposed to show participants a set of images does not display.

It was suggested to me by @wakecarter that I should to clear the keyboard buffer, for example in End Routine of my code component, but nothing seems to happen if I use the clearEvents function.

Do you have any suggestions on how to resolve this?

Thank you again for your help!

If it’s displaying each word but no images then there can’t be an issue with the word routine ending. It’s running multiple times. Please show any code and components related to the image presentation.

Gotcha. Here are the components for the image presentation routine:

Stim_resp refers to the keys that participants press to choose the image (‘a’ or ‘b’).

Stim_image is the image:

And, here is the trial_loop.

Screenshot 2020-07-10 09.39.09

Thanks!

Hi,

I thought it might be helpful to add that the image presentation works fine in the Builder, and the experiment runs as intended.

I’ve also included the python code for the image presentation:

# ------Prepare to start Routine "image"-------
    continueRoutine = True
    # update component parameters for each repeat
    stim_image.setImage(stim)
    image_key.keys = []
    image_key.rt = []
    _image_key_allKeys = []
    # keep track of which components have finished
    imageComponents = [stim_image, image_key]
    for thisComponent in imageComponents:
        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")
    imageClock.reset(-_timeToFirstFrame)  # t0 is time of first possible flip
    frameN = -1
    
    # -------Run Routine "image"-------
    while continueRoutine:
        # get current time
        t = imageClock.getTime()
        tThisFlip = win.getFutureFlipTime(clock=imageClock)
        tThisFlipGlobal = win.getFutureFlipTime(clock=None)
        frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
        # update/draw components on each frame
        
        # *stim_image* updates
        if stim_image.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
            # keep track of start time/frame for later
            stim_image.frameNStart = frameN  # exact frame index
            stim_image.tStart = t  # local t and not account for scr refresh
            stim_image.tStartRefresh = tThisFlipGlobal  # on global time
            win.timeOnFlip(stim_image, 'tStartRefresh')  # time at next scr refresh
            stim_image.setAutoDraw(True)
        
        # *image_key* updates
        waitOnFlip = False
        if image_key.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
            # keep track of start time/frame for later
            image_key.frameNStart = frameN  # exact frame index
            image_key.tStart = t  # local t and not account for scr refresh
            image_key.tStartRefresh = tThisFlipGlobal  # on global time
            win.timeOnFlip(image_key, 'tStartRefresh')  # time at next scr refresh
            image_key.status = STARTED
            # keyboard checking is just starting
            waitOnFlip = True
            win.callOnFlip(image_key.clock.reset)  # t=0 on next screen flip
            win.callOnFlip(image_key.clearEvents, eventType='keyboard')  # clear events on next screen flip
        if image_key.status == STARTED and not waitOnFlip:
            theseKeys = image_key.getKeys(keyList=['a', 'b'], waitRelease=False)
            _image_key_allKeys.extend(theseKeys)
            if len(_image_key_allKeys):
                image_key.keys = _image_key_allKeys[-1].name  # just the last key pressed
                image_key.rt = _image_key_allKeys[-1].rt
                # was this correct?
                if (image_key.keys == str(correct)) or (image_key.keys == correct):
                    image_key.corr = 1
                else:
                    image_key.corr = 0
                # a response ends the routine
                continueRoutine = 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
            break
        continueRoutine = False  # will revert to True if at least one component still running
        for thisComponent in imageComponents:
            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 "image"-------
    for thisComponent in imageComponents:
        if hasattr(thisComponent, "setAutoDraw"):
            thisComponent.setAutoDraw(False)
    trials.addData('stim_image.started', stim_image.tStartRefresh)
    trials.addData('stim_image.stopped', stim_image.tStopRefresh)
    # check responses
    if image_key.keys in ['', [], None]:  # No response was made
        image_key.keys = None
        # was no response the correct answer?!
        if str(correct).lower() == 'none':
           image_key.corr = 1;  # correct non-response
        else:
           image_key.corr = 0;  # failed to respond (incorrectly)
    # store data for trials (TrialHandler)
    trials.addData('image_key.keys',image_key.keys)
    trials.addData('image_key.corr', image_key.corr)
    if image_key.keys != None:  # we had a response
        trials.addData('image_key.rt', image_key.rt)
    trials.addData('image_key.started', image_key.tStartRefresh)
    trials.addData('image_key.stopped', image_key.tStopRefresh)
    # the Routine "image" was not non-slip safe, so reset the non-slip timer
    routineTimer.reset()
    thisExp.nextEntry()
    
# completed 2 repeats of 'trials'

Thank you again!

I assume that that’s compiled code. What about your code components?

Yes, that’s the compiled code! I don’t have code components for the image routine because I didn’t need it to run the experiment on PsychoPy.

Do you have any variable components or code in the other components?

In the “image” routine, don’t have any code in the other components. The only thing I have is the images being pulled from the conditions file.

Screenshot 2020-07-13 14.52.16

I do have a code component for the previous “word” routine, but not for the image presentation routine.