Skip to content

Commit

Permalink
Merge pull request #101 from computational-psychology/refactor_targets
Browse files Browse the repository at this point in the history
Refactor target placement in various stimuli.

Add `mask_targets()` and `place_targets()` general-purpose functions which can be used to designate target "elements" (bars, rings, frames, etc.) from an existing `_mask`.

Integrate new functions into `waves`, `pinwheels`, `rings` and `whites`

Add `rings.circular_generalized()` and `bullseye.circular_generalized()` using new functions

This single-implementation of target placement has the advantage that it all works the same: first element is 1, target_indices can be negative (counting "backwards" from the last bar/ring/etc.).
  • Loading branch information
JorisVincent committed Sep 6, 2023
2 parents 37b70c3 + dea6b57 commit 885ec6c
Show file tree
Hide file tree
Showing 20 changed files with 692 additions and 342 deletions.
93 changes: 93 additions & 0 deletions docs/reference/demos/stimuli/bullseyes.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,99 @@ out = iw.interactive_output(
display(ui, out)
```

## Circular bullseye, generalized
{py:func}`stimupy.stimuli.bullseyes.circular_generalized`

```{code-cell} ipython3
import ipywidgets as iw
from stimupy.utils import plot_stim
from stimupy.stimuli.bullseyes import circular_generalized
# Define widgets
w_height = iw.IntSlider(value=10, min=1, max=20, description="height [deg]")
w_width = iw.IntSlider(value=10, min=1, max=20, description="width [deg]")
w_ppd = iw.IntSlider(value=20, min=1, max=40, description="ppd")
w_radius1 = iw.FloatSlider(value=1, min=0, max=2, description="radius1 [deg]")
w_radius2 = iw.FloatSlider(value=2, min=1, max=3, description="radius2 [deg]")
w_radius3 = iw.FloatSlider(value=3, min=2, max=4, description="radius2 [deg]")
w_int1 = iw.FloatSlider(value=1, min=0, max=1, description="int-ring1")
w_int2 = iw.FloatSlider(value=0.3, min=0, max=1, description="int-ring2")
w_int3 = iw.FloatSlider(value=0.8, min=0, max=1, description="int-ring3")
w_int_back = iw.FloatSlider(value=0., min=0, max=1, description="intensity background")
w_ori = iw.Dropdown(value="center", options=['mean', 'corner', 'center'], description="origin")
w_rot = iw.FloatSlider(value=0, min=0, max=360, description="rotation [deg]")
w_mask = iw.Dropdown(value=None, options=[None, 'target_mask', 'frame_mask'], description="add mask")
w_tint = iw.FloatSlider(value=0.5, min=0, max=1, description="target int")
# Layout
b_im_size = iw.HBox([w_height, w_width, w_ppd])
b_geometry = iw.HBox([w_radius1, w_radius2, w_radius3])
b_intensities = iw.HBox([w_int1, w_int2, w_int3, w_int_back])
b_target = iw.HBox([w_tint])
b_add = iw.HBox([w_ori, w_rot, w_mask])
ui = iw.VBox([b_im_size, b_geometry, b_intensities, b_target, b_add])
# Function for showing stim
def show_circular_generalized(
height=None,
width=None,
ppd=None,
radius1=None,
radius2=None,
radius3=None,
int1=None,
int2=None,
int3=None,
intensity_background=None,
origin=None,
add_mask=False,
intensity_target=None,
rotation=0.0,
):
try:
stim = circular_generalized(
visual_size=(height, width),
ppd=ppd,
radii=(radius1, radius2, radius3),
intensity_rings=(int1, int2, int3),
intensity_background=intensity_background,
origin=origin,
intensity_target=intensity_target,
)
plot_stim(stim, mask=add_mask)
except Exception as e:
raise ValueError(f"Invalid parameter combination: {e}") from None
# Set interactivity
out = iw.interactive_output(
show_circular_generalized,
{
"height": w_height,
"width": w_width,
"ppd": w_ppd,
"radius1": w_radius1,
"radius2": w_radius2,
"radius3": w_radius3,
"int1": w_int1,
"int2": w_int2,
"int3": w_int3,
"intensity_background": w_int_back,
"origin": w_ori,
"add_mask": w_mask,
"intensity_target": w_tint,
"rotation": w_rot,
},
)
# Show
display(ui, out)
```



## Circular, Two-sided
{py:func}`stimupy.stimuli.bullseyes.circular_two_sided`
Expand Down
93 changes: 93 additions & 0 deletions docs/reference/demos/stimuli/rings.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,99 @@ out = iw.interactive_output(
display(ui, out)
```

## Circular, generalized
{py:func}`stimupy.stimuli.rings.circular_generalized`

```{code-cell} ipython3
import ipywidgets as iw
from stimupy.utils import plot_stim
from stimupy.stimuli.rings import circular_generalized
# Define widgets
w_height = iw.IntSlider(value=10, min=1, max=20, description="height [deg]")
w_width = iw.IntSlider(value=10, min=1, max=20, description="width [deg]")
w_ppd = iw.IntSlider(value=20, min=1, max=40, description="ppd")
w_radius1 = iw.FloatSlider(value=1, min=0, max=2, description="radius1 [deg]")
w_radius2 = iw.FloatSlider(value=2, min=1, max=3, description="radius2 [deg]")
w_radius3 = iw.FloatSlider(value=3, min=2, max=4, description="radius2 [deg]")
w_int1 = iw.FloatSlider(value=1, min=0, max=1, description="int-ring1")
w_int2 = iw.FloatSlider(value=0.3, min=0, max=1, description="int-ring2")
w_int3 = iw.FloatSlider(value=0.8, min=0, max=1, description="int-ring3")
w_int_back = iw.FloatSlider(value=0., min=0, max=1, description="intensity background")
w_ori = iw.Dropdown(value="center", options=['mean', 'corner', 'center'], description="origin")
w_mask = iw.Dropdown(value=None, options=[None, 'target_mask', 'frame_mask'], description="add mask")
w_tidx = iw.IntSlider(value=1, min=1, max=4, description="target idx")
w_tint = iw.FloatSlider(value=0.5, min=0, max=1, description="target int")
# Layout
b_im_size = iw.HBox([w_height, w_width, w_ppd])
b_geometry = iw.HBox([w_radius1, w_radius2, w_radius3])
b_intensities = iw.HBox([w_int1, w_int2, w_int3, w_int_back])
b_target = iw.HBox([w_tidx, w_tint])
b_add = iw.HBox([w_ori, w_mask])
ui = iw.VBox([b_im_size, b_geometry, b_intensities, b_target, b_add])
# Function for showing stim
def show_circular_generalized(
height=None,
width=None,
ppd=None,
radius1=None,
radius2=None,
radius3=None,
int1=None,
int2=None,
int3=None,
intensity_background=None,
origin=None,
add_mask=False,
intensity_target=None,
target_indices=None,
):
try:
stim = circular_generalized(
visual_size=(height, width),
ppd=ppd,
radii=(radius1, radius2, radius3),
intensity_rings=(int1, int2, int3),
intensity_background=intensity_background,
origin=origin,
intensity_target=intensity_target,
target_indices=target_indices,
)
plot_stim(stim, mask=add_mask)
except Exception as e:
raise ValueError(f"Invalid parameter combination: {e}") from None
# Set interactivity
out = iw.interactive_output(
show_circular_generalized,
{
"height": w_height,
"width": w_width,
"ppd": w_ppd,
"radius1": w_radius1,
"radius2": w_radius2,
"radius3": w_radius3,
"int1": w_int1,
"int2": w_int2,
"int3": w_int3,
"intensity_background": w_int_back,
"origin": w_ori,
"add_mask": w_mask,
"target_indices": w_tidx,
"intensity_target": w_tint,
},
)
# Show
display(ui, out)
```

## Two-sided rings
{py:func}`stimupy.stimuli.rings.circular_two_sided`

Expand Down
2 changes: 1 addition & 1 deletion stimupy/components/texts.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def text(
fontsize,
encoding="unic",
)
except IOError:
except OSError:
font = ImageFont.load_default()

# Determine dimensions of total text
Expand Down
20 changes: 10 additions & 10 deletions stimupy/papers/RHS2007.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ def WE_thick(ppd=PPD, pad=True):
"frequency": 4.0 / width,
"intensity_bars": (v1, v3),
"intensity_target": v2,
"target_indices": (2, 5),
"target_indices": (3, 6),
"target_heights": 4.0,
"period": "even",
}
Expand Down Expand Up @@ -200,7 +200,7 @@ def WE_thin_wide(ppd=PPD, pad=True):
"frequency": 8.0 / width,
"intensity_bars": (v3, v1),
"intensity_target": v2,
"target_indices": (3, 12),
"target_indices": (4, 13),
"target_heights": 2.0,
"period": "even",
}
Expand Down Expand Up @@ -252,7 +252,7 @@ def WE_dual(ppd=PPD, pad=True):
"frequency": 4.0 / width,
"intensity_bars": (v1, v3),
"intensity_target": v2,
"target_indices": (2, 5),
"target_indices": (3, 6),
"target_heights": 2.0,
"period": "even",
}
Expand Down Expand Up @@ -322,8 +322,8 @@ def WE_anderson(ppd=PPD, pad=True):
"frequency": 8.0 / width,
"intensity_bars": (v1, v3),
"intensity_target": v2,
"target_indices_top": (5,),
"target_indices_bottom": (10,),
"target_indices_top": (6,),
"target_indices_bottom": (11,),
"target_center_offset": height / 10.0,
"target_height": height / 5.0,
"intensity_stripes": (v1, v3),
Expand Down Expand Up @@ -391,8 +391,8 @@ def WE_howe(ppd=PPD, pad=True):
"frequency": 8.0 / width,
"intensity_bars": (v1, v3),
"intensity_target": v2,
"target_indices_top": (5,),
"target_indices_bottom": (10,),
"target_indices_top": (6,),
"target_indices_bottom": (11,),
"target_center_offset": height / 5.0,
"target_height": height / 5.0,
"intensity_stripes": (v1, v3),
Expand Down Expand Up @@ -712,7 +712,7 @@ def WE_circular1(ppd=PPD, pad=True):
params = {
"ppd": ppd,
"frequency": 8.0 / height,
"target_indices": 4,
"target_indices": 5,
"intensity_background": v2,
"intensity_target": v2,
"clip": True,
Expand Down Expand Up @@ -773,7 +773,7 @@ def WE_circular05(ppd=PPD, pad=True):
params = {
"ppd": ppd,
"frequency": 16.0 / height,
"target_indices": 10,
"target_indices": 11,
"intensity_background": v2,
"intensity_target": v2,
"clip": True,
Expand Down Expand Up @@ -834,7 +834,7 @@ def WE_circular025(ppd=PPD, pad=True):
params = {
"ppd": ppd,
"frequency": 32.0 / height,
"target_indices": 22,
"target_indices": 23,
"intensity_background": v2,
"intensity_target": v2,
"clip": True,
Expand Down
16 changes: 8 additions & 8 deletions stimupy/papers/domijan2015.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ def grating(visual_size=VSIZES["grating"], ppd=PPD, shape=SHAPES["grating"]):
"visual_size": single_vissize,
"ppd": ppd,
"n_bars": 9,
"target_indices": (4,),
"target_indices": (5,),
"bar_width": 1.0 * visual_resize,
}

Expand Down Expand Up @@ -636,7 +636,7 @@ def white(visual_size=VSIZES["white"], ppd=PPD, pad=PAD, shape=SHAPES["white"]):
"visual_size": visual_size,
"ppd": ppd,
"frequency": 4.0 / visual_size[1],
"target_indices": (2, 5),
"target_indices": (3, 6),
"target_heights": 2.1 * visual_resize,
"period": "even",
}
Expand Down Expand Up @@ -1080,8 +1080,8 @@ def white_yazdanbakhsh(
"visual_size": visual_size,
"ppd": ppd,
"frequency": 4.0 / visual_size[1],
"target_indices_top": (2,),
"target_indices_bottom": (5,),
"target_indices_top": (3,),
"target_indices_bottom": (6,),
"target_center_offset": 0.0,
"target_heights": visual_size[0] / 4.0,
"gap_size": visual_size[0] / 10.0,
Expand Down Expand Up @@ -1165,8 +1165,8 @@ def white_anderson(
"visual_size": visual_size,
"ppd": ppd,
"frequency": 5.0 / visual_size[1],
"target_indices_top": (2,),
"target_indices_bottom": (7,),
"target_indices_top": (3,),
"target_indices_bottom": (8,),
"target_center_offset": visual_size[0] / 10.0,
"target_height": visual_size[0] / 5.0,
"stripe_center_offset": visual_size[0] / 5.0,
Expand Down Expand Up @@ -1249,8 +1249,8 @@ def white_howe(visual_size=VSIZES["white_howe"], ppd=PPD, shape=SHAPES["white_ho
"visual_size": visual_size,
"ppd": ppd,
"frequency": 5.0 / visual_size[1],
"target_indices_top": (2,),
"target_indices_bottom": (7,),
"target_indices_top": (3,),
"target_indices_bottom": (8,),
"target_center_offset": visual_size[0] / 5.0,
"target_height": visual_size[0] / 5.0,
"period": "even",
Expand Down
4 changes: 2 additions & 2 deletions stimupy/papers/murray2020.py
Original file line number Diff line number Diff line change
Expand Up @@ -731,8 +731,8 @@ def white(ppd=PPD):
"ppd": ppd,
"visual_size": (8.0, 8.0),
"frequency": 4.0 / 8.0,
"target_indices_top": (1, 3, 5),
"target_indices_bottom": (2, 4, 6),
"target_indices_top": (2, 4, 6),
"target_indices_bottom": (3, 5, 7),
"target_center_offset": 2,
"target_heights": 2,
"intensity_bars": (70, 17.5),
Expand Down
Loading

0 comments on commit 885ec6c

Please sign in to comment.