Random selection of image stimuli without repetition across different blocks

OK, so insert a code component and put something like this in its “begin experiment” tab, to set up the lists for the rest of the experiment:

# create two lists of filenames (or modify your existing code to import 
# them from disk):
low_files  = [str(i) +'_low.jpg' for i in range(32)]
high_files = [str(i) +'_high.jpg' for i in range(32)]

# randomise their order:
shuffle(low_files)
shuffle(high_files)

# get now-randomised selections of each for each block:
observe_files = low_files[0:8] + high_files[0:8]
physical_files = low_files[8:16] + high_files[8:16]
spacebar_files = low_files[16:24] + high_files[16:24]
dual_files = low_files[24:32] + high_files[24:32]

# randomly intersperse the low/high trials:
shuffle(observe_files)
shuffle(physical_files)
shuffle(spacebar_files)
shuffle(dual_files)

Then make a 4-row conditions file that looks like this:

n_observe    n_physical    n_spacebar    n_dual   instruction
32           0             0             0        Observe something.
0            32            0             0        Do something.
0            0             32            0        Press space.
0            0             0             32       Do two things.

Your experiment will consist of four routines, each surrounded by a loop that is not connected to a conditions file. Enclose all of those routines and loops with another, outer loop, that is connected to that small conditions file, that has an nReps value of 1, and is set to random.

Then in each of the inner loops, put the appropriate variable name in its nReps field (e.g. n_observe for the loop surrounding the “observe” routine, n_physical for the “physical” loop, etc).

Hopefully you can see where this is going. The outer loop will run 4 times, once for each row in the conditions file. On each of its iterations, just one of the inner loops will run (for 32 iterations), while the other three don’t run at all. This is how you control the randomisation of your block order.

The last step is how you control the image shown on a given trial. In each of the four trial routines, put something like this in its “begin routine” tab to select (and record) the chosen image:

# for the "observe" routine:
current_file = observe_files.pop() # get the next value
thisExp.addData('current_file', current_file) # record it in the data

You can then use the variable current_file in the image field of your image stimuli. Make sure the code component is above the image stimulus (they can be moved up or down by right-clicking their icons), so that the image component gets the latest value for the variable. Set that field to update every repeat.

For the other routines, use the same code but just change the name of the list you are popping an entry from.

Hopefully that fits what you want?

In general, this isn’t a good idea. Creating multiple experiment files becomes very difficult to maintain. e.g. if you need to make a change, then it needs to be made exactly the same in every file, and the chance of introducing errors is very high. Wherever possible, we should try to express our designs within a single Builder file.

2 Likes