I know there is RadialStim. But how do I define sections within this stimulus, such that each section reverse at a different rate (count by the number of frames), where reverse means turn from black to white and vice versa.
For this example, there are 12 sections across the angularCycles, and 4 across the radialPhase. A total of 48 sections, reversing at a different rate.
You could get something similar by using the mask and ori parameters to create a RadialStim for each of the 48 sections. The temporal contrast profile of each section can then be controlled independently.
A rough demo:
import numpy as np
import psychopy.visual
import psychopy.event
stim_diameter_pix = 512
stim_radius_pix = stim_diameter_pix // 2
n_angular_sections = 12
n_radial_sections = 4
angular_size_deg = 360 / n_angular_sections
n_angular_cycles_per_section = 2
n_angular_cycles = n_angular_cycles_per_section * n_angular_sections
angular_phase = 0.25
n_radial_cycles_per_section = 2
n_radial_cycles = n_radial_cycles_per_section * n_radial_sections
base_radial_mask = np.zeros(stim_radius_pix)
base_radial_mask[:(stim_radius_pix // n_radial_sections) - 2] = 1
empty_centre_radius_pix = 10
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):
radial_mask = np.zeros(stim_radius_pix)
# shift the mask to the correct radial section
radial_mask = np.roll(
base_radial_mask,
i_radial_section * stim_radius_pix // n_radial_sections,
)
# hide centre region
radial_mask[:empty_centre_radius_pix] = 0.0
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_cycles,
angularPhase=angular_phase,
radialCycles=n_radial_cycles,
mask=radial_mask,
)
)
for section in sections:
# set as required for this section
section.contrast = np.random.choice([-1, 1])
section.draw()
win.flip()
psychopy.event.waitKeys()
Thanks @djmannion for your codes, it shows that we can define the black and white squares within RadialStim.
I see that we can use mask parameter, and in your code is defined by base_radial_mask. For this demo stimulus, the values in base_radial_mask looks like this:
There are 256 elements in this array (base_radial_mask), what does each element associates to actually? Since I have to reverse each section at a different rate, where reverse means turning black squares to white. Understanding how mask and base_radial_mask works might be the way to perform reversal.
You can do the reversal via section.contrast, rather than changing the mask. In the demo code, I am randomly reversing the contrast of each section. You would instead need to reverse the contrast of a given section according to its required rate.
Each element corresponds to a radial distance from the centre and specifies its visibility. The base_radial_mask defines the innermost section, and is then moved ‘outwards’ for each subsequent radial section.