# Conditional looping problem

hello, I am trying to make it so the participant has to repeat the set of practice trials again if they get less than 85% correct,
so far it is running through the trials in a loop with the % score calculated after this loop
i presume i will need to use an if/else statement after this score is calculated but have no idea what i can put in this statement to make the loop repeat - and have only managed to find builder view examples online.
i think it would look something like this:

``````if nCorr<85:

else:
``````

with nCorr being the percentage correct

any help would be much appreciated!

You would have to put your current loop inside another loop, but rather than a for loop, it would have to be a while loop. `while` loops repeat as long as the condition you provide is true. So one option for you could be:

``````runPractice = True

while runPractice:
for trial in practiceTrials:
# This for loop should be the same as you have already

# then after your for loop, you check if they got the necessary amount right,
# and if so you set runPractice false
if nCorr<85:
runPractice = False

``````

Note that while-loops can run forever if for some reason the condition for the while loop never turns false, so it would be a good idea to have some other way of terminating the experiment.

1 Like

while loops, of course!
its working partially (as in it moves on if you get 85%+) but its having a problem with looping back to the beginning, and is instead looping between my accuracy statement (â€śyou have got _% correctâ€ť) and try again statement over and over.
hereâ€™s the basic structure of the code

``````while runPractice:
for trial in practiceTrials:
#trial details
nCorr=#accuracy calculation
fmsg.setText("you got %i %% \n of trials correct" %(nCorr))
fmsg.draw()
win.flip()
core.wait(2.0)
if nCorr <85:
fmsg.setText("sorry, try again!")
fmsg.draw()
win.flip()
core.wait(2.0)
else:
runPractice=False
``````

I think this may be an indentation problem as this is on the same level as the for and if statements, but i cant work out how to resolve this

also donâ€™t worry, Iâ€™ve got an escape key in there for that very reason

Thanks for the help!

Just a hunch, maybe practiceTrials is empty after the first run? Add this line before your for loop:

``````print("There are {0} trials in practice trials".format(len(praticeTrials)))
for trial in practiceTrials:
``````

Maybe thereâ€™s nothing in there so nothing happensâ€¦

But honestly I didnâ€™t quite understand your explanation of the problem. If this doesnâ€™t fix it, could you be a little clearer about what is happening or not happening and when?

Hmm, that doesnâ€™t seem to work, its coming up with the error:

``````print("There are {0} trials in practice trials".format(len(practiceTrials)))
TypeError: object of type 'TrialHandler' has no len()
``````

i presume this is because practiceTrials is a trial handler containing a spreadsheet rather than a variable?
(but Iâ€™m not sure - Iâ€™m quite new to PsycoPy)
so this could be the problem, but that particular method doesnâ€™t solve it

as for explaining it better:

the experiment is a Posner style task, and successfully loops through the list of practice trials, once it gets to the end of the list of practice trials (there are 32 trials on the spreadsheet) i have programmed it to show your percentage correct.

If the participant gets less than 85% of the answers correct i would like it to display a message (Iâ€™ve used â€śsorry try againâ€ť in the code above), and then repeat all 32 practice trials.

but instead when it reaches this â€śsorry try againâ€ť screen it loops back to the â€śyou got _% of trials correctâ€ť screen, then back to the "sorry try again screen and back to the â€śyou got _% of trials correctâ€ť and so onâ€¦
so it seems to be looping through these feedback messages rather than the actual experiment

hope that clarifies things!

I think Daniel is right that your TrialHandler doesnâ€™t return anything anymore - basically, since youâ€™ve already run through your trials, if you try `for trial in practiceTrials:` again, this loop will run 0 times.

The easiest way to fix this (I think) would be for you to move your creation of `practiceTrials` into the while loop (so just before the for loop).

Note that this would â€śeraseâ€ť your record of the participantâ€™s response in the previous practice runs, so you may want to save that data if you need it.

I should have really thought of this when I suggested the while loop the first time around!

Ah ok, the error just means they didnâ€™t implement a method for â€ślenâ€ť. Iâ€™m not incredibly familiar with the TrialHandler, so anyone else reading please chime in.

The problem Iâ€™m trying to get at is that after running

``````for trial in practiceTrials:
``````

once, I suspected practiceTrials is empty all subsequent times, so nothing happens after the first loop through.

Now that Iâ€™m in front of my computer I made a simple test script to see if this was the case, and yes, it turns out that you can only loop over a TrialHandler once (without further intervention).
faceCombinations.xlsx (5.3 KB)
thTest.py (1.4 KB)

So weâ€™ve identified the problem, but actually I personally donâ€™t have a lot of experience with the TrialHandler, so Iâ€™m going to wait for someone else to give a better answer, unless I get a chance to do a little more research later (which I of course encourage you to do as well!), in which case Iâ€™ll write back.

EDIT

Ah, sorry @jan.freyberg , I was writing this while you responded!

1 Like

Yes that was the problem, and putting the trial handler inside the loop has fixed it!
as for saving the data Iâ€™m not sure if ill need to do that as it just practice conditions - but if i do ill cross that bridge when i come to it! (i probably will when it comes to my main trials)

thank you both for your help,
i could have been stuck on this for days!

No problem, good luck with the experiment

Youâ€™re welcome! (though we havenâ€™t given a good answer, and hopefully someone else will chime in with some good advice)

But after looking (slightly) more at the files that the builder generates, it looks like the typical way things are done is that each experiment has an ExperimentHandler, which is in charge of saving data, and that the loops you add in the builder are TrialHandler objects, which are given to the ExperimentHandler with .addLoop() . So my guess would be that youâ€™ll need to call that if you want data saved correctly, but again donâ€™t quote me.

If youâ€™re going to be coding experiments and using these objects, it would be worth studying the page for these in the the docs, and studying the _lastRun.py files that are generated by the builder to see how psychopy uses ExperimentHandler and TrialHandler . Iâ€™ve personally been lazy in this department so far and have just coding data saving myself, sorry I donâ€™t have time to give you a better answer at the moment. Iâ€™m sure some better advice will be coming soon from someone!

Exactly, the iterator is exhausted after, well, iterating over it. So you should create a new one if you want to iterate once more.

It shouldnâ€™t be necessary to use the `ExperimentHandler`, it just makes saving all log files easier, and provides a simple way to pickle (create a `psydat` file) of ALL `TrialHandlers` in your experiment at once. A bundle, so to speak But saving the data for each `TrialHandler` individually should work equally well. In fact, I rarely use the `ExperimentHandler` in my own studies.

1 Like