Setting up a Sugar Factory Task on Psychopy

Hi -

I am creating a Dynamic Systems Control Task (Sugar Factory) and we have a code that we used to run the experiment in Octave locally. We now need to design the experiment such that it can be run with a wider audience and want to use Psychopy given it seems the most flexible platform for this task and the experiment can also be run online.

As a caveat, I have little experience in coding and have never used Psychopy. However, I have tried to re code our original experiment in Octave into Python (below) but I am struggling to get it to run in Psychopy. I think the easiest option I have found for me is to use the builder tool and then use this custom coding to create the experiment in the trials, however, whichever way I try and use the code it does not seem to run in JS.

The experiment should essentially work as follows (at a high level):

  • Participant sees a chart with a starting bar chart of 6000
  • They are then asked to enter a number from 100-1200 (in intervals of 100) in order to reach a target production level of 9000
  • After they enter the number, they also have to mark how confident they are on a scale of 1-5 that they will reach the target production
  • Once they enter a value, the bar chart updates based on the equation in this code and they see the new production
  • This repeats 20 times which is one block
  • The experiment should have five blocks in this format

There are two issues here:

  • the code (I imagine the code in and of itself is not correct and does not include the necessary psychopy language to run in JS especially)
  • how the code will be used in Psychopy (I am not sure if the best way would be to have psychopy run the entire script in a trial or separate the code so Psychopy runs the loops in the builder and have separate blocks with the same code)

Any advice/suggestions or guidance is welcome. Hoping someone with much more experience in both areas may be able to help!

Thanks so much in advance


from psychopy import visual, event, core, gui, simpledialog

Create a window

win = visual.Window([1800,700], monitor=“testMonitor”)

W_level = list(range(100, 1300, 100)) # possible worker numbers (100-1200 in steps of 100)
C_level = list(range(1, 6)) # possible confidence ratings
random_er = [-1000, 0, 1000] # possible random error in final production +/- 1000

trial_perblock = 20 # number of trials per block
blockn = 5 # number of blocks

P_start=6000 # starting production level (hard-coded in line with the paper)
W_start=600 # startiang worker level; The values are reset to these levels at the start of each block

input_check=0 # for worker number input
conf_check=0 # for confidence rating input

W = [[0 for i in range(trial_perblock)] for j in range(blockn)]
E = [[0 for i in range(trial_perblock)] for j in range(blockn)]
P = [[0 for i in range(trial_perblock)] for j in range(blockn)]
C = [[0 for i in range(trial_perblock)] for j in range(blockn)]

for b in range(1, blockn + 1):
# Initialize block & display first W&P
ok = 0 # for end-of block

print("Workers   : ", W_start)
print("Production: ", P_start)

# create the chart to display to participants
win = visual.Window()

bar = visual.Rect(win, width=0.5, height=P_start, pos=(0, 0), fillColor='blue')
line = visual.Line(win, start=(-0.5, 9000), end=(trial_perblock + 1.5, 9000), lineColor='red')
xaxis = visual.Line(win, start=(-0.5, 0), end=(trial_perblock + 1.5, 0), lineColor='black')
yaxis = visual.Line(win, start=(0, 0), end=(0, 12000), lineColor='black')

for t in range(1, trial_perblock+1):
while True:
userinput = simpledialog.askinteger(“Select number of workers”,
"Workers: " + str(W_level) + "\nBlock: " + str(b) + " Day: " + str(t),
minvalue=100, maxvalue=1200)

    if userinput in W_level:
        W[b-1][t-1] = userinput
        E[b-1][t-1] = random.choice(random_er)
        if t == 1:
            P[b-1][t-1] = 20*W[b-1][t-1] - P_start + E[b-1][t-1]
            P[b-1][t-1] = 20*W[b-1][t-1] - P[b-1][t-2] + E[b-1][t-1]
        P[b-1][t-1] = max(1000, min(12000, P[b-1][t-1]))

        conf_check = 0
        while conf_check == 0:
            conf_input = int(input("Confidence in producing between 8000-10000 on THIS day: \n 1=Not at all confident \n 2=Slightly confident \n 3=Confident \n 4=Very confident \n 5=Extremely confident \n"))
            if conf_input in C_level:
                conf_check = 1
                C[b][t] = conf_input
                print("Invalid input. Please enter a valid number from 1 to 5.")

        print("Workers: " + str(W[b][t]))
        print("Production: " + str(P[b][t]))
        print("Confidence: " + str(C[b][t]))

        bar.height = P[b][t]


while ok == 0:
end_block = input(“Press Q to end the block”)
if end_block == ‘Q’ or end_block == ‘q’:
ok = 1

W_start = W_level[random.choice(range(len(W_level)))]
P_start = 6000
print(“Next block”)