| Reference | Downloads | Github

Save stimulus generated by loop as image


I have a stimulus (a colour wheel) that is generated by drawing hundreds of lines; each line is added to the image via a loop, which obviously takes some time (it takes about 500 milliseconds to draw). As such I would like to save the stimulus as an image so that I can present the stimulus as an image rather than draw it every time I need it.

I have had a look at BufferImageStim but cannot work out how to use it for a stimulus that is generated within a loop. Below is some minimal code that creates my stimulus.

    import os
    import numpy as np  
    from numpy import sin, cos, radians, deg2rad, arange
    from psychopy import visual, data, event, gui, core

    # radius of colour wheel
    colour_radius = 250

    # width of the wheel
    colour_width = 35

    # resolution of colours
    colour_res = np.arange(0, 360, 0.1)

    scrsize = (800, 800)
    win = visual.Window(size = scrsize, color = (0.6, 0.6, 0.6), units = 'pix', fullscr = False)

    # decalre one element (line) of the stimulus (to be modified within the upcoming loop)
    stim = visual.Line(win, units = 'pix')

    #the loop that creates the stimulus`
    for curr_colour in np.nditer(colour_res):
        # get the current degrees in radians
        colour_radians = deg2rad(curr_colour)
        # calculate the x and y START points of the line for the circle
        x_pos_inner = (colour_radius - colour_width) * cos(colour_radians)
        y_pos_inner = (colour_radius - colour_width) * sin(colour_radians)
        # calculate the x and y END points of the line for the circle
        x_pos = colour_radius * cos(colour_radians)
        y_pos = colour_radius * sin(colour_radians)
        stim.setLineColor([curr_colour, 1, 1], colorSpace = 'hsv')
        stim.setStart([y_pos_inner, x_pos_inner])
        stim.setEnd([y_pos, x_pos])

    keys = event.waitKeys(keyList = ['space', 'escape'])

Thank you for your time.

Ah, I just replied to your other post
Colour Wheel implementation
saying that you should render as an image rather than as lines, then saw this

The answer is that you should render as an image (a texture) in the first place. Two options:

  1. create a texture that contains a circle and pass that to GratingStim
  2. create a linear/cartesian texture to specify your colours and pass that to RadialStim (its job is basically to render a cartesian texture into a circular form).

I think the second one is easier for you. The array you ultimately pass must be RGB (not HSV) but psychopy can help convert it as well:

Have a look at the demos in Coder on rotatingFlashingWedge (to see radial stim in action) and also the one on customTextures to see passing of a numpy array directly to a stimulus.

I can help more tomorrow, but I have a feeling you’ll enjoy working it out yourself and I don’t want to spoil the fun! :wink:

1 Like

Couldn’t help myself - it was n interesting one to try and write. I’ve pasted the solution in the other thread. Don’t go there if you want to work it through yourself ;-):

1 Like

Great, thanks Jon! In the meantime, I found the “win.getMovieFrame” and “win.saveMovieFrame” to store an image of the stimulus which I can then load every time it’s needed using the visual.ImageStim. But your solution is nice and flexible, so thanks very much!