Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0560b07
commit 0f86a01
Showing
1 changed file
with
168 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |