Task-Switching in Builder view

I see, thank you for taking the time to break it down like that.

The code you posted works perfectly! Just a quick question; Would you recommend inserting event.clearEvents() in the Begin Routine tab of the secondary task to make sure the program isn’t counting previous key presses as responses to the task? I did so for the primary task (the math problems) since pressing c, ,i, or ‘y’ even when there was no stimuli present resulted in each key press being counted, but I just want to be sure this won’t have any other consequences on how they are recorded. I checked my output files and they look fine.

Anyway, this is what I have in my End Routine tab for the secondary task:

if wp_response:
    thisExp.addData('wordproblem_rt', t) #rt for entire trial
    
if not wp_response : #if no response
    gainsThisBlock = gainsThisBlock - 5 # minus 5 points for no response
    thisExp.addData('wordproblem_correct', 'N/A')
    run_secondary_task = False
    
#update total points
gainsTotal=gainsThisBlock + gainsTotal
thisExp.addData('TotalPoints', gainsTotal)

This is similar to what I have for time recording in the primary task. Is it possible to isolate the rt by each key press?

In general yes, that is a good idea (this is effectively why the Builder keyboard component does when you select “Discard previous”), and something that we should handle explicitly when dealing with responses in code. I’ve lost a little touch with what is happening in this thread, but sometimes you might only want to do this on the first iteration of a loop that occurs within a trial.

You should record the rt for each response when it occurs, and append it to a list, something like:

Begin routine:

rt_list = [] # initialise empty list

Each frame:

for key in wp_response:
        rt_list.append(t)
        key = key.lower()
        num_received = num_received + 1
        answer = answer + key

“End routine” either:

if wp_response:
    thisExp.addData('wordproblem_rts', rt_list)

or split them out into separate columns:

if wp_response:
    # write a separate column variable for each reaction time 
    # (wordproblem_rt_ 0, wordproblem_rt_ 1, etc):
    for column_num in len(rt_list):
        thisExp.addData('wordproblem_rt_' + str(column_num), rt_list[column_num])

I have updated the code to your previous suggestion from 4 days ago, but I have been getting the following error

    if wp_response:
NameError: name 'wp_response' is not defined

This is in regards to the End Routine tab in my secondary task routine:

if wp_response:
    thisExp.addData('wordproblem_rts', rt_list)
    
if not wp_response : #if no response
    gainsThisBlock = gainsThisBlock - 5 # minus 5 points for no response
    thisExp.addData('wordproblem_correct', 'N/A')


    
#update total points
gainsTotal=gainsThisBlock + gainsTotal
thisExp.addData('TotalPoints', gainsTotal)

I have tried troubleshooting this all weekend, and it seems to happen every time unless the very first trial of the experiment contains the popup and it is responded to (y press to switch tasks instead of c or i for the primary task.)

Sorry, this thread has been going for too long for me to know what code you currently have and where. That makes it impossible to diagnose a bug like this. Can you once again show all of the code, with what tab/routine it comes from??

Of course.

Begin Routine:

if not run_secondary_task:     
    continueRoutine = False

gainsThisBlock = 0


num_required = len(corrAns)
num_received = 0 
answer = ''

rt_list = [] # initialise empty list 

Each Frame:

# check the keyboard queue for events:
wp_response = event.getKeys()

if wp_response: # must allow for multiple key presses
    for key in wp_response:
        rt_list.append(t)
        key = key.lower()
        num_received = num_received + 1
        answer = answer + key

    if num_received == num_required:
        # amend the score accordingly:
        if answer == corrAns: # corrAns refers to the correct answer to the word problem, can be any key
            gainsThisBlock = gainsThisBlock + 5 # 5 points for a correct answer
            thisExp.addData('wordproblem_correct', 'True')
        else:
            gainsThisBlock = gainsThisBlock - 5 # minus 5 points for an incorrect answer
            thisExp.addData('wordproblem_correct', 'False')
        
        #go on to the next problem: 
        continueRoutine = False 

End Routine:

if wp_response:
    thisExp.addData('wordproblem_rts', rt_list)
    
if not wp_response : #if no response
    gainsThisBlock = gainsThisBlock - 5 # minus 5 points for no response
    thisExp.addData('wordproblem_correct', 'N/A')

#update total points
gainsTotal=gainsThisBlock + gainsTotal
thisExp.addData('TotalPoints', gainsTotal)

Oops, OK, that helped make a possible issue obvious. I think the issue is that if the secondary task doesn’t run (i.e. the routine is skipped) the “end routine” code will still execute. This will be an issue because in that case, as the routine itself didn’t run, neither did the “every frame” code, and so the variable wp_response never got created. So we should make the code in that “end routine” tab conditional too.

So we should tidy up that “end routine” code, something like this:

if run_secondary_task: # now only execute the following code conditionally
    if wp_response:
        thisExp.addData('wordproblem_rts', rt_list)    
    else: # there was no response
        gainsThisBlock = gainsThisBlock - 5 # minus 5 points for no response
        thisExp.addData('wordproblem_correct', 'N/A')

    # update total points
    gainsTotal = gainsThisBlock + gainsTotal
    thisExp.addData('TotalPoints', gainsTotal)

This was actually a useful bug to arise, because it also highlights that if the routine was skipped, the reaction times for that trial might still be saved, simply because the wp_response variable still exists from a previous run of the routine.
So we should also reset the wp_response variable at the start of the routine, as you already do for rt_list. i.e. add this to the at the end of the “begin routine” code:

wp_response = []

Yes, this must’ve been the case. I assumed that the ContinueRoutine = False clause in the Begin Routine tab would stop everything, including the End Routine tab.

I tried using the code you suggested earlier to split up key press rt into different columns:

but it returns the following error:

 for column_num in len(rt_list):
TypeError: 'int' object is not iterable

That is the last problem I have with the code. I do have another question concerning PsychoPy however. Every time I open my experiment file, one tab of code is compressed into one line for some reason, so I have to go in and fix all the indents. Is this a known issue?

Sorry, try range(len(rt_list))

The task works perfectly now, thank you so much!
I do still have the issue below however.

I am including a screenshot to better illustrate my issue. Is there a way to prevent this from happening every time the psyexp file is opened?

See: