psychopy.org | Reference | Downloads | Github

Read sequence of image files from a folder

Hi, I am totally new to PsychoPy, and coding in general (this is day 3). This is what I want to do:
Participants see a sequence of photographs. They move through the sequence with a key press, and the reaction time to each photograph is recorded.

The problem is that the photographs are specific to each individual participant, so the files will have different names every time I run the experiment. I can’t find any information about how to read a sequence of files from a specified folder - not sure if I’m using the wrong search terms though.

I’ve been trying to build up the code bit-by-bit, and I’ve got to here, specifying a single photo to present:

from psychopy import core, visual, event, clock

win = visual.Window(fullscr=True,allowGUI=True)
img = visual.ImageStim(win, 'G0020132.JPG', size = 1.5, flipVert=False)
kb = keyboard.Keyboard()
timer = core.Clock()

img.draw()
win.flip()

continuing = True
while continuing:
    timer.reset()
    kb.clock.reset()
    
    key = event.waitKeys()[0]
    rt = timer.getTime()
    core.wait(0.001)  # make sure event was processed by ptb too
    print(key)
    print(rt)

    if key == 'q':
        continuing = False

I’m now stuck. I’ve seen posts about reading from a csv file, but this would be a pain in the present situation as the files are different for each participant. Any help on demos, search terms, examples, etc. would be very much appreciated! Thanks

We need a bit more info on the subject to image-list relation. Are the image lists tied to particular subjects ( Joe must get list 1, Bob must get list 2 … ) or is there a set of lists that just needs to be randomized | exhausted | rotated across subjects. Also, how many lists and subjects do you anticipate?

There are several easy ways to accomplish various strategies, but the practical way to do this depends on the details requested above.

Hi Ben, thanks for replying.

Image lists are tied to particular subjects. There are two lists of images for each subject: one list contains 10 images, the other list contains a variable number of images, which pilot testing suggests will be in the region of 150-250. There will be 48 subjects in total, so 96 different lists of images.

Still a little scarce on details, but I think we can start puzzling through with that. A few more questions to consider:

When you say the files are different for every participant, do you mean that there are 150-250 images for each participant that only that participant sees? Or is there a pool of images that is sampled independently for each participant?

Do your images have file-naming conventions that will help you out? That is, is this “G0020132” filename telling you something about which participant should see it or when, or is it arbitrary? You are really going to want to have a consistent naming convention if you can.

Just to give a high-level view of what a solution will probably look like, the best bet is either going to have something in your experiment that is able to procedurally synthesize a unique list of filenames from the subject number or identifier, which depends heavily on having a very consistent file-naming convention, or reading from pre-constructed CSVs. However, we may be able to automate the creation of those CSVs with another Python script.

There are 150-250 images for each participant that only that participant sees (if it helps to make sense of it, the images for each participant are photos captured by a GoPro worn by that same participant in a previous session, so the stimuli are totally inidividualised with no overlap).

The file names as they currently stand do not give any information about which participant should see them, but within-participant, the names do give information about the order of image presentation (i.e. G0020132 is followed by G0020133). I guess I might need to batch-rename them?

One approach then is to have a dialog box when the experiment begins. The box will take a subject number or name or code. Best to make these very systematic ( same length, number of digits, letters, format etc) so assume “S0001”, “S0002”, … best to avoid putting any condition codes in these strings.

Others were correct to suggest you create a file or files with the subject to image-list values in because hard coding them in the python file is convenient, but a space waster.

What I would do then, would be to have a directory below your script (call in “infiles”) and in that dir, put a corresponding file for each subject, say for example infiles/S0001.in infiles/S0002.in …

After getting the code “S0001” in the dialog box which would be assigned a variable, e.g. scode (and checking to make sure it is a subject code you have a file for) you would attempt to open the filename “infiles”+scode+".in"

If it is true that S0001 only gets G001*** then this is simplified. If it is really systematic then you can
generate a list of filenames to read inside your experiment based on subject code and not have to read in lists.

This is really helpful, thanks. It will take me a while to work it all out, but one immediate question is how to create the file with the image-list values, given that I will have up to 10,000 images to work with.

Since you mentioned being new at Python there are a few methods that will be of use here.

  1. The os library can help you build file-paths. See here https://docs.python.org/3.7/library/os.html

  2. If you have all the photos for a specific participant in a given subfolder inside the folder where your script is saved, then all you need to do is make a dropdown like @ben suggests that gets you the folder name, and then you can use os.listdir to get a list of all the files in that directory. Then you can loop through them to load them into a list. For example, some pseudocode:

import os
from psychopy import core, visual, event, clock

win = visual.Window(fullscr=True,allowGUI=True)

subjectFolder = 's0001' # Replace this with a GUI.dlg dropdown list

folderList = os.lsdir(subjectFolder) 
# This will return a list of every filename in the folder named "s0001"

stimList = []
for i in range(0, len(folderList)):
    tempStim = visual.ImageStim(win, os.path.join(subjectFolder, folderList[i]), size = 1.5, flipVert = False)
    stimList.append(tempStim)

At the end of that you would have a list, stimList, where each item in the list was one of the images, and you could just cycle through it with a loop. There are more sophisticated ways to do it, but this is probably the simplest.