How to preload images and precisely control the presentation time of each image?

1,922 views
Skip to first unread message

Wei Wang

unread,
Apr 6, 2016, 10:27:05 PM4/6/16
to psychopy-users
Hello:

I am very new to PsychoPy, and want to use it to present multiple images (e.g. 30 images with resolution 1920*1080 ) in a short duration.  I tried to use excel with images names as condition, but there is a delay to present the images. In addition, I want to present each image in a very short time (e.g. 1/60 second). How can I do these?

Thanks

Wei 

Oliver Clark

unread,
Apr 7, 2016, 9:32:52 AM4/7/16
to psychopy-users
You should pre-load your images in an ISI (http://www.psychopy.org/builder/components/static.html) - there is an option to do this in the image component in builder (the dropdown box that says constant by default). To get the image on screen for one frame (i.e. 1/60s) you would set the stop attribute to duration(frames) and use 1 as the value.

The reliability of this will heavily depend on the graphics card you have (don't expect much from an intel onboard device in Windows!)

Best wishes,

Oli

Michael MacAskill

unread,
Apr 7, 2016, 3:15:06 PM4/7/16
to psychop...@googlegroups.com
Hi Wei,

Oil's advice is the standard one and usually the way to go, but I suspect that it won't work in your case. To load and decompress an image from disk takes a finite amount of time. It is a race to get it done within a single frame interval (16.7 ms in your case), and in Builder, it isn't really possible to use an ISI period here since you are displaying images for only one frame each, immediately in succession.

Realistically for rapid serial presentation tasks like this, you are going to need to load all 30 images before the trial starts and create a separate image stimulus for each. Actually displaying images takes no time at all, it is the initial creation of them that imposes delays.

The constraint then becomes how much memory your graphics card can hold, because it needs to have all 30 images in memory simultaneously (Builder normally updates each image stimulus on every trial as required, so the graphics card only has to hold one at a time in memory. But in your case, you will have to trade memory for speed.

This will require writing some code. But before getting that underway, you'll need to check that the actual image files themselves are 1920 × 1080. You definitely don't want any images that need to be scaled down: those extra pixels will chew through memory.

Come back to us if you want to proceed this way. You can still run this experiment in Builder, but:

— You'll need to insert some code to handle pre-loading all of the stimuli.
— You'll need to test whether your graphics card hardware can handle holding all of them in memory at once.

Regards,

Michael
--
Michael R. MacAskill, PhD 66 Stewart St
Research Director, Christchurch 8011
New Zealand Brain Research Institute NEW ZEALAND

Senior Research Fellow, michael....@nzbri.org
Te Whare Wānanga o Otāgo, Otautahi Ph: +64 3 3786 072
University of Otago, Christchurch http://www.nzbri.org/macaskill

Wei Wang

unread,
Apr 7, 2016, 4:38:08 PM4/7/16
to psychopy-users
Hi, Michael:

Thank you very much for your response. Yes, your understanding is exactly what I want to do. Actually, I have tried as Oliver suggested, but it takes some time to load all the images and they do not behave exactly same as what I expected. 

Here is want I want to do: 1) preload all the images before the experiment start (e.g. t = 0 when all the images are loaded in the memory and ready to present), and 2) then show one image in one frame (1/60 second). That is, it will take 0.5 seconds to present all the 30 images.Can you tell me how can I implement it? 

Wei

Wei Wang

unread,
Apr 7, 2016, 5:38:00 PM4/7/16
to psychopy-users
Hi, Michael:

In addition, GUI-based Builder offers a quick and convenient way to implement coding, but some parts are unnecessary (e.g. inputs with subjects, session, keyboards, etc). What I want PsychoPy to do is to load all the images and present them in a defined sequence within a short duration (1/60 second). How can I implement it with simplest code?

Thanks

Wei

 

Michael MacAskill

unread,
Apr 7, 2016, 6:26:20 PM4/7/16
to psychop...@googlegroups.com

> On 8/04/2016, at 08:38, Wei Wang <wangw...@gmail.com> wrote:
>
> Here is want I want to do: 1) preload all the images before the experiment start (e.g. t = 0 when all the images are loaded in the memory and ready to present), and 2) then show one image in one frame (1/60 second). That is, it will take 0.5 seconds to present all the 30 images.Can you tell me how can I implement it?

Insert a code component in your trial routine. In its "Begin experiment" tab, put something like this (untested, so you will need to debug):

import glob # a module that allows you to access filenames from a folder

# assuming all your image files are in a subfolder called 'images',
# get the list of filenames with the relevant extension:
filenames = glob.glob(os.path.join('images', '*.jpg'))

images = [] # need to start with an empty list

# create an image stimulus from each file, and store in the list:
for file in filenames:
images.append(visual.ImageStim(win=win, image=file))


In the trial routine, insert a static period set to have a duration of 30 frames (or any other stimulus you might need). This is just to provide some sort of placeholder so that the trial will last exactly 0.5 seconds. Then in the "every frame" tab of the code component, put something like this:

# grab the next image in the list & draw it:
images.pop().draw()

Regards,

Michael

Wei Wang

unread,
Apr 8, 2016, 2:13:01 AM4/8/16
to psychopy-users
Hi, Michael:

Is there any quick tutorial I can learn to write the code only with the function I want to implement? For the GUI-based builder converted code, there are a lot of unnecessary parts. In other words, if I want to delete something from the builder-based code, which parts can I delete?

Thanks

Wei

Oliver Clark

unread,
Apr 8, 2016, 5:54:28 AM4/8/16
to psychopy-users
Hi Wei - here is the page on coder:

http://www.psychopy.org/coder/coder.html

Michael's code idea should work just in coder with a bare minimum of code lines - you'll just need to create a window using visual.Window() and an image stimulus using visual.ImageStim() - once you have this you should have everything you need!

Oli

Michael MacAskill

unread,
Apr 10, 2016, 7:09:09 PM4/10/16
to psychop...@googlegroups.com
Oli's right, hand-written PsychoPy code can be very concise: just check some of the demos under the Demo menu in Coder view.

The only thing what would need to be changed from my suggested code would be creating a window (as per the demos), and then something like this to set up a drawing cycle:

# display new images at 60 Hz:
for image in images:
image.draw() # draw the image to the back buffer
win.flip() # show it on screen, sync'ed with refresh cycle

Regards,

Michael
Reply all
Reply to author
Forward
0 new messages