Create stimuli spanning a parameter space#
One of the strengths of stimupy is that its fully parameterized stimulus functions make it easy to create stimulus parameter spaces — or, more briefly, stimspaces.
A stimspace is a systematic variation of a stimulus across one or more parameter dimensions.
This is useful for experiments, computational modeling, and visualizations where you want to explore how changing certain stimulus parameters affects a stimulus.
Create a stimspace in stimupy#
stimupy provides two main utility functions for building stimspaces:
utils.permutate_params— generates all possible parameter combinations as dictionaries.utils.create_stimspace_stimuli— uses these combinations to generate actual stimulus images.
To define a stimspace, supply the parameters you want to vary as lists.
A parameter with a single value should still be wrapped in a list for consistency.
Example: 1D stimspace for Gabors#
To generate a stimspace, we first need to know the relevant variables of the stimulus function we want to use. Here, let’s explore stimspaces for Gabors.
from stimupy.stimuli.gabors import gabor
help(gabor)
Help on function gabor in module stimupy.stimuli.gabors:
gabor(
visual_size=None,
ppd=None,
shape=None,
frequency=None,
n_bars=None,
bar_width=None,
period='ignore',
rotation=0.0,
phase_shift=0,
intensities=(0.0, 1.0),
origin='center',
round_phase_width=False,
sigma=None
)
Draw a Gabor: a sinewave grating in a Gaussian envelope
Parameters
----------
visual_size : Sequence[Number, Number], Number, or None (default)
visual size [height, width] of image, in degrees
ppd : Sequence[Number, Number], Number, or None (default)
pixels per degree [vertical, horizontal]
shape : Sequence[Number, Number], Number, or None (default)
shape [height, width] of image, in pixels
frequency : Number, or None (default)
spatial frequency of grating, in cycles per degree visual angle
n_bars : Number, or None (default)
number of bars in the grating
bar_width : Number, or None (default)
width of a single bar, in degrees visual angle
sigma : float or (float, float)
sigma of Gaussian in degree visual angle (y, x)
period : "even", "odd", "either" or "ignore" (default)
ensure whether the grating has "even" number of phases, "odd"
number of phases, either or whether not to round the number of
phases ("ignore")
rotation : float, optional
rotation (in degrees), counterclockwise, by default 0.0 (horizontal)
phase_shift : float
phase shift of grating in degrees
intensities : Sequence[float, ...]
maximal intensity value for each bar, by default (0.0, 1.0).
origin : "corner", "mean" or "center"
if "corner": set origin to upper left corner
if "mean": set origin to hypothetical image center (default)
if "center": set origin to real center (closest existing value to mean)
Returns
-------
dict[str, Any]
dict with the stimulus (key: "img"),
mask with integer index for each bar (key: "grating_mask"),
and additional keys containing stimulus parameters
In this example, we vary the frequency parameter while keeping the other parameters constant.
from stimupy.utils import permutate_params
params = {
"visual_size": [1.], # Each parameter must be in a list []
"ppd": [100],
"sigma": [0.1],
"frequency": [1, 2, 4], # Varying frequency spans the stimspace
}
permuted_params = permutate_params(params=params)
permuted_params
[{'visual_size': 1.0, 'ppd': 100, 'sigma': 0.1, 'frequency': 1},
{'visual_size': 1.0, 'ppd': 100, 'sigma': 0.1, 'frequency': 2},
{'visual_size': 1.0, 'ppd': 100, 'sigma': 0.1, 'frequency': 4}]
Now we generate and plot the stimuli for this 1D stimspace:
from stimupy.utils import create_stimspace_stimuli, plot_stimuli
space_1d = create_stimspace_stimuli(
stimulus_function=gabor,
permutations_dicts=permuted_params,
)
plot_stimuli(space_1d, units="deg")
Example: 2D stimspace for Gabors#
Before, we have only focused on a single stimulus parameter. However, you can vary as many stimulus parameters at once as you like. In the next example, we vary both the frequency and the sigma of the Gabor to create a 2D stimspace.
params["sigma"] = [0.05, 0.1, 0.15] # Now vary sigma as well
permuted_params_2d = permutate_params(params=params)
permuted_params_2d
[{'visual_size': 1.0, 'ppd': 100, 'sigma': 0.05, 'frequency': 1},
{'visual_size': 1.0, 'ppd': 100, 'sigma': 0.05, 'frequency': 2},
{'visual_size': 1.0, 'ppd': 100, 'sigma': 0.05, 'frequency': 4},
{'visual_size': 1.0, 'ppd': 100, 'sigma': 0.1, 'frequency': 1},
{'visual_size': 1.0, 'ppd': 100, 'sigma': 0.1, 'frequency': 2},
{'visual_size': 1.0, 'ppd': 100, 'sigma': 0.1, 'frequency': 4},
{'visual_size': 1.0, 'ppd': 100, 'sigma': 0.15, 'frequency': 1},
{'visual_size': 1.0, 'ppd': 100, 'sigma': 0.15, 'frequency': 2},
{'visual_size': 1.0, 'ppd': 100, 'sigma': 0.15, 'frequency': 4}]
stimspace_2d = create_stimspace_stimuli(
stimulus_function=gabor,
permutations_dicts=permuted_params_2d,
)
plot_stimuli(stimspace_2d, units="deg")