Skip to content

Commit

Permalink
Absorb bessel into components.waves
Browse files Browse the repository at this point in the history
  • Loading branch information
JorisVincent committed Mar 21, 2023
1 parent 8b3db94 commit 69f5c2f
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 71 deletions.
1 change: 0 additions & 1 deletion stimupy/components/__init__.py
Expand Up @@ -237,7 +237,6 @@ def create_overview():
"disc": circulars.disc(**p, radius=3),
"ring": circulars.ring(**p, radii=(1, 3)),
"annulus (=ring)": circulars.annulus(**p, radii=(1, 3)),
"bessel": circulars.bessel(**p, frequency=1),
"circular_sine_wave": circulars.sine_wave(**p, frequency=0.5),
"circular_square_wave": circulars.square_wave(**p, frequency=0.5),
# edges
Expand Down
69 changes: 1 addition & 68 deletions stimupy/components/circulars.py
Expand Up @@ -4,14 +4,13 @@

from stimupy.components import image_base, mask_elements, waves
from stimupy.utils import resolution
from stimupy.utils.utils import apply_bessel, round_to_vals
from stimupy.utils.utils import round_to_vals

__all__ = [
"disc_and_rings",
"disc",
"ring",
"annulus",
"bessel",
"sine_wave",
"square_wave",
]
Expand Down Expand Up @@ -288,71 +287,6 @@ def ring(
annulus = ring


def bessel(
visual_size=None,
ppd=None,
shape=None,
frequency=None,
order=0,
intensity_rings=(1.0, 0.0),
origin="mean",
):
"""Draw a Bessel stimulus, i.e. draw circular rings following an nth order
Bessel function of a given frequency.
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 circular grating, in cycles per degree
order : int
n-th order Bessel function
intensity_rings : (float, float)
intensity values of rings, first value indicating center intensity
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"),
empty mask (key: "ring_mask"),
and additional keys containing stimulus parameters
"""

base = image_base(
visual_size=visual_size,
ppd=ppd,
shape=shape,
rotation=0,
origin=origin,
)

arr = base["radial"] * frequency * 2 * np.pi
img = apply_bessel(arr, order=order)
img = (img - img.min()) / (img.max() - img.min())
img = img * (intensity_rings[0] - intensity_rings[1]) + intensity_rings[1]

stim = {
"img": img,
"ring_mask": np.zeros(base["shape"]).astype(int),
"visual_size": base["visual_size"],
"ppd": base["ppd"],
"shape": base["shape"],
"order": order,
"frequency": frequency,
"intensity_rings": intensity_rings,
}
return stim


def sine_wave(
visual_size=None,
ppd=None,
Expand Down Expand Up @@ -542,7 +476,6 @@ def square_wave(
"disc": disc(**p, radius=3),
"disc_and_rings": disc_and_rings(**p, radii=(1, 2, 3)),
"ring": ring(**p, radii=(1, 2)),
"bessel": bessel(**p, frequency=0.5),
"sine_wave": sine_wave(**p, frequency=0.5),
"square_wave": square_wave(**p, frequency=0.5),
}
Expand Down
75 changes: 74 additions & 1 deletion stimupy/components/waves.py
Expand Up @@ -7,7 +7,14 @@
from stimupy.components import draw_regions, image_base
from stimupy.utils import int_factorize, resolution
from stimupy.utils.contrast_conversions import adapt_intensity_range
from stimupy.utils.utils import round_to_vals
from stimupy.utils.utils import apply_bessel, round_to_vals

__all__ = [
"sine",
"square",
"staircase",
"bessel",
]


def resolve_grating_params(
Expand Down Expand Up @@ -624,6 +631,71 @@ def staircase(
return stim


def bessel(
visual_size=None,
ppd=None,
shape=None,
frequency=None,
order=0,
intensities=(1.0, 0.0),
origin="mean",
):
"""Draw a Bessel stimulus, i.e. draw circular rings following an nth order
Bessel function of a given frequency.
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 circular grating, in cycles per degree
order : int
n-th order Bessel function
intensities : (float, float)
intensity values of rings, first value indicating center intensity
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"),
empty mask (key: "ring_mask"),
and additional keys containing stimulus parameters
"""

base = image_base(
visual_size=visual_size,
ppd=ppd,
shape=shape,
rotation=0,
origin=origin,
)

arr = base["radial"] * frequency * 2 * np.pi
img = apply_bessel(arr, order=order)
img = (img - img.min()) / (img.max() - img.min())
img = img * (intensities[0] - intensities[1]) + intensities[1]

stim = {
"img": img,
"ring_mask": np.zeros(base["shape"]).astype(int),
"visual_size": base["visual_size"],
"ppd": base["ppd"],
"shape": base["shape"],
"order": order,
"frequency": frequency,
"intensity_rings": intensities,
}
return stim


def overview(**kwargs):
"""Generate example stimuli from this module
Expand Down Expand Up @@ -666,6 +738,7 @@ def overview(**kwargs):
"staircase - angular": staircase(**default_params, **grating_params, base_type="angular"),
"staircase - cityblock": staircase(**default_params, **grating_params, base_type="cityblock"),

"bessel": bessel(**default_params, frequency=0.5),
}
# fmt: on

Expand Down
2 changes: 1 addition & 1 deletion stimupy/papers/modelfest.py
Expand Up @@ -38,8 +38,8 @@
import pandas as pd

from stimupy.components import gaussians, lines, shapes
from stimupy.components.circulars import bessel
from stimupy.components.edges import gaussian_edge
from stimupy.components.waves import bessel
from stimupy.gabors import gabor
from stimupy.illusions import checkerboards
from stimupy.noises.binaries import binary as binary_noise
Expand Down

0 comments on commit 69f5c2f

Please sign in to comment.