RadialStim, only one segment (not pair) per angular x radial sections

Expected outcome:
I would like to have a RadialStim where there are 3 layers counting from the middle of the circle, and each layer have 8 segments, like so…

image

Problem:
I have define 4 angular sections and 3 radial sections. Somehow, each segment seems to “must have” both a white and a black section. How do I make sure that each segment has only 1 part (not both black and white).

What I have so far (code):

from psychopy import visual, core

win = visual.Window([1200,800], monitor="testMonitor", units="pix")

stim_diameter_pix = 512
n_angular_sections = 4
n_radial_sections = 3

psychopy_object = visual.RadialStim(
    win=win, 
    ori=540,
    size=stim_diameter_pix,
    pos=(0,0),
    angularCycles=n_angular_sections,
    radialCycles=n_radial_sections,
    opacity=1, 
    depth=-1, 
)

psychopy_object.draw()
win.update()

core.wait(10.0)

@jingles , you could try halving the n_radial_sections, and to get a different number of sections for the center stim, you overlay a second RadialStim with different parameters, e.g., n_angular_sections = 2

But that would still get a black and a white portion for every section. So for example, 3 radial sections would result in 6 layers (3 pairs of black and white). 2 radial sections will give you 4 layers.

Question: how to reduce the pair to just 1 section, such that 3 radial sections would only produce 3 layers.

If you try using 1.5 radial sections, you should get 3. Give this code a try - its not perfect since the inner radialstim does not align correctly:

from psychopy import visual, core

win = visual.Window([1200,800], monitor="testMonitor", units="pix")

stim_diameter_pix = 512
n_angular_sections = 4
n_radial_sections = 1.5

psychopy_object = visual.RadialStim(
    win=win, 
    ori=22.15,
    size=stim_diameter_pix,
    pos=(0,0),
    angularCycles=n_angular_sections,
    radialCycles=n_radial_sections,
    opacity=1, 
    depth=-1, 
)

psychopy_object2 = visual.RadialStim(
    win=win, 
    ori=135,
    size=512/3,
    pos=(0,0),
    angularCycles=2,
    radialCycles=.5,
    opacity=1, 
    depth=-1, 
)

psychopy_object.draw()
psychopy_object2.draw()
win.flip()

core.wait(10.0)

Thanks @dvbridges, I understand what you did and know why there is psychopy_object and psychopy_object2 (to handle the inner circle that is different from the outer one. For now, ignore that.

Going back to the “black and white segment per angular x radial section”. Setting it to n_radial_sections = 1.5, indeed visually we can achieve that visuals that matches the expected outcome. But doing so, we can’t manage each section individually. What do I mean by that? After designing the layout of the radial, at each frame, I would like to decide which segment is white and which are black. See the code below.

import numpy as np

import psychopy.visual
import psychopy.event
from psychopy import visual, core

stim_diameter_pix = 512
n_angular_sections = 4
n_radial_sections = 3
angular_phase = 0.25
angular_size_deg = 360 / n_angular_sections

with psychopy.visual.Window(
    size=(600, 600), color=(-1,) * 3, units="pix", fullscr=False
) as win:

    sections = []

    for i_radial_section in range(n_radial_sections):

        for i_angular_section in range(n_angular_sections):

            sections.append(
                psychopy.visual.RadialStim(
                    win=win,
                    size=(stim_diameter_pix,) * 2,
                    units="pix",
                    visibleWedge=(0, angular_size_deg),
                    ori=i_angular_section * angular_size_deg,
                    angularCycles=n_angular_sections,
                    radialCycles=n_radial_sections,
                    angularPhase=angular_phase,
                )
            )

    print("sections", len(sections))
    
    for i in range(4):
        # imagine this is per frame, where I would like to decide which section is black or white
        for section in sections:
            section.contrast = np.random.choice([-1, 1]) # instead of random, we have an array to keep track at each frame whether this is black or white
            section.draw()
        win.flip()
        core.wait(1.0) # added just so we can see the change (for this ticket example only)

    psychopy.event.waitKeys()

This code works, and we almost had it, but each angular x radial section contain both the black and the white portion (two portions). Instead, we just want to have one portion per section (lets say 1 for white, and -1 for black).

Greatly appreciate your inputs thus far.

Ok, I think you can try to achieve this using the tex argument, heres something to work with. It alternates the color of the inner circle for each segment using the getTex function. There may be a better way, but this is all I have found so far

from psychopy import visual, core
import numpy as np

win = visual.Window([1200,800], fullscr=True, monitor="testMonitor", units="pix")

stim_diameter_pix = 512
n_angular_sections = 4
n_radial_sections = 1
angular_phase = .25
angular_size_deg = 360 / n_angular_sections


def getTex(inv):
    tex = np.zeros(shape=(4, 2))
    if inv:
        tex[0] = np.array((-1, 1)) # outer ring - set to zero to make invisible
        tex[1] = np.array((1, 1)) # center ring
        tex[2] = np.array((-1, 1)) # center inner ring
        tex[3] = np.array((1, -1)) # center outer ring
        return tex
    tex[0] = np.array((-1, 1)) # outer ring
    tex[1] = np.array((-1, -1)) # center ring
    tex[2] = np.array((-1, 1)) # center inner ring
    tex[3] = np.array((1, -1)) # center outer ring
    return tex

sections = []

for i_radial_section in range(n_radial_sections):
    idx = 0
    for i_angular_section in range(n_angular_sections):
        
        sections.append(
            visual.RadialStim(
                win=win,
                size=(stim_diameter_pix,) * 2,
                units="pix",
                visibleWedge=(0, angular_size_deg),
                ori=i_angular_section * angular_size_deg,
                angularCycles=2,
                radialCycles=n_radial_sections,
                angularPhase=angular_phase,
                tex=getTex(idx%2)
            )
        )
        idx += 1

        
for i in range(4):
        # imagine this is per frame, where I would like to decide which section is black or white
        for section in sections:
            section.draw()
        win.flip()
        core.wait(1)



1 Like

Does anyone has input on how to create a RadialStim such that each angular x radial section only contain one portion per section (lets say 1 for white, and -1 for black)? Not each angular x radial section contain both the black and the white portion (two portions)