psychopy.org | Reference | Downloads | Github

How to repeat incorrect trials only

What are you trying to achieve?:
I am running a two-alternative forced choice task where participants make judgements about a set of images. It begins with practice task, where participants need to get 100% correct to continue to the main task. I am looking to have incorrect items repeated in a random order.

What did you try to make it work?:
I created an outer loop (with the routine loop nested within it) that repeats the practice trials if less than 100% of items within the first round were incorrect, as per these instructions: Repeat trial if answers are incorrect

What specifically went wrong when you tried that?:
It worked well, but all the practice items are repeated when less than 100% accuracy is achieved, rather than just the previously incorrectly answered items.

I am new to Psychopy and have looked on loads of forums to work out a way around this but haven’t been able to make anything work.

Thanks in advance!!

I’m not entirely sure this will be possible in Builder with a random loop, but a possible route to investigate would be

  • controlling the selected rows field of the inner loop. In the first run through, all rows would be selected but afterwards, you would just select the subset of desired rows where the response was incorrect.

I’m just not sure that would really work, because if the loop is randomised, the row numbers might not correspond any more on a subsequent loop. So perhaps this would be an alternative:

  • In your conditions file, include a column number with a unique identifier per row (it could just be sequential numbers 1,2,3,…), let’s say that column is called row_id
  • At the beginning of the routine, on the very first trial (when the iteration number of both loops is zero), initialise a list like this:
if outer_loop_name.thisN == 0 and inner_loop_name.thisN == 0:
    wrong_list = []
  • On each incorrect trial, add the unique id to that list, like this:
if outer_loop_name.thisN == 0 and blah blah: # where blah blah is your check that the response was incorrect
    wrong_list.append(row_id)

Then also include some code like this in the "begin routine " tab for running in the second pass through the loop:

# one the second run through the loop, only run a trial if it was previously
# recorded as incorrect:
if outer_loop_name.thisN == 1:
    if row_id is not in wrong_list:
        continueRoutine = False

The above is just a sketch of what to do, and would need to be extended if there could be additional runs until the loop is completely perfectly.

1 Like

Hi Michael,

That’s super helpful! Thanks so much. I am now able to get the incorrect items to be repeated.

However, after the incorrect items were repeated and answered correctly, a new set of practice questions commenced. This seems to be because the code I used to terminate the practice trials relies on a full set of items to be answered correctly.

I tried to play around with the code to change this, but it got a bit messy and did not work. Any advice for something simpler would be appreciated !!

I’ve added some screenshots incase it’s helpful.


51%20pm

In the “Begin routine” section, you could do something like this:

# don't run practice a third time:
if outer_loop_name.thisN == 2:
    outer_loop_name.finished = True
    inner_loop_name.finished = True
    continue_routine = False

You might also need to insert a check in the “end routine” tab so that code doesn’t run on the third rep, or work this capacity into that tab, in which case you would need to check if the outer loop was on the second iteration and the inner loop on its last iteration.

This worked. Thanks Michael!

I relied on this thread for my experiment. It works for the first round but after that, there are no iterations in the wrong_list and all the items that initially were answered incorrectly are repeated.
In our experiment, we want to repeat the incorrect trials only until everything is answered correctly.


I would really appreciate it if you could help me with this one!!

I thank you all for this useful thread, as we just need to repeat the trials until 100% correct (which seems to be a rather common case). Now I don’t need further help, but I would add some notes in case somebody may find it useful.

I wonder why the outer loop is necessary, as a single random loop can do it. One problem would be how to judge if we are in the first round or not, and this seems to be checked by something like
if loop_name.thisN >= len(loop_name.trialList):
unless there is a variable that represents the current number of repetition (I’m not sure).

Also, it should be better to remove the stimulus from wrong_list (wrong_list.remove(row_id) once the response gets correct. This can allow third or further round to get really 100% correct, which I don’t think is done in the above discussion of disabling the third round. (nRep should be set large enough, and the loop should be finished when wrong_list is empty at any point after the first round.)

Dear All @Michael, @wakecarter, and @jon,
I am trying to build an Audio-visual paired association test. In the training block, I want to repeat incorrect trials until receiving a correct response.
As you can see in the pictures, I created an outer loop with the name trials_9 to repeat incorrect trials.



In the first round, everything goes well but for the second loop in which incorrect trials must be repeated I received this error:
File “D:\Hildesheim University activities\Audio-visual association training ver.1\Audio-visual association training ver.1_lastrun.py”, line 713, in
if mouse_9.clicked_name[0] == CorrAns:
IndexError: list index out of range

Experiment ended.

I would appreciate it if anyone can help me!!

I think that your issue is that you have code that skips the routine during your second loop but your code in End Routine will run even when the routine is skipped – and the mouse hasn’t clicked on any objects.

You need to add the same conditional to your End Routine code so it also gets skipped.

Dear @wakecarter ,

I also put this part of my code in the End Routine but I received the same error!

if trials_9.thisN == 1:
if row_ID not in wrong_list:
continueRoutine = False

Please could you past the current text of your End Routine Python code so I can edit it for you to show you what I mean?

if mouse_9.clicked_name[0] == CorrAns:
    number_correct = number_correct + 1
    msg = "Correct"
    msgcolor='green'
    mycorrAns = 1
 
else:
        msg = "Incorrect! Try again" 
        msgcolor='red'
        mycorrAns = 0

if testing_block9_loop.thisN + 1 == testing_block9_loop.nTotal:
    if number_correct/(testing_block9_loop.nTotal) >= 1:
        trials_9.finished = True
    else:
        trials_9.finished = False

if trials_9.thisN ==0 and mycorrAns == 0:
    wrong_list.append(row_ID)

if trials_9.thisN == 1:
    if row_ID not in wrong_list:
        continueRoutine = False

print(mouse_9.clicked_name) # DEBUG
print(type(mouse_9.clicked_name)) # DEBUG
print(CorrAns) # DEBUG
print(TrialType)
print(mycorrAns)

Thank you @wakecarter for your help and support.

Try this

if trials_9.thisN == 1 and row_ID not in wrong_list:
        pass
elif mouse_9.clicked_name[0] == CorrAns:
    number_correct = number_correct + 1
    msg = "Correct"
    msgcolor='green'
    mycorrAns = 1
else:
        msg = "Incorrect! Try again" 
        msgcolor='red'
        mycorrAns = 0

if testing_block9_loop.thisN + 1 == testing_block9_loop.nTotal:
    if number_correct/(testing_block9_loop.nTotal) >= 1:
        trials_9.finished = True
    else:
        trials_9.finished = False

if trials_9.thisN ==0 and mycorrAns == 0:
    wrong_list.append(row_ID)

Thank you @wakecarter it works perfectly.
Now I want to write code that says remove a row_ID from the wrong_list when it receives a correct answer and then finishes the outer loop if wrong_list is empty. How can I write it?

That sounds like it should be in a new thread. You could add a link back to this one but should also describe how it is currently working and what is still needed.