psychopy.org | Reference | Downloads | Github

Drawing ShapeStim together with Gratingstim using blendMode = 'add'

Hi all,

I am currently programming a stimulus that consists of geometrical shapes (which I intend to draw using ShapeStim) to which pixel noise is added within a square window. For example, given a 128 x 128 pixels window, I would draw one triangle and three arrows (one in each quadrant) and add pixel noise to these stimuli.

Based on my readings, blendMode = ‘add’ seems to be designed to achieve this. However, I get very strange behavior when I code up this type of stimulus. I present a minimal example below.

I have read some posts on this issue (here on discourse as well as on stackoverflow [1, 2] and an issue posted on github).

Based on some of the responses to these issues I updated to the most recent PsychoPy 1.85.1 where the TextStim issue seems to be fixed. I verified this, and the issue with combining a GratingStim with a TextStim using blendMode=‘add’ no longer occurs for me. However, I still get behavior similar to the second stackoverflow post in that the colors generated in the ‘add’ mode are just off, and this also seems to mess up manipulating the contrast of the ShapeStim objects. My knowledge of the OpenGL machinery that is happening under the hood is too limited to be able to pinpoint a specific problem, so I thought to highlight it here as a variant of an issue that has been previously reported.

I guess my question is either: (1) is there an efficient way to generate a similar stimulus without relying on blendMode = ‘add’? or (2) does anyone know how to solve this color issue that seems to occur when relying on blendMode = ‘add’

A code example that should in principle should show the issue:

from psychopy import core, visual, event
import numpy as np 

win = visual.Window((96, 96), allowGUI=False, units='pix', fullscr=False, 
                    blendMode = 'add', useFBO = True)

line = visual.Line(win, start = -20, end = 20, lineWidth=2, 
                   contrast = .1)
                   
noiseTexture = np.random.normal(0, np.sqrt(.0625), size=(128,128))

patch = visual.GratingStim(win, tex=noiseTexture,
    size=(128, 128), units='pix')
    
line.draw()
patch.draw()
win.flip()

event.waitKeys()

win.close()
core.quit()

You should probably describe what you expected to see and how the outcome differed from that.

I think the problem is that the value that is added by the line is its representation in RGB units (which doesn’t seem to be the case for the GratingStim). For example, setting the contrast of the line to 0 and drawing it on the gray background will give you a white line (0.5 background + 0.5 line).

You can get around this by specifying a negative contrast value; for example, if you want the line to add 0.1 (in -1:1), you can set its contrast value to -0.9.

Note however that you are still likely to get ‘off’ colours with your example code, as the noiseTexture already tends to go outside the allowable range (-1:1) and the line would only exacerbate that (and cause the colours to appear).