Skip to content

Commit

Permalink
Merge branch 'main' into feat_waves
Browse files Browse the repository at this point in the history
  • Loading branch information
LynnSchmittwilken committed Mar 23, 2023
2 parents 21b4d8d + 1c76f9c commit 799fb5b
Show file tree
Hide file tree
Showing 40 changed files with 591 additions and 476 deletions.
8 changes: 7 additions & 1 deletion docs/getting_started/getting_started.md
@@ -1,9 +1,15 @@
# Getting started with `stimupy`

The following pages serve as **tutorial**,
walking you through the very basics of installing and using `stimupy`.

Along the way, they also refer to some [topic guides](../topic_guides/),
which have more in-depth explanation on various concepts and design decisions.

```{toctree}
:numbered:
installation
first_stim
illusion
stimulus
replicate
```
4 changes: 2 additions & 2 deletions docs/getting_started/replicate.md
Expand Up @@ -18,10 +18,10 @@ Since `stimupy`s functions are highly parameterizable,
lots of variants of a stimulus can be created,
and thus specific existing parameterizations can be recreated.

For a large selection of the generic `stimupy.illusions`,
For a large selection of the generic `stimupy.stimuli`,
there are specific parameterizations in the published literature.
Some of these are implement in stimupy as well,
under the corresponding [`stimupy.papers`](../reference/api/stimupy.papers).
under the corresponding [`stimupy.papers`](../reference/_api/stimupy.papers).

```{code-cell}
:tags: [hide-cell]
Expand Down
Expand Up @@ -10,13 +10,11 @@ kernelspec:
name: python3
---

# Exploring an illusion
# Exploring more complex stimuli

The geometric components in [`stimupy.components`](../reference/api/stimupy.components)
The geometric components in [`stimupy.components`](../reference/_api/stimupy.components)
form the basic building blocks for all stimuli implement in `stimupy`.
More complex stimuli can be composed using the functions that generate components.
Included in `stimupy` is a large set of functionst to generate more complex stimuli,
which we term [`illusions`](../reference/api/stimupy.illusions).

## Simultaneous Brightness Contrast (SBC)

Expand All @@ -26,8 +24,14 @@ import matplotlib.pyplot as plt
from stimupy.utils import plot_stim
```

Included in `stimupy` is a large set of functions
to generate more complex [`stimuli`](../reference/_api/stimupy.stimuli).
These are generally subdivided into specifically named submodules.
All of these can be accessed either through `stimupy.stimuli.<submodule>`,
or by `from stimupy import <submodule>`:

```{code-cell}
from stimupy.illusions import sbcs
from stimupy import sbcs
stim = sbcs.basic(visual_size=(6,8), ppd=10, target_size=(2,2))
Expand All @@ -45,8 +49,8 @@ plot_stim(component)
plt.show()
```

