Skip to content

Commit

Permalink
closes #84; added mueller_lyer
Browse files Browse the repository at this point in the history
  • Loading branch information
LynnSchmittwilken committed Jan 26, 2023
1 parent 0560b07 commit 0f86a01
Showing 1 changed file with 168 additions and 0 deletions.
168 changes: 168 additions & 0 deletions stimuli/illusions/mueller_lyer.py
@@ -0,0 +1,168 @@
import numpy as np
import copy
from stimuli.components import lines
from stimuli.utils import resolution


__all__ = [
"mueller_lyer",
]

def mueller_lyer(
visual_size=None,
ppd=None,
shape=None,
outer_lines_length=None,
outer_lines_angle=45,
target_length=None,
line_width=0,
intensity_outer_lines=1.0,
intensity_target=0.5,
intensity_background=0.0,
):
"""
Mueller-Lyer illusion
Parameters
----------
visual_size : Sequence[Number, Number], Number, or None (default)
visual size [height, width] of grating, 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 grating, in pixels
outer_lines_length : Number
length of outer lines in degrees visual angle
outer_lines_angle : Number
angle of outer lines in degrees. Must be between -180 and 180 degrees.
target_length : Number
length of target line in degrees visual angle
line_width :
line width in degrees visual angle; if 0 (default), line width is 1 px
intensity_outer_lines : Number
intensity value of outer lines
intensity_target : Number
intensity value of target line
intensity_background : Number
intensity value of background
Returns
----------
dict[str, Any]
dict with the stimulus (key: "img"),
mask with integer index for each target (key: "target_mask"),
and additional keys containing stimulus parameters
References
----------
Mueller-Lyer, F. (1896). Zur Lehre von den optischen Taeuschungen. Ueber
Kontrast und Konfluxion. Zeitschrift fuer Psychologie und Physiologie
der Sinnesorgane, IX, 1-16.
"""
# Resolve resolution
shape, visual_size, ppd = resolution.resolve(shape=shape, visual_size=visual_size, ppd=ppd)

if outer_lines_angle < -180 or outer_lines_angle > 180:
raise ValueError("outer_lines_angle should be between -180 and 180 deg")

angle1 = copy.deepcopy(outer_lines_angle) + 90
angle2 = -angle1 - 180
angle4 = copy.deepcopy(outer_lines_angle) - 90
angle3 = -angle4 - 180

target_line = lines.line(
visual_size=visual_size,
ppd=ppd,
shape=shape,
line_position=None,
line_length=target_length,
line_width=line_width,
rotation=90,
intensity_line=intensity_target-intensity_background,
intensity_background=0,
origin="center",
)

oline1 = lines.line(
visual_size=visual_size,
ppd=ppd,
shape=shape,
line_position=(0, -target_length/2),
line_length=outer_lines_length,
line_width=line_width,
rotation=angle1,
intensity_line=intensity_outer_lines-intensity_background,
intensity_background=0,
origin="center",
)

oline2 = lines.line(
visual_size=visual_size,
ppd=ppd,
shape=shape,
line_position=(0, -target_length/2),
line_length=outer_lines_length,
line_width=line_width,
rotation=angle2,
intensity_line=intensity_outer_lines-intensity_background,
intensity_background=0,
origin="center",
)

oline3 = lines.line(
visual_size=visual_size,
ppd=ppd,
shape=shape,
line_position=(0, target_length/2),
line_length=outer_lines_length,
line_width=line_width,
rotation=angle3,
intensity_line=intensity_outer_lines-intensity_background,
intensity_background=0,
origin="center",
)

oline4 = lines.line(
visual_size=visual_size,
ppd=ppd,
shape=shape,
line_position=(0, target_length/2),
line_length=outer_lines_length,
line_width=line_width,
rotation=angle4,
intensity_line=intensity_outer_lines-intensity_background,
intensity_background=0,
origin="center",
)

# Add outer lines together
olines = oline1["img"] + oline2["img"] + oline3["img"] + oline4["img"]
omasks1 = oline1["line_mask"]*2 + oline2["line_mask"]*3
omasks2 = oline3["line_mask"]*4 + oline4["line_mask"]*5

target_line["img"] += olines
target_line["img"] = np.where(target_line["img"] > intensity_outer_lines, intensity_outer_lines, target_line["img"])

target_line["line_mask"] += omasks1
target_line["line_mask"] = np.where(target_line["line_mask"] > 3, 3, target_line["line_mask"])
target_line["line_mask"] += omasks2
target_line["line_mask"] = np.where(target_line["line_mask"] > 5, 5, target_line["line_mask"])

target_line["target_mask"] = np.where(target_line["line_mask"] == 1, 1, 0).astype(int)
return target_line



if __name__ == "__main__":
from stimuli.utils import plot_stim
p1 = {
"visual_size": 10,
"ppd": 20,
"outer_lines_length": 1,
"outer_lines_angle" : 45,
"target_length": 6,
"line_width": 0.1,
}

stim = mueller_lyer(**p1)
plot_stim(stim, stim_name="mueller-lyer", mask=True, save=None)

0 comments on commit 0f86a01

Please sign in to comment.