Block feedback and points system

Hi all,

OS (Windows 11)
PsychoPy version (v2021.2.2)

I am very new to PsychoPy and have been mostly working with the builder view inserting code components where necessary. I have managed to do everything needed with the help of posts on this forum and others. There is one thing that I just can’t get my head around as to how to even begin implementing. Below is a snapshot of my flow:

I would like the routine after before the ISI (Block_Feedback) to show accruement of points across the course of the block (in text elements), that vary according to the response type, judgement type and player type. I found the following post: Giving feedback adding points collected in every round however my response-feedback is not binary and I am struggling to even adapt the code for my needs. Here is a snapshot of my excel file to demonstrate what I am referencing:

excel

In experimental terms I want to implement the following:

  1. Player 1 (Participant) - text component 1, total of the following points over the course of the 64 trials per block:
  • For where $match == NOMATCH
    **For correct answer, truth == 1, this trial is worth 0 points.
    **For incorrect answer, truth == 0: if response == $low_lie this trial is worth +1 point WHERE $judgement == Believed, and -1 Point WHERE $judgement == Not Believed; if response == $high_lie this is worth +2 points WHERE $judgement == Believed, and -2 points WHERE judgement == Not Believed.

*For where $match == COLOURMATCH
**If correct answer, truth == 1, this trial is worth +1 point.
**If incorrect answer, truth == 0: if response == $high_lie, this is worth +2 points WHERE $judgement == Believed, and -2 points WHERE $judgement == Not Believed; where response is not the truth or high value lie, this is worth 0 points (perceived as a behavioural error).

  • For where $match == SUITMATCH
    **If correct answer, truth == 1, this trial is worth +2 points.
    **if incorrect, truth == 0 , this is perceived as a behavioural error worth 0 points.
  1. Player 2 (Computer) - text component 2, total of the following points over 64 trials per block:
    *For where player 1 response is correct, truth == 1, this is worth +1 point WHERE $judgement == Believed, and -1 point WHERE $judgement == Not Believed.
    *For where participants report the incorrect answer, truth == 0, this is worth +1 point WHERE $judgement == Not Believed, and -1 point WHERE $judgement == Believed.

Hopefully this communicates effectively what I am trying to do, I am just so stumped how to write a loop with so many conditional statements. I am also worried that the lack of input for some of the cells in the excel files (low_lie/high_lie) may screw up the code- but not sure how to express that for these cells if they make any other response than those held within the truth, low_lie, high_lie variables then this is a behavioural error.

Thank you in advance for any aid you can give me!

Tigan

Hello Tigan,

an ifelse-construction would do the job. If you don’t know how to set up a ifelse-construction, google “if elif python”. Start with a simpler example and expand later.

Best wishes Jens

Hi Jens,

Thank you for this suggestion! I have written the following elif construction which currently isn’t working but given I know barely any python I think it’s at least halfway there:

# needs to be declared in the project at start: @ begin experiment
runningTotalParticipant=0 
runningTotalComputer=0

# The below variable values will need to be replaced with the specific project variables: already have $truth (correct answer), $match (match type) and $judgement (beleieved or not believed) encoded within experiment.
low_lie_trial=True 

def CalcFunction(match,truth): # Main function to score and increment the totals for correct responses to all types of match
    global runningTotalParticipant
    global low_lie_trial
    if match == "SUITMATCH": # Only correct adds to total, any other response taken as behavioural error
        if truth:runningTotalParticipant+=2
    elif match == "NOMATCH": # Only incorrect adds to total
        if not truth:CalcNoMatch(low_lie_trial,judgement)
    elif matchType == "COLOURMATCH": # Both options can add to total
        if truth:runningTotalParticipant+=1 
        elif not truth:CalcColourMatch(low_lie_trial,judgement)
    CalcComputerScore(judgement,truth)
    
def CalcNoMatch(low_lie_trial,judgement): # Function to calculate low or high value lies on a NOMATCH trial, need to debug to define low_lie_trial is only where response = COLOURMATCH (i.e.worth +/- 1)- how?
    global runningTotalParticipant
    if low_lie_trial and judgement == "Believed":runningTotalParticipant+=1 #low lie and believed
    elif low_lie_trial and judgement == "Not Believed":runningTotalParticipant-=1 #low lie and not believed
    elif not low_lie_trial and judgement == "Believed":runningTotalParticipant+=2 #high lie and believed
    elif not low_lie_trial and judgement == "Not Believed":runningTotalParticipant-=2 #high lie and not believed
    
