psychopy.org | Reference | Downloads | Github

Breaking out of Pyschopy Loop is Failing, Experiment Keeps Going


#1

Windows 7
PsychoPy version: 1.90.1
Standard Standalone? y

I used builder to make an experiment with several loops. In each loop they have three trials and must get two correct to advance to next loop. If they get the first two trials correct, they can advance to next loop without seeing third trial. In the code component, I have built an if statement that checks if they have gotten two trials correct, and then, if so, ends the loop with
nameOfLoop.finished = True

It’s not actually breaking out of the loop though, the experiment continues with all trials. I added a print "whatever" line after the line of code to break out of the loop (in the same indentation) and that gets printed as output, so i know the condition is being met and the code for ending the loop should be read. So I’m not sure why it’s not working. Could you give me suggestions on how to troubleshoot this? I also verified the name of the loop was exactly the same as the way I was naming it in the code component.

Side note, the python.exe black screen (not sure what to call that) spits out a bunch of ‘never’ lines when I start the experiment, I don’t know if that’s a clue of some sort?

Thanks!


#2

We need to see both your code and the error messages.


#3

Hi Michael,

I apologize for the slow reply. So I overhauled the experiment a bit, but am still having a variation on the same problem. So in this experiment, there is an inner loop (called Circle_Blocks) and an outer loop (called Meta_Loop). The inner loop cycles through three trials showing a sequence of circles light up (it’s a spatial span task). The outer loop cycles through blocks, wherein each block corresponds to a different number of circles in the sequence (on the first block, 3 circles light up; on the second block, 4 circles lights up etc). The participant uses the mouse to click on empty circles to indicate the sequence with which the circles lit up.

At the beginning of the experiment, I initialize the following two variables in a code component:

end_experiment=0
circle_loop=2

In the first routine of the Meta_Loop (before it steps into the Circle_Blocks loop)–in the schema it’s called “Update Loop” I have the following code in a code component:

circle_loop=circle_loop+1
trial_counter=0
trials_correct=0

and in a separate code component but same “Update Code” routine I have:

if end_experiment==1:
    Meta_Loop.finished=True

At the end of each trial inside the Circle_Block Loop, I have a routine called “Check Outcome” with a code component to increment the trial number, check the outcome of the mouse responses, and tally the number of trials correct with the following code, and either break out of the inner loop if the first two trials in the 3-trial-series are correct, or change the ‘end_experiment’ variable to a 1 so when it returns to the beginning of the outer loop, it breaks out of the meta loop. The code looks like so:

trial_counter=trial_counter+1

#check if all the responses were correct
if circle_loop==3:
    if first_mouse_response.clicked_name[0]==Correct_response_circle1:
        if second_mouse_response.clicked_name[0]==Correct_response_circle2:
            if third_mouse_response.clicked_name[0]==Correct_response_circle3:
                trials_correct=trials_correct+1

if circle_loop==4:
    if first_mouse_response.clicked_name[0]==Correct_response_circle1:
        if second_mouse_response.clicked_name[0]==Correct_response_circle2:
            if third_mouse_response.clicked_name[0]==Correct_response_circle3:
                if fourth_mouse_response.clicked_name[0]==Correct_response_circle4:
                    trials_correct=trials_correct+1

if circle_loop==5:
    if first_mouse_response.clicked_name[0]==Correct_response_circle1:
        if second_mouse_response.clicked_name[0]==Correct_response_circle2:
            if third_mouse_response.clicked_name[0]==Correct_response_circle3:
                if fourth_mouse_response.clicked_name[0]==Correct_response_circle4:
                    if fifth_mouse_response.clicked_name[0]==Correct_response_circle5:
                        trials_correct=trials_correct+1
if circle_loop==6:
    if first_mouse_response.clicked_name[0]==Correct_response_circle1:
        if second_mouse_response.clicked_name[0]==Correct_response_circle2:
            if third_mouse_response.clicked_name[0]==Correct_response_circle3:
                if fourth_mouse_response.clicked_name[0]==Correct_response_circle4:
                    if fifth_mouse_response.clicked_name[0]==Correct_response_circle5:
                        if sixth_mouse_response.clicked_name[0]==Correct_response_circle6:
                            trials_correct=trials_correct+1

if circle_loop==7:
    if first_mouse_response.clicked_name[0]==Correct_response_circle1:
        if second_mouse_response.clicked_name[0]==Correct_response_circle2:
            if third_mouse_response.clicked_name[0]==Correct_response_circle3:
                if fourth_mouse_response.clicked_name[0]==Correct_response_circle4:
                    if fifth_mouse_response.clicked_name[0]==Correct_response_circle5:
                        if sixth_mouse_response.clicked_name[0]==Correct_response_circle6:
                            if seventh_mouse_response.clicked_name[0]==Correct_response_circle7:
                                trials_correct=trials_correct+1

if circle_loop==8:
    if first_mouse_response.clicked_name[0]==Correct_response_circle1:
        if second_mouse_response.clicked_name[0]==Correct_response_circle2:
            if third_mouse_response.clicked_name[0]==Correct_response_circle3:
                if fourth_mouse_response.clicked_name[0]==Correct_response_circle4:
                    if fifth_mouse_response.clicked_name[0]==Correct_response_circle5:
                        if sixth_mouse_response.clicked_name[0]==Correct_response_circle6:
                            if seventh_mouse_response.clicked_name[0]==Correct_response_circle7:
                                if eighth_mouse_response.clicked_name[0]==Correct_response_circle8:
                                    trials_correct=trials_correct+1
#participant gets two in a row right
if trial_counter==2 and trials_correct==2:
    Circle_Blocks.finished=True

#participant gets two in a row wrong
if trial_counter==2 and trials_correct==0:
    end_experiment=1
    print "two trials in a row failed"
    Circle_Blocks.finished=True
    print "experiment should end"

#participant advances to 3rd trial and doesn't get two out of three correct
if trial_counter==3 and trials_correct==1:
    end_experiment=1
    print "got to three trials but only got one correct"
    Circle_Blocks.finished=True
    print "experiment should end"

What IS working: The code to break out of the inner loop (Circle_Blocks) if you get the first two trials in a block correct is working fine. However, what is not working is the code to break out of the outer loop and end the experiment if the participant gets the first two trials in a row wrong, or by the third trial has only gotten one trial correct (hence loses on a best 2-out-of-3 scenario). The variable end_experiment gets set to 1, but then it doesn’t break out of the Meta_Loop on the next block, it appears to go on for an additional block, and I’m not sure why.

I’m also attaching a schematic image of the loops and position of the routines I discussed, if that will help. Please let me know if you need additional information and I really appreciate your help!

There are no errors per se, only that the several instances of the word ‘never’ gets spit out to the output.

Thanks so much!


#4

That’s too late: the next iteration of the loop has already started, so setting Meta_Loop.finished=True will have no effect until the following iteration. The .finished attribute must be set before the end of the current iteration if it is to prevent the next one starting. It doesn’t immediately terminate the current iteration.

The confusion might arise because continueRoutine = False takes effect (almost) immediately, and can terminate a routine part way through its normal run. But ending a loop doesn’t act immediately, but only when deciding whether to run the next iteration.


#5

Ah okay, that makes sense! Thank you SO much.