Criterion learning - conditional mapping?

Hello all! I am trying to achieve something quite complex with a pretty limited knowledge of coding and python and could really use the assistance of a kind Samaritan.

What I am trying to achieve:

I am trying to programme a criterion learning task in psychopy. The task will test participants ability to recall a word from a word pair. They will be given feedback on whether they are correct and if incorrect they will be given the correct answer. I have no issues with this aspect of the experiment and have a fully working version of this.

The programme needs to remember whether the participant has gotten the answer correct or not. Once a participant has got a specific trial correct twice, it will be removed from the loop. The loop needs to continue to repeat until the participant has answered each trail correctly twice.

What I have tried to far make it work:

I have began by creating a few trials in separate blocks instead of creating one block with the trials being defined in an excel sheet like usual. I did this with the logic of this article I read which suggests a potential work around about not being able to include conditional mapping in the builder. How to hack conditional branching in the PsychoPy builder | Computing for Psychologists

Currently each of these blocks contains a trial in which participants see one half of a word pair, can type in the other word and are given feedback on whether they are correct or not, this aspect is fully functional. What I want to achieve from here is the criterion learning aspect, so that each of these trials are repeated until answered correctly twice.

If anyone has any suggestions on how to achieve this I would greatly welcome them. My limited knowledge of coding which I think will be needed for this, has got be at a loss. If any more information is needed please just ask.

1 Like

Itā€™s a little hard from the information here to know how to proceed. Your general intention is clear but thereā€™s not quite enough detail here to advise you on things to try. It would be a good idea for you to post a simple minimal working example of the experiment.

Hi Daniel,

Rather than trying to explain through screenshots and lengthy blocks of text, would it be easier if I were to just upload what I have right now?

I have created a ā€˜standaloneā€™ file to work on this specific task separate from the rest of my experiment. There is also no conditions file so you shouldnā€™t anything other than this file, let me know if it isnā€™t working though.

Spaging program session 1 alternative.psyexp (50.2 KB)

Best Wishes,
Lee

Hello Lee,

Well actually it will be better to have the outer loop with a conditions file, otherwise we still wonā€™t really know how to put all of this together.

And Iā€™m sorry but Iā€™m having trouble holding my tongue about recommending you think about redesigning some things here. All of these blocks have the exact same structure, and they all have a loop that only happens once right? Why not just have one pair of stimulus - feedback routines, with a loop around it and a conditions file? Hereā€™s a working example based on what you gave me:

criterion2.psyexp (10.2 KB)
innerConditions.xlsx (4.8 KB)

Weā€™re not addressing your criterion testing yet, but first letā€™s see what you think about this, and then get a version with the outer loop so we can see the whole picture.

I hope you understand what I mean: the minimal working example should be minimal in that it doesnā€™t have added or unnecessary elements, or a huge number of trials beyond what we need to know, but things like your loop and conditions file are necessary to know how the whole thing should run. Talk to you soon.

Actually I think I have a solution for this. Letā€™s see what you and the others think. This is kind of quick and dirty, Iā€™m trying to keep it simple and keep it in the builder.

My solution was to create a dictionary at the beginning of the experiment that will keep track of number of times correct for each word. Words arenā€™t removed from the loop, rather if their score is 2 then the stimulus will not be presented. Lines for skipped items will still appear in your data output file, but with a response value of ā€œLEARNEDā€ so they can be easily filtered out later. Again, Iā€™m thinking this may be a worthwhile price to pay for simplicity.

The next problem is that we donā€™t know how many times the loop will have to go through, (we would like a ā€˜whileā€™ loop but psychopy will generate a ā€˜forā€™ loop). My solution was to set a ridiculously high number of loops (like a thousand or a million) but then break the loop when all words have a score of 2 (by setting .finished = True on the loop). An imperfect but simple solution.

In my examples below, Iā€™m only going to include the code thatā€™s relevant to this question. The complete code can be found in the file Iā€™m attaching here.

This has two routines: trial and feedback. Hereā€™s the code component for ā€˜trialā€™:

Begin experiment

# make a dictionary to hold scores for stimulus texts
# It will look like this (though instead of 'word1', it will
#      be your stimulus text, I'm assuming they only 
#      appear once in your conditions file):
#   scoreDict = {
#            'word1': 0,
#            'word2': 1, # after having gotten one right
#            ...etc. }
scoreDict = {}
allData = data.importConditions(u'innerConditions.xlsx')
for dl in allData:
    scoreDict[dl[u'stimText']] = 0

Begin routine

# This alreadyLearned variable will be
# used in the Feedback routine to determine
# whether or not feedback should be shown.
alreadyLearned = False
if scoreDict[stimText] >= 2:
    continueRoutine = False
    alreadyLearned = True

End Routine

if alreadyLearned:
    block_1_loop.addData('response', 'LEARNED')
    block_1_loop.addData('correct', 'LEARNED')
elif key_resp_1.keys == list(corrResp):
    # increment the score for this word by 1
    scoreDict[stimText] += 1
else:
    # the rest of your code

# Loop through score dictionary, if any 
# has a score less than two, break the loop
# and continue with the experiment. 
haveTrialsLeft = False
for st in scoreDict:
    if scoreDict[st] < 2:
        haveTrialsLeft = True
        break

if not haveTrialsLeft:
    # All have a score of two, stop the loop
    block_1_loop.finished = True

In the ā€˜feedbackā€™ routine, I added a code component:

Begin routine

    # this variable was set earlier
    if alreadyLearned:
        # don't show the feedback routine
        continueRoutine = False

Hereā€™s the experiment and conditions file. Letā€™s see what you all think.

innerConditions.xlsx (4.8 KB)
criterion2.psyexp (11.7 KB)

3 Likes

Hi Daniel,

Sorry for the very delayed reply!

Thank you so much for taking time to look into this and to come up with a solution. I have implemented what you have suggested into my larger experiment and it works perfectly! I was aware that I had to get psychopy to keep a log of how many times a trial was answered correctly but really struggled to implement it due to my limited coding knowledge.

Thanks again, I really appreciate your help!

BW,
Lee