def CalcColourMatch(low_lie,judgement): # Function to calculate the high lie on a COLOURMATCH trial
    global runningTotalParticipant
    if not low_lie_trial and judgement == "Believed":runningTotalParticipant+=2 #high lie and believed
    elif not low_lie_trial and judgement == "Not Believed":runningTotalParticipant-=2 #high lie and not believed

def CalcComputerScore (judgement, truth):# Function to calcluate the computer score
    global runningTotalComputer
    if truth and judgement == "Believed": runningTotalComputer+=1
    elif truth and judgement == "Not Believed": runningTotalComputer-=1
    elif not truth and judgement == "Believed": runningTotalComputer+=1
    elif not truth and judgement == "Not Believed": runningTotalComputer-=1

# Call the main function
CalcFunction(match,truth)
# debug code
print (str(runningTotalParticipant) + " " + str(runningTotalComputer))

The experiment crashes when I try to implement it. The reason for this I assume is potentially two things:

  • I haven’t defined the boolean variable low_lie_trial fully. I was advised to use it and understand the premise of the variable is that it is always either true or false. At the beginning I state that it is true (does this mean always true throughout the experiment?) but I need it to be false on certain occasions and I do not know where exactly in the code I should state it to be false although I know I need it to be for high lies only.

  • I am calling variables that are previously/not defined in the routine for code. PsychoPy obviously works by insert code at certain places within the experimental routine (before or end of routine). The $truth variable value will be known at the end of the trials_exp routine, then the $judgement variable value will be known at the end of P2_judgement routine (see image above). It is almost like I need to have the main bulk of code at the end of each loop run to have all the information to calculate the points, but PsychoPy doesn’t seem to have an option for this. I am unsure whether I have the same code at the end of both routines it will synchronise appropriately if you follow what I mean.

I would greatly appreciate any help anyone can give me!

Kind regards,
Tigan

Hello Tigan,

well I never used to define a function in PsychoPy. I use the builder to build the experiment and use code-elements to tweak it. So I assume that I can’t be offer you much help.

I always initialize/define variables before I use them. Given that they are variables you can change them throughout the experiment. So, your boolean variable will not always be true. But is the variable “truth” ever initialized?

I noticed one thing in your CalcFunction: the first two if/elif compare match, the third matchType. Does this work?

Best wishes Jens

Hi Tigan,

Please could you share the error message that you get?

Sorry I am having a little trouble understanding exactly what you need here, is it that you have one running point counter (that is increased differentially depending on different roles) or several point counters increased independantly?

Thanks,
Becca

Hi,

I edited the elif construction and then set the Boolean variable to be based on response types and it works!

Thank you

#Calculate Participant score
if match == "SUITMATCH": # Only correct adds to total, any other response taken as behavioural error
    if pr_match_resp == 1:TrialParticipant+=2
elif match == "NOMATCH": # Only incorrect adds to total
    if ((key == 'left') and (expInfo == "A")) or ((key == 'right') and (expInfo == "B")): low_lie_trial=False
    else: low_lie_trial = True
    if pr_match_resp == 0:
        if low_lie_trial and judgement == "Believed":TrialParticipant+=1 #low lie and believed
        elif low_lie_trial and judgement == "Not Believed":TrialParticipant-=1 #low lie and not believed
        elif not low_lie_trial and judgement == "Believed":TrialParticipant+=2 #high lie and believed
        elif not low_lie_trial and judgement == "Not Believed":TrialParticipant-=2 #high lie and not believed
elif match == "COLOURMATCH": # Both options can add to total
    if (key == 'left' and expInfo == "A") or (key == 'right' and expInfo == "B"): low_lie_trial=False
    else: low_lie_trial = True
    if pr_match_resp == 1:TrialParticipant+=1
    elif pr_match_resp == 0:
        if not low_lie_trial and judgement == "Believed":TrialParticipant+=2 #high lie and believed
        elif not low_lie_trial and judgement == "Not Believed":TrialParticipant-=2 #high lie and not believed

#Calculate Computer score    
if pr_match_resp == 1 and judgement == "Believed": TrialComputer+=1
elif pr_match_resp == 1 and judgement == "Not Believed": TrialComputer-=1
elif pr_match_resp == 0 and judgement == "Believed": TrialComputer-=1
elif pr_match_resp == 0 and judgement == "Not Believed": TrialComputer+=1