Skip to content

Commit

Permalink
Merge remote-tracking branch 'tubgitlab/lynn_illusions' into dev_refa…
Browse files Browse the repository at this point in the history
…ctor

Mainly auto-formatting, but also use utils.plot_stim
  • Loading branch information
JorisVincent committed Jun 14, 2022
2 parents 874a014 + 821263d commit f1c716a
Showing 1 changed file with 44 additions and 36 deletions.
80 changes: 44 additions & 36 deletions stimuli/illusions/cornsweet.py
Expand Up @@ -2,67 +2,75 @@


def cornsweet(
size=(10, 10),
ppd=10,
contrast=0.5,
ramp_width=2,
size=(10.0, 10.0),
ppd=10.0,
vmax=1.0,
vmin=0.0,
vtarget=0.5,
ramp_width=2.0,
exponent=2.75,
mean_lum=0.5,
):
# TODO: the parameters aren't analogous to the other stimuli
"""
Create a matrix containing a rectangular Cornsweet edge stimulus.
The 2D luminance profile of the stimulus is defined as
L = L_mean +/- (1 - X / w) ** a * L_mean * C/2 for the ramp and
L = L_mean for the area beyond the ramp.
Left side:
v = vtarget + (1 - X / w) ** a * (vmax-vtarget) for the ramp and v = vtarget beyond.
Right side:
v = vtarget - (1 - X / w) ** a * (vmin-vtarget) for the ramp and v = vtarget beyond.
X is the distance to the edge, w is the width of the ramp, a is a variable
determining the steepness of the ramp, and C is the contrast at the edge,
defined as C = (L_max-L_min) / L_mean.
determining the steepness of the ramp, vtarget is the luminance of the targets and
vmax/vmin are the max/min luminances.
Parameters
----------
size : tuple of 2 numbers
the size of the matrix in degrees of visual angle
ppd : number
the number of pixels in one degree of visual angle
contrast : float, in [0,1]
the contrast at the Cornsweet edge, defined as Michelson contrast
(max_luminance - min_luminance) / (max_luminance + min_luminance)
ramp_width : number (optional)
the width of the luminance ramp in degrees of visual angle.
Default is 3.
exponent : number (optional)
Determines the steepness of the ramp. Default is 2.75. An
exponent value of 0 leads to a stimulus with uniform flanks.
mean_lum : number
The mean luminance of the stimulus, i.e. the value outside of
the ramp area.
size in degrees of visual angle
ppd : float
number of pixels in one degree of visual angle
vmax : float
maximum luminance value
vmin : float
minimum luminance value
vtarget : float
luminance value of targets (=plateaus)
ramp_width : float
width of luminance ramp in degrees of visual angle
exponent : float
determines steepness of ramp (default is 2.75. 1 would be linear)
Returns
-------
Dictionary with img: ndarray (2D) and empty mask
Dictionary with img: ndarray (2D) and mask
References
----------
The formula and default values are taken from Boyaci, H., Fang, F., Murray,
The formula and default values are adapted from Boyaci, H., Fang, F., Murray,
S.O., Kersten, D. (2007). Responses to Lightness Variations in Early Human
Visual Cortex. Current Biology 17, 989-993.
"""

size = [int(size[0] * ppd), int(size[1] * ppd)]
img = np.ones(size) * mean_lum
ramp_width = int(ramp_width * ppd)
img = np.ones(size) * vtarget
mask = np.zeros(size)

# Create ramp profiles individually for left and right side
dist = np.arange(size[1] / 2.0)
dist = dist / (ramp_width * ppd)
dist = dist / ramp_width
dist[dist > 1.0] = 1.0
profile = (1.0 - dist) ** exponent * mean_lum * contrast
img[:, : int(np.ceil(size[1] / 2.0))] += profile[::-1]
img[:, size[1] // 2 :] -= profile
mask = None
profile1 = (1.0 - dist) ** exponent * (vmax - vtarget)
profile2 = (1.0 - dist) ** exponent * (vmin - vtarget)
img[:, : int(size[1] / 2.0)] += profile1[::-1]
img[:, size[1] // 2 :] += profile2

# Generate the target mask
mask[:, 0 : int(size[1] / 2.0 - ramp_width - 1)] = 1
mask[:, int(size[1] / 2.0 + ramp_width + 1) : :] = 2
return {"img": img, "mask": mask}


if __name__ == "__main__":
import matplotlib.pyplot as plt
from stimuli.utils import plot_stim

stim = cornsweet()
plt.imshow(stim, cmap="gray")
plt.show()
plot_stim(stim, mask=True)

0 comments on commit f1c716a

Please sign in to comment.