Counters to randomize stimuli images not working properly

Hey,

New psychopy3 user here in need of some help.

I am trying to randomize the pairing of two stimuli images that flash on the screen at the same time for a total of 60 trials. Within these 60 trials I need to fulfill these 3 cases:

  1. a cupcake on the left and a muffin on the right 15 times
  2. a muffin on the left and a cupcake on the right 15 times
  3. a cupcake on the left and a cupcake on the right 30 times

I have both 8 cupcake images and 8 muffin images (excel file below) that need to be randomly paired together to meet these 3 criteria:

At the very beginning of the experiment I’ve set up a routine with some code that does the following:

import random, xlrd

random.seed()

in_file = 'cupmuf_database.xlsx'


num_items = 8
num_tests = 60
cur = 0

After some instructions for participants comes my trial routine.
In begin routine:

inbook = xlrd.open_workbook(in_file)
insheet = inbook.sheet_by_index(0)
cases = ["c_cupR_mufL","c_mufR_cupL","c_cupL_cupR"]

cup_stim = []
muf_stim = []
c_cupR_mufL_count = 15
c_mufR_cupL_count = 15
c_cupL_cupR_count = 30


left = []
right = []
correct=[]
for rowx in range(1,num_items+1):
    row = insheet.row_values(rowx)
    cup_stim.append(row[0])
    muf_stim.append(row[1])

for x in range(60):
  if (c_cupR_mufL_count == 0 and "c_cupR_mufL" in cases):
    cases.remove("c_cupR_mufL")
  if (c_mufR_cupL_count == 0 and "c_mufR_cupL" in cases):
    cases.remove("c_mufR_cupL")
  if (c_cupL_cupR_count == 0 and "c_cupL_cupR" in cases):
    cases.remove("c_cupL_cupR")


    ran = random.randrange(0, len(cases))
    test = cases[ran]

    
  if (test == "c_cupR_mufL"):
    right.append(cup_stim[random.randrange(1, 8)])
    left.append(muf_stim[random.randrange(1, 8)]) 
    c_cupR_mufL_count = c_cupR_mufL_count - 1
    correct.append(1)
  if (test == "c_mufR_cupL"):
    left.append(cup_stim[random.randrange(1, 8)]) 
    right.append(muf_stim[random.randrange(1, 8)]) 
    c_mufR_cupL_count = c_mufR_cupL_count - 1
    correct.append(1)
  if (test == "c_cupL_cupR"):
    leftVal = random.randrange(1, 8)
    rightVal = random.randrange(1, 8)
    if leftVal == rightVal:
      if rightVal == 8:
        rightVal = rightVal - 1
      else:
        rightVal = rightVal + 1
    left.append(cup_stim[leftVal -1])
    right.append(cup_stim[rightVal -1])
    c_cupL_cupR_count = c_cupL_cupR_count - 1
    correct.append(0)

In end routine:

thisExp.addData('left', left[cur])
thisExp.addData('right', right[cur])
thisExp.addData('correct', correct[cur])

if key_resp_2.keys == "left" and correct[cur] == 1:
    thisExp.addData('res', 1)
else:
    thisExp.addData('res', 0)

if left[cur] == muf_stim or right[cur] == muf_stim:
    isTarget = 1
else:
    isTarget = 0
    
cur = cur + 1

My loop is set for nReps to equal $num_tests (which I’ve defined as 60).

When I run this I do get 60 trials each time and all 8 cupcake and muffin images are being used but I don’t get the correct number of pairings for each of my 3 cases. For example, I’ll get 23 cupcake left and cupcake right instead of 30 cupcake left and cupcake right.

I hope this was enough information, I can clarify if something doesn’t make sense.

Thanks in advance.

I think there’s a much simpler way of achieving your goal.

If you have

cases = ["c_cupR_mufL","c_mufR_cupL","c_cupL_cupR","c_cupL_cupR"]*15
shuffle(cases)

That should give you 60 trials in random order of the correct proportions.

I wasn’t aware of a shuffle function thank you for bringing that to my attention!
I’m not sure how to edit my current code to make it work with your suggestion. Could you help me figure it out?
I also should’ve mentioned that the left and right cupcake cannot be the same image.
Additionally, I want to preserve the variables “left”, “right”, and “correct” as my end routine keeps track of which stimuli image was used on either the right or left and if the image pairing was correct (in this case all muffins are correct targets so any time any muffin is shown correct = 1)
This is my end routine:

thisExp.addData('left', left[cur])
thisExp.addData('right', right[cur])
thisExp.addData('correct', correct[cur])

if key_resp_2.keys == "left" and correct[cur] == 1:
    thisExp.addData('res', 1)
else:
    thisExp.addData('res', 0)

if left[cur] == muf_stim or right[cur] == muf_stim:
    isTarget = 1
else:
    isTarget = 0
    
cur = cur + 1

Keeping the “cur” tracker also matters because my left image = $left[$cur] and my right image = $right[$cur].

Any help on implementing the shuffle function into my code would be greatly appreciated.
Thank you so much!