However, some of the stimulus parameters have different names in `illusions`.
In particular, **all** `illusions` have the concept of a `target` region(s):
However, some of the stimulus parameters have different names in `stimuli`.
In particular, **all** `stimuli` have the concept of a `target` region(s):
image regions that are of some particular scientific interest in this stimulus.
For an SBC stimulus, this would be the rectangular path.
Thus, the `sbcs.basic` function takes a
Expand Down Expand Up @@ -81,9 +85,26 @@ plot_stim(two_sided_stim)
plt.show()
```

## White's illusion
## Todorovic illusion
```{code-cell}
from stimupy import todorovics
stim_tod = todorovics.two_sided_rectangle(
visual_size=(10,20),
ppd=10,
target_size=3,
covers_size=1.5,
covers_offset=2
)
plot_stim(stim_tod)
plt.show()
```

## White's effect stimulus
```{code-cell}
from stimupy.illusions import whites
from stimupy import whites
stim_whites = whites.white_two_rows(
visual_size=(10,12),
Expand Down
101 changes: 32 additions & 69 deletions stimupy/components/__init__.py
Expand Up @@ -2,6 +2,7 @@

import numpy as np

from stimupy.components import * # angulars, edges, frames, gaussians, lines, radials, shapes, waves
from stimupy.utils import resolution

__all__ = [
Expand Down Expand Up @@ -210,9 +211,6 @@ def draw_regions(mask, intensities, intensity_background=0.5):
return img


from stimupy.components import angulars, edges, frames, gaussians, lines, radials, shapes, waves


def overview(skip=False):
"""Generate example stimuli from this module
Expand All @@ -221,72 +219,36 @@ def overview(skip=False):
dict[str, dict]
Dict mapping names to individual stimulus dicts
"""

p = {
"visual_size": 10,
"ppd": 20,
}

# fmt: off
stimuli = {
# angulars
"wedge": angulars.wedge(**p, width=30, radius=3),
"angular_grating": angulars.grating(**p, n_segments=8),
"pinwheel": angulars.pinwheel(**p, n_segments=8, radius=3),
# circulars
"rings (generalized)": radials.rings(**p, radii=[1, 2, 3]),
"disc": radials.disc(**p, radius=3),
"ring": radials.ring(**p, radii=(1, 3)),
"annulus (=ring)": radials.annulus(**p, radii=(1, 3)),
# edges
"step_edge": edges.step_edge(**p),
"gaussian_edge": edges.gaussian_edge(**p, sigma=1.5),
"cornsweet_edge": edges.cornsweet_edge(**p, ramp_width=3),
# frames
"frames": frames.frames(**p, radii=(1, 2, 3)),
# gaussians
"gaussian": gaussians.gaussian(**p, sigma=(1, 2)),
# lines
"line": lines.line(**p, line_length=3),
"dipole": lines.dipole(**p, line_length=3, line_gap=0.5),
"line_circle": lines.circle(**p, radius=3),
# shapes
"rectangle": shapes.rectangle(**p, rectangle_size=3),
"triangle": shapes.triangle(**p, triangle_size=3),
"cross": shapes.cross(**p, cross_size=3, cross_thickness=0.5),
"parallelogram": shapes.parallelogram(**p, parallelogram_size=(3, 3, 1)),
"ellipse": shapes.ellipse(**p, radius=(2, 3)),
"shape_wedge": shapes.wedge(**p, width=30, radius=3),
"shape_annulus": shapes.annulus(**p, radii=(1, 3)),
"shape_ring": shapes.ring(**p, radii=(1, 3)),
"shape_disc": shapes.disc(**p, radius=3),
}
# fmt: on

# stimuli = {}
# for stimmodule_name in __all__:
# if stimmodule_name in ["overview", "plot_overview"]:
# pass

# print(f"Generating stimuli from {stimmodule_name}")
# # Get a reference to the actual module
# stimmodule = globals()[stimmodule_name]
# try:
# stims = stimmodule.overview()

# # Accumulate
# stimuli.update(stims)
# except NotImplementedError as e:
# if not skip:
# raise e
# # Skip stimuli that aren't implemented
# print("-- not implemented")
# pass
stimuli = {}
for stimmodule_name in __all__:
if stimmodule_name in [
"overview",
"plot_overview",
"draw_regions",
"image_base",
"mask_elements",
]:
continue

print(f"Generating stimuli from {stimmodule_name}")
# Get a reference to the actual module
stimmodule = globals()[stimmodule_name]
try:
stims = stimmodule.overview()

# Accumulate
stimuli.update(stims)
except NotImplementedError as e:
if not skip:
raise e
# Skip stimuli that aren't implemented
print("-- not implemented")
pass

return stimuli


def plot_overview(mask=False, save=None, extent_key="shape"):
def plot_overview(mask=False, save=None, units="deg"):
"""Plot overview of examples in this module (and submodules)
Parameters
Expand All @@ -297,15 +259,16 @@ def plot_overview(mask=False, save=None, extent_key="shape"):
save : None or str, optional
If None (default), do not save the plot.
If string is provided, save plot under this name.
extent_key : str, optional
Key to extent which will be used for plotting.
Default is "shape", using the image size in pixels as extent.
units : "px", "deg" (default), or str
what units to put on the axes, by default degrees visual angle ("deg").
If a str other than "deg"(/"degrees") or "px"(/"pix"/"pixels") is passed,
it must be the key to a tuple in stim
"""
from stimupy.utils import plot_stimuli

stims = overview(skip=True)
plot_stimuli(stims, mask=mask, extent_key=extent_key, save=save)
plot_stimuli(stims, mask=mask, units=units, save=save)


if __name__ == "__main__":
Expand Down
4 changes: 2 additions & 2 deletions stimupy/components/angulars.py
Expand Up @@ -65,7 +65,7 @@ def wedge(
rotation=0.0,
inner_radius=0.0,
intensity_wedge=1.0,
intensity_background=0.5,
intensity_background=0.0,
origin="mean",
):
"""Draw a wedge, i.e., segment of a disc
Expand All @@ -90,7 +90,7 @@ def wedge(
intensity_wedge : float, optional
intensity value of wedge, by default 1.0
intensity_background : float, optional
intensity value of background, by default 0.5
intensity value of background, by default 0.0
origin : "corner", "mean" or "center"
if "corner": set origin to upper left corner
if "mean": set origin to hypothetical image center (default)
Expand Down
46 changes: 39 additions & 7 deletions stimupy/components/edges.py
Expand Up @@ -5,13 +5,13 @@
from stimupy.components import gaussians, image_base

__all__ = [
"step_edge",
"gaussian_edge",
"cornsweet_edge",
"step",
"gaussian",
"cornsweet",
]


def step_edge(
def step(
visual_size=None,
ppd=None,
shape=None,
Expand Down Expand Up @@ -67,7 +67,7 @@ def step_edge(
return stim


def gaussian_edge(
def gaussian(
visual_size=None,
ppd=None,
shape=None,
Expand Down Expand Up @@ -105,7 +105,7 @@ def gaussian_edge(
if sigma is None:
raise ValueError("gaussian_edge() missing argument 'sigma' which is not 'None'")

stim = step_edge(
stim = step(
visual_size=visual_size,
ppd=ppd,
shape=shape,
Expand All @@ -129,7 +129,7 @@ def gaussian_edge(
return stim


def cornsweet_edge(
def cornsweet(
visual_size=None,
ppd=None,
shape=None,
Expand Down Expand Up @@ -234,3 +234,35 @@ def cornsweet_edge(
}

return stim


def overview(**kwargs):
"""Generate example stimuli from this module
Returns
-------
stims : dict
dict with all stimuli containing individual stimulus dicts.
"""
default_params = {
"visual_size": 10,
"ppd": 10,
}
default_params.update(kwargs)

# fmt: off
stimuli = {
"edges_step": step(**default_params),
"edges_gaussian": gaussian(**default_params, sigma=3),
"edges_cornsweet": cornsweet(**default_params, ramp_width=3),
}
# fmt: on

return stimuli


if __name__ == "__main__":
from stimupy.utils import plot_stimuli

stims = overview()
plot_stimuli(stims, mask=False, save=None)
2 changes: 1 addition & 1 deletion stimupy/components/frames.py
Expand Up @@ -128,7 +128,7 @@ def overview(**kwargs):

# fmt: off
stimuli = {
"frames": frames(**default_params, radii=(1, 2, 3)),
"frames_frames": frames(**default_params, radii=(1, 2, 3)),
}
# fmt: on

Expand Down
34 changes: 23 additions & 11 deletions stimupy/components/gaussians.py
Expand Up @@ -96,18 +96,30 @@ def gaussian(
return stim


if __name__ == "__main__":
from stimupy.utils.plotting import plot_stimuli
def overview(**kwargs):
"""Generate example stimuli from this module
p = {
"visual_size": (10, 8),
"ppd": 50,
"rotation": 90,
Returns
-------
stims : dict
dict with all stimuli containing individual stimulus dicts.
"""
default_params = {
"visual_size": 10,
"ppd": 10,
}
default_params.update(kwargs)

stims = {
"gaussian1": gaussian(**p, sigma=2),
"gaussian2": gaussian(**p, sigma=(3, 2)),
}
# fmt: off
stimuli = {
"gaussians_gaussian": gaussian(**default_params, sigma=(3, 1.5), rotation=70),}
# fmt: on

return stimuli


if __name__ == "__main__":
from stimupy.utils import plot_stimuli

plot_stimuli(stims, mask=True)
stims = overview()
plot_stimuli(stims, mask=False, save=None)

0 comments on commit 799fb5b

Please sign in to comment.