How to create bullseye stimuli in PTB?

Hi all!

This is Jiangang. I’m trying to use bullseye stimuli (sine-wave concentric circles with parameters like contrast and spatial frequency, similar to gratings) in my experiment. Just like what is shown in fig. 1 of this study (Dynamic hidden states underlying working-memory-guided behavior | Nature Neuroscience). It has been done with Psychtoolbox but I cannot find how it is done anyhow.

Any help would be much appreciated!


Hi, a colleague Junxiang Luo recently modified my colour grating procedural shader to generate polar, circular or spiral gratings, and like the color grating shader it can generate sine or square waves, you can specify both grating colours (i.e. make proper red-green gratings) and offset from any base colour. Examples:

As these are procedural they are easy to use and all the parameters can be animated with high speed, including morphing between the different classes by changing the radial and circular spatial frequencies. You can download them here:

You want CreateProceduralPolarGrating.m, PolarGratingShader.frag.txt PolarGratingShader.vert.txt — a demo of how to use them is found in this file: ProceduralPolarGratingDemo.m — copy them to a folder on the path and run the demo to get an idea of how to use them…


I am a newbie in psychtoolbox and I need a version of the radial sine grating where the contrast is high at the top 30 degrees of the doughnut, and low at the rest of the shape. How can I achieve this contrast modulation?

At least with the procedural code that should be straight-forward, you can access the Y position and modify contrast based on that. I don’t have time to nerdle with shaders so you are on your own, see Shader - Shadertoy BETA for an example of the ProceduralColourGrating (which the polar grating was based off) running in a a great online editor, this is a nice way to test tweaks to the shader (tweak the code and see results in realtime).

If you had a PTB licence this is possibly something Mario could whip up fairly quickly?

Thank you for your reply. However what I don’t understand is that there are no coordinates specified in the procedural texture code. Normally what I would do is to multiply specific pixel values with the specific coordinates in the texture. I have no idea how to do that when the procedural texture here doesn’t have provided pixel values.
(unfortunately I don’t have a PTB license)

GLSL shaders operate on every pixel independently, with the current pixel position given by vec2 pos = gl_TexCoord[0].xy; so pos.x is the X position and pos.y is the y position. You can then do all sorts of polar ↔ cartesian magic.

Anyway for your needs, a simpler shortcut is to just use Screen('FillArc') to draw an arc over the procedural texture that will act as a mask:

Add this code to the demo to define a centered rect:

segmentRect = [0 0 600 600];
segmentRect = CenterRectOnPointd(segmentRect, width/2, height/2);

and then draw over the procedural texture:

Screen('DrawTexture', win, texture, [], [],...
		angle, [], [], baseColor, [], [],...
		[phase, radialFrequency, contrast, sigma, circularFrequency, 0, 0, 0]);
Screen('DrawTexture', win, masktex, [], maskDstRects, [], [], 1, baseColor, [], []);
Screen('FillArc', win, baseColor, segmentRect, 45, 270);

change the 45 and 270 to rotate the segment as needed…

EDIT: sorry I forgot you wanted contrast modulation, you change the alpha opacity of the mask which would reduce the contrast, although not in “formally” precise way, but may good enough for your needs…