Display multiple images simultaneously

Hi,

I wonder what’s the best way to display multiple images on the screen simultaneously. (Preferably with only one image component)

I have 100 small images to display at the same time, with their file names in a condition file. The image position varies, and is calculated/randomized in a code component.

My guess is that some custom codes are needed so that the screen flips only after all images are placed on the screen, instead of flipping 100 times.

I appreciate any further comments.

If you added 100 image Components, I believe it would only flip the screen once, as the flip command happens at the end of the frame loop rather than after each component. I can see why you wouldn’t want to add all those components though…

What you could do is have all the file names in an excel cell separated by a delimeter (such as a comma), then use a Variable component to split them apart into a list. For example, if your excel sheet looked like this:
image

You could create a Variable component with the value:

$ImageFile.split(",")

This means the Variable, let’s call it imlist, will be a list of all the filenames there, as it splits the cell value at every comma.

The challenge then is creating all the Image components - but you could create one in Builder, then in a Code component you could make 100 copies using .copy() and set the image value of each to the corresponding image file, then store them in a list, something like:

for i in range(100):
    images[i] = MyImage.copy()
    images[i].image = imlist[i]

You’d then have to add code to draw each image rather than just draw the original, but if you give this first bit a go and let me know how you get on I can then help you further.

I got a bit lost starting at copying the component 100 times. What is MyImage in your example? I also wasn’t sure how you would use images[i] when you actually draw them. Some elaboration would be very helpful.
Thanks.

MyImage in this case is your placeholder Image component in Builder view, so when you say MyImage.copy() what you’re saying is “I’ve made this blank Image component in Builder, now make a copy of it”.

images will therefore be a list of Image objects, so you can do anything to images[i] that you would do to MyImage, if that makes sense? I think drawing it should be as simple as adding to the Each Frame tab:

for i in range(100):
    images[i].draw()

As you’re essentially saying “for each image in images, perform it’s draw command”

It’s starting to make sense, while it gives me an error with the copy() command:
'ImageStim' object has no attribute 'copy'

Any thought?

Oops, my mistake! Some objects in Python have a copy method, I thought ImageStim did too… So instead you’ll need to add:

import copy

to the Begin Experiment tab, then rather than MyImage.copy() use copy.copy(MyImage) - so essentially you’re importing a method to copy it rather than using its own method. Does the same thing though!

Ok, it makes sense. Now there’s one last issue, I believe. When we copy the image component, we are copying an “ImageStim” object in PsychoPy. It seems though the indexing is having a problem -

for i in range(3):
    images[i] = copy.copy(imageSample)
    images[i].image = imList[i]

IndexError: list assignment index out of range

Another similar error -
'ImageStim' object does not support indexing

When I tried this method with only one image (so no indexing), it worked fine.

Ah, I guess you need to initialise a blank list first… You could try adding this to the beginning:

images = []*len(imList)

or you could do this:

for i in range(len(imList)):
    images.append(copy.copy(imageSample))
    images[i].image = imList[i]

which should work too. Which you go with is personal preference really!

Oh yes, of course I should do it this way. Silly question.
Now the images are drawn on screen properly. Glad that I don’t need to create 100 components in the builder. :grinning:

Thanks Todd.