Probabilistic feedback for two different stimuli

Hi there,

I am programming an experiment where participants have to make a judgement about whether a line presented is short or long via keyboard press. I am trying to write custom code to provide feedback for only a certain number of trials. In a loop of 100 trials, I want a max of 40 correct responses to present a message (“Correct!! You won 20 cents.”).

Moreover, I want to introduce a response bias so that the long line is rewarded more often than the short line. This ratio will be 3:1, where if the participant gets 40 correct responses, 30 of these will be presented when they correctly identify the long line and 10 when they correctly identify the short line.

I saw a post that used a random number generator to probabilistically present the feedback for correct answers. The short and long lines (there are only 2) are presented in random order that I have looped in through a spreadsheet to be repeated 50 times. I was thinking along the lines of an if/else statement, such that if the image presented is the long line and the response is correct, present the feedback for 75% of the correct responses for a total of 40 correct trials being presented with feedback.

Thanks!

Hi Kate,

Yes, I think you’re on the right lines with an if statement! What I would do is add a “counter” at routine end - something like this:

if correct:
    corrResps += 1

So that if they answer correctly, it adds 1 to corrResps. You could then have a further if statement with:

if corrResps > 40:
    presentReward = True

And then have your reward message set up to run only when presentReward is True.

I’m a little unclear on some aspects, do you want to dynamically change the ratio of correct to false based on participants’ answers? Because if this is a simple switch between two probabilities, you could have two columns in the conditions file with those probabilities met, an dynamically switch between them. For example, if the condition for a higher probability correct was for them to have hit 40 correct answers, if you image was called stim, and the columns were highCorrect and lowCorrect, you could do:

if corrResp > 40:
    stim.image = highCorrect
else:
    stim.image = lowCorrect

As each trial, PsychoPy will take a row of the conditions file and assign the value of each cell to a variable with its column name.

Hope this helps!

1 Like

Thank you so much for your detailed response! As I am fairly new to Python/PsychoPy, I have a few questions about your logic that I just want to make sure I fully understand.

I’m having trouble understanding how your second if statement would result in only 40 correct responses being rewarded with feedback. The feedback is being provided immediately after the response, and I’m hoping to present it randomly throughout the entire block of trials. I do like the idea of the counter, but am unsure if it will provide what I am looking for.

The ratio of correct responses will always be 3:1, with correct responses for the long line being rewarded 3x as often as correct responses for the short line. I’m not sure I fully understand the logic behind the highCorrect and lowCorrect. Again, sorry if this is a basic question I am just a little stumped!

I’ll paste what I have tried so far. In the “End Routine” component at the end of the routine with the trial, here is my code for scoring correct vs. incorrect responses:

#score for the correct answer
if m_v.keys == 'v' and Image == 'Stimuli/long_mouth.jpg':
    thisExp.addData ('Score','Big_Corr')

elif m_v.keys == 'm' and Image == 'Stimuli/short_mouth.jpg':
    thisExp.addData ('Score', 'Lil_Corr')

elif m_v.keys == 'v' and Image == 'Stimuli/short_mouth.jpg':
    thisExp.addData ('Score', 'Big_FA') #big false alarm

else:
    thisExp.addData ('Score', 'Lil_FA') #little false alarm

In a separate routine, I defined a variable I called Reward in Begin Experiment:

Reward = [0, 1]

In Begin Routine:

if m_v.corr == 1 and random() > .6:
    Reward == 1 

else:
    Reward == 0

Each Frame:

if Reward == 1 and m_v.keys == 'v' and MV == 'v' and random() >.25:
    msg = 'Correct!! You won 20 cents.'

elif Reward == 1 and m_v.keys == 'v' and MV == 'v' and random() >.75:
    msg = ''

if Reward == 1 and m_v.keys == 'm' and MV == 'm' and random() >.75:
    msg = 'Correct!! You won 20 cents.'

elif Reward == 1 and m_v.keys == 'm' and MV == 'm' and random() >.75:
    msg = ''

else: msg = ''

No feedback appears even when I select the correct response for every trial.

Again, I really appreciate your help!

I’m having trouble understanding how your second if statement would result in only 40 correct responses being rewarded with feedback.

My mistake, I thought you wanted responses to be rewarded only after 40 correct responses. The logic behind a counter is that it increases by 1 each time there’s a correct answer, so by only rewarding when the counter is <40, only the first 40 correct answers are rewarded.

The ratio of correct responses will always be 3:1, with correct responses for the long line being rewarded 3x as often as correct responses for the short line. I’m not sure I fully understand the logic behind the highCorrect and lowCorrect. Again, sorry if this is a basic question I am just a little stumped!

I see, so it’s not the ratio of correct/wrong, it’s the ratio of rewarded/unrewarded? That’ll be a bit more complicated, but it looks like you’ve actually got most of it! random() > 0.75 and random() > 0.25 should give you a 3:1 ratio of rewards. One problem I can see immediately is here:

if m_v.corr == 1 and random() > .6:
    Reward == 1 
else:
    Reward == 0

The operator == doesn’t set a value, it just compares it. So what you’re saying isn’t “set Reward to equal 1”, you’re saying “does Reward equal one?”. What you need is Reward = 1 and Reward = 0, with just one equals sign. This is most likely why the reward isn’t appearing. Also, as you’re comparing to random() twice, you may be decreasing the likelihood - if you already have a condition for setting Reward at a 3:1 ratio, then so long as Reward == 1 is in your if statement you don’t need to then do an additional comparison against random(). You could simplify your is statements like so:

if Reward == 1:
    if (m_v.keys == 'v' and MV == 'v') or (m_v.keys == 'm' and MV == 'm'):
        msg = 'Correct!! You won 20 cents.'
    else:
        msg = ''
else:
    msg = ''

So: If Reward is 1, check whether they were correct. If they were correct, reward them, if not, don’t. If Reward is not 1, don’t reward them.

To limit this to 40 rewards, you just need to create a counter at the beginning of the experiment, let’s call it rewardCounter, ad set its initial value to 0. Then, change your if statements to look like this:

if Reward == 1 and rewardCounter < 40:
    if (m_v.keys == 'v' and MV == 'v') or (m_v.keys == 'm' and MV == 'm'):
        msg = 'Correct!! You won 20 cents.'
        rewardCounter += 1
    else:
        msg = ''
else:
    msg = ''

So, each time you give out a reward, you’re adding 1 to rewardCounter, and once it exceeds 40 then no more rewards will be given.

One other concern, what do you do with msg once defined? Is there a Text element at the end of each routine whose content is set to $msg?

Thank you so so much! This was exactly the solution I needed. To answer your question, I do indeed have a text element set to $msg for every repeat :slight_smile:

I really appreciate the thoroughness of your response!!

Hi Kate, @Kate_Checknita

Appreciate this was a post from a long time ago, but am I right that you were looking to do a rendition of the probabalistic reward task reported in Pizzagali et al. (2008)? I was curious whether you still had access to the code you put together? :slightly_smiling_face:

Thanks.