psychopy.org | Reference | Downloads | Github

Random selection of image stimuli without repetition across different blocks

Hi all,

I’m completely new to PsychoPy (and any sort of coding), and would really appreciate any sort of help!

My experiment is recall memory test.

The design is a within-subjects design, where participants will be shown images across 4 different task instructions (blocks). These images vary based on whether they are low in number of objects or high in number of objects. There will be 16 trials in each block, where each trial is the display of an image. Each block will show a total of 8 ‘low’ images, and 8 ‘high’ images. I have a list of 32 images for ‘low’ and a list of 32 images for ‘high’, in total.

I would like to vary the block order so that it is counterbalanced, and also would like to use all 64 images once only in the entire experiment, but randomise the order in which it appears to each participant while still maintaining the structure of 8 ‘low’ images and 8 ‘high’ images per block.

Therefore, I would like to present 16 images in each block, randomly choose 8 out of the 32 images from the ‘low’ object file, and 8 out of the 32 images from the ‘high’ object file, without using the images again in a later block.

After sifting through the forum, the closest solution i could find was how to create a new condition file for each run. However, this meant that the same 16 images after being randomly selected from the 2 files would be shown across all blocks, just in a random order.

This is the code in question:

import pandas as pd

fileName = ['LowVSTM.csv', 'HighVSTM.csv']
conditionFile = pd.DataFrame(columns=['painting'])  # where 'painting' is the column name for your images

for files in fileName:
    myDat = pd.read_csv(files)  # Get conditions file 
    myDat = myDat.sample(frac=1).reset_index(drop=True)  # Shuffle the dataframe
    myDat = myDat.head(8)  # Take first 8 rows from sheet
    conditionFile = conditionFile.append(myDat)  # Append to new conditions file variable

conditionFile.to_csv("randPainting.csv", index=False)  # Save to new csv file for use in the loop handler.

(from Randomly Select from Multiple Conditions files)

Can somebody please point me on the right track and let me know if my design can even use this code?

Please let me know if further information is needed to clarify this as well.

Again any help will be greatly appreciated! Thank you!

Alice

1 Like

Hi Alice,

Can you describe your design more precisely (especially consider that the term “randomised” has very meanings in design terms)? i.e. think the level of detail you’d need to provide in the method section of a paper so that the reader knows unambiguously what you did. Specifying that level of detail is what is required to create an algorithm that exactly matches what you want to achieve.

We need to know things about how many trials are in each block, how many elements there are in each of your lists, does block order vary or is it constant, are these constraints all within-subject, or do any apply across subjects, and so on.

Hi Michael,

Thanks for replying.

My experiment is recall memory test.

The design is a within-subjects design, where participants will be shown images across 4 different task instructions (blocks). These images vary based on whether they are low in number of objects or high in number of objects. There will be 16 trials in each block, where each trial is the display of an image. Each block will show a total of 8 ‘low’ images, and 8 ‘high’ images. I have a list of 32 images for ‘low’ and a list of 32 images for ‘high’, in total.

I would like to vary the block order so that it is counterbalanced, and also would like to use all 64 images once only in the entire experiment, but randomise the order in which it appears to each participant while still maintaining the structure of 8 ‘low’ images and 8 ‘high’ images per block.

I hope this clarifies things, but am happy to go into more detail.

Are the instructions the only thing that varies between blocks?

i.e. is the trial procedure the same in each task, just with different instructions, or does the trial procedure itself vary depending on the task?

The answer to this determines the overall layout of the Builder experiment.

Hi Michael,

My experiment is specifically looking at cognitive offloading and whether the way we view/interact with images can lead to poorer memory and/or offloading.

The trial procedure always involves presenting the images in the same way as described (8 low, 8 high images), but there will be slight changes as follows based on the instructions:

  1. Observe images
  2. Physical task while viewing (this trial procedure won’t be different from the ‘observe images’ block).
  3. Observe images, pressing a spacebar key for each image (that triggers a screenshot audio sound)
  4. Dual task - listening to an audio file while observing images

What I was going to do with randomising the blocks, was to create separate tests varying the order of blocks. Unless there’s a way to code for this?

Regarding the images presented in each trial though, I’m using a total of 64 images throughout the entire run of the experiment, but want to make it so that only 8 images randomly selected from the low file and 8 images from the high file for each block, and not to repeat these images in each run.

Thank you again for responding.

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

Thank you so much!! iI’ll try that out and update this post with the results.

Hi Michael,

Thank you so much for your help! This fits exactly what I wanted.

I have another follow up question, if that’s okay. I’ve been trying to add task instructions to display before beginning each block of paintings, and the participant has to hit enter after reading it before they can view the images. I also want to obtain confidence ratings on a slider after each block. Do I add these as new routines within each smaller loop?
Thank you,

Alice

you can have just one routine for instructions, that runs on every iteration of the outer loop (so this routine won’t need to be enclosed in another, inner, loop. You can add a column to the conditions file for the outer loop that contains instructions (see post above, which I’ve edited to incorporate that new column). Put that variable name in the text field of your instruction routine. i.e. on each block, the instructions corresponding to that block will appear.

Similarly, you can have a single routine for rating, at the end, not enclosed in an inner loop.

Thank you so much. It’s now looking exactly how i want it to!