diff --git a/stimupy/noises/binaries.py b/stimupy/noises/binaries.py index cb12765a..0c757afd 100644 --- a/stimupy/noises/binaries.py +++ b/stimupy/noises/binaries.py @@ -47,9 +47,7 @@ def binary( binary_noise = np.random.randint(0, 2, size=shape) - 0.5 # Adjust intensity range: - binary_noise = adapt_intensity_range( - {"img": binary_noise}, intensity_range[0], intensity_range[1] - )["img"] + binary_noise = adapt_intensity_range(binary_noise, intensity_range[0], intensity_range[1]) stim = { "img": binary_noise, diff --git a/stimupy/noises/narrowbands.py b/stimupy/noises/narrowbands.py index 39646201..bbe9ad62 100644 --- a/stimupy/noises/narrowbands.py +++ b/stimupy/noises/narrowbands.py @@ -82,9 +82,7 @@ def narrowband( narrow_noise = np.real(narrow_noise) # Adjust intensity range: - narrow_noise = adapt_intensity_range( - {"img": narrow_noise}, intensity_range[0], intensity_range[1] - )["img"] + narrow_noise = adapt_intensity_range(narrow_noise, intensity_range[0], intensity_range[1]) stim = { "img": narrow_noise, diff --git a/stimupy/noises/naturals.py b/stimupy/noises/naturals.py index 6b76865e..c687415f 100644 --- a/stimupy/noises/naturals.py +++ b/stimupy/noises/naturals.py @@ -81,7 +81,7 @@ def one_over_f( noise = np.real(noise) # Adjust intensity range: - noise = adapt_intensity_range({"img": noise}, intensity_range[0], intensity_range[1])["img"] + noise = adapt_intensity_range(noise, intensity_range[0], intensity_range[1]) stim = { "img": noise, diff --git a/stimupy/noises/whites.py b/stimupy/noises/whites.py index 2a12090b..341090a1 100644 --- a/stimupy/noises/whites.py +++ b/stimupy/noises/whites.py @@ -58,9 +58,7 @@ def white( white_noise = np.random.rand(*shape) * 2.0 - 1.0 # Adjust intensity range: - white_noise = adapt_intensity_range( - {"img": white_noise}, intensity_range[0], intensity_range[1] - )["img"] + white_noise = adapt_intensity_range(white_noise, intensity_range[0], intensity_range[1]) stim = { "img": white_noise, diff --git a/stimupy/papers/bindmann2004.py b/stimupy/papers/bindmann2004.py index 57f18e4f..1446cfbd 100644 --- a/stimupy/papers/bindmann2004.py +++ b/stimupy/papers/bindmann2004.py @@ -31,7 +31,7 @@ import numpy as np from stimupy import illusions -from stimupy.utils.contrast_conversions import adapt_intensity_range +from stimupy.utils.contrast_conversions import adapt_intensity_range_dict from stimupy.utils.pad import pad_dict_by_visual_size __all__ = [ @@ -188,7 +188,7 @@ def bullseye_thin_gw45_gb31(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -249,7 +249,7 @@ def bullseye_thin_gw45_gb38(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -310,7 +310,7 @@ def bullseye_thin_gw45_gb45(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -371,7 +371,7 @@ def bullseye_thin_gw45_gb52(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -432,7 +432,7 @@ def bullseye_thin_gw45_gb59(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -493,7 +493,7 @@ def bullseye_thin_gw60_gb46(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -554,7 +554,7 @@ def bullseye_thin_gw60_gb53(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -615,7 +615,7 @@ def bullseye_thin_gw60_gb60(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -676,7 +676,7 @@ def bullseye_thin_gw60_gb67(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -737,7 +737,7 @@ def bullseye_thin_gw60_gb74(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -798,7 +798,7 @@ def bullseye_thin_gw75_gb61(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -859,7 +859,7 @@ def bullseye_thin_gw75_gb68(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -920,7 +920,7 @@ def bullseye_thin_gw75_gb75(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -981,7 +981,7 @@ def bullseye_thin_gw75_gb82(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -1042,7 +1042,7 @@ def bullseye_thin_gw75_gb89(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -1103,7 +1103,7 @@ def bullseye_thick_gw45_gb31(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -1164,7 +1164,7 @@ def bullseye_thick_gw45_gb38(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -1225,7 +1225,7 @@ def bullseye_thick_gw45_gb45(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -1286,7 +1286,7 @@ def bullseye_thick_gw45_gb52(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -1347,7 +1347,7 @@ def bullseye_thick_gw45_gb59(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -1408,7 +1408,7 @@ def bullseye_thick_gw60_gb46(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -1469,7 +1469,7 @@ def bullseye_thick_gw60_gb53(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -1530,7 +1530,7 @@ def bullseye_thick_gw60_gb60(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -1591,7 +1591,7 @@ def bullseye_thick_gw60_gb67(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -1652,7 +1652,7 @@ def bullseye_thick_gw60_gb74(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -1713,7 +1713,7 @@ def bullseye_thick_gw75_gb61(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -1774,7 +1774,7 @@ def bullseye_thick_gw75_gb68(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -1835,7 +1835,7 @@ def bullseye_thick_gw75_gb75(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -1896,7 +1896,7 @@ def bullseye_thick_gw75_gb82(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim @@ -1957,7 +1957,7 @@ def bullseye_thick_gw75_gb89(ppd=PPD): stim1["original_range"] = (INTENSITY_BLACK, INTENSITY_WHITE) # Adapt range between 0 and 1 - stim = adapt_intensity_range(stim1) + stim = adapt_intensity_range_dict(stim1) return stim diff --git a/stimupy/utils/contrast_conversions.py b/stimupy/utils/contrast_conversions.py index c600bf43..cf68c5e1 100644 --- a/stimupy/utils/contrast_conversions.py +++ b/stimupy/utils/contrast_conversions.py @@ -6,6 +6,10 @@ "adapt_rms_contrast", "adapt_normalized_rms_contrast", "adapt_intensity_range", + "adapt_michelson_contrast_dict", + "adapt_rms_contrast_dict", + "adapt_normalized_rms_contrast_dict", + "adapt_intensity_range_dict", ] def transparency(img, mask=None, alpha=0.5, tau=0.2): @@ -33,14 +37,119 @@ def transparency(img, mask=None, alpha=0.5, tau=0.2): return img -def adapt_michelson_contrast(stim, michelson_contrast, mean_luminance=None): +def adapt_michelson_contrast(img, michelson_contrast, mean_luminance=None): """ Adapt Michelson contrast of image + Parameters + ---------- + img : np.ndarray + stimulus array + michelson_contrast : float + desired Michelson contrast + mean_luminance : float + desired mean luminance; if None (default), dont change mean luminance + + Returns + ---------- + img : np.ndarray + image with adapted michelson contrast and mean luminance if passed + """ + if mean_luminance is None: + mean_luminance = img.mean() + + # Adapt Michelson contrast + img = (img - img.min()) / (img.max() - img.min()) + img = img * michelson_contrast * 2.0 * mean_luminance + img += mean_luminance - michelson_contrast * mean_luminance + return img + + +def adapt_rms_contrast(img, rms_contrast, mean_luminance=None): + """ + Adapt rms contrast of image (std) + + Parameters + ---------- + img : np.ndarray + stimulus array + rms_contrast : float + desired rms contrast (std divided by mean intensity) + mean_luminance : float + desired mean luminance; if None (default), dont change mean luminance + + Returns + ---------- + img : np.ndarray + image with adapted rms contrast and mean luminance if passed + """ + if mean_luminance is None: + mean_luminance = img.mean() + + # Adapt rms contrast + img = img - img.mean() + img = img / img.std() * rms_contrast + mean_luminance + return img + + +def adapt_normalized_rms_contrast(img, rms_contrast, mean_luminance=None): + """ + Adapt normalized rms contrast of image (std divided by mean) + + Parameters + ---------- + img : np.ndarray + stimulus array + rms_contrast : float + desired rms contrast (std divided by mean intensity) + mean_luminance : float + desired mean luminance; if None (default), dont change mean luminance + + Returns + ---------- + img : np.ndarray + image with adapted rms contrast and mean luminance if passed + """ + if mean_luminance is None: + mean_luminance = img.mean() + + img = img - img.mean() + img = img / img.std() * rms_contrast * mean_luminance + mean_luminance + return img + + +def adapt_intensity_range(img, intensity_min=0.0, intensity_max=1.0): + """ + Adapt intensity range of image + + Parameters + ---------- + img : np.ndarray + stimulus array + intensity_min : float + new minimal intensity value + intensity_max : float + new maximal intensity value + + Returns + ---------- + img : np.ndarray + image with adapted intensity range + """ + + img = (img - img.min()) / (img.max() - img.min()) + img = img * (intensity_max - intensity_min) + intensity_min + return img + + +def adapt_michelson_contrast_dict(stim, michelson_contrast, mean_luminance=None): + """ + Adapt Michelson contrast of image in dict + Parameters ---------- stim : dict - stimulus dictionary containing at least keys "img" and "mask" + stimulus dictionary containing at least key "img" michelson_contrast : float desired Michelson contrast mean_luminance : float @@ -54,13 +163,9 @@ def adapt_michelson_contrast(stim, michelson_contrast, mean_luminance=None): mean luminance ("mean_luminance") and additional keys containing stimulus parameters """ - if mean_luminance is None: - mean_luminance = stim["img"].mean() - # Adapt Michelson contrast - img = (stim["img"] - stim["img"].min()) / (stim["img"].max() - stim["img"].min()) - img = img * michelson_contrast * 2.0 * mean_luminance - img += mean_luminance - michelson_contrast * mean_luminance + # Adapt Michelson contrast of image + img = adapt_michelson_contrast(stim["img"], michelson_contrast, mean_luminance) stim["img"] = img stim["michelson_contrast"] = michelson_contrast @@ -68,14 +173,14 @@ def adapt_michelson_contrast(stim, michelson_contrast, mean_luminance=None): return stim -def adapt_rms_contrast(stim, rms_contrast, mean_luminance=None): +def adapt_rms_contrast_dict(stim, rms_contrast, mean_luminance=None): """ Adapt rms contrast of image (std) Parameters ---------- stim : dict - stimulus dictionary containing at least keys "img" and "mask" + stimulus dictionary containing at least key "img" rms_contrast : float desired rms contrast (std divided by mean intensity) mean_luminance : float @@ -89,11 +194,8 @@ def adapt_rms_contrast(stim, rms_contrast, mean_luminance=None): mean luminance ("mean_luminance") and additional keys containing stimulus parameters """ - if mean_luminance is None: - mean_luminance = stim["img"].mean() - - img = stim["img"] - stim["img"].mean() - img = img / img.std() * rms_contrast + mean_luminance + # Adapt rms_contrast of image + img = adapt_rms_contrast(stim["img"], rms_contrast, mean_luminance) stim["img"] = img stim["rms_contrast"] = rms_contrast @@ -101,14 +203,14 @@ def adapt_rms_contrast(stim, rms_contrast, mean_luminance=None): return stim -def adapt_normalized_rms_contrast(stim, rms_contrast, mean_luminance=None): +def adapt_normalized_rms_contrast_dict(stim, rms_contrast, mean_luminance=None): """ Adapt normalized rms contrast of image (std divided by mean) Parameters ---------- stim : dict - stimulus dictionary containing at least keys "img" + stimulus dictionary containing at least key "img" rms_contrast : float desired rms contrast (std divided by mean intensity) mean_luminance : float @@ -122,11 +224,9 @@ def adapt_normalized_rms_contrast(stim, rms_contrast, mean_luminance=None): mean luminance ("mean_luminance") and additional keys containing stimulus parameters """ - if mean_luminance is None: - mean_luminance = stim["img"].mean() - img = stim["img"] - stim["img"].mean() - img = img / img.std() * rms_contrast * mean_luminance + mean_luminance + # Adapt normalized rms contrast + img = adapt_normalized_rms_contrast(stim["img"], rms_contrast, mean_luminance) stim["img"] = img stim["rms_contrast"] = rms_contrast @@ -134,14 +234,14 @@ def adapt_normalized_rms_contrast(stim, rms_contrast, mean_luminance=None): return stim -def adapt_intensity_range(stim, intensity_min=0.0, intensity_max=1.0): +def adapt_intensity_range_dict(stim, intensity_min=0.0, intensity_max=1.0): """ Adapt intensity range of image Parameters ---------- stim : dict - stimulus dictionary containing at least keys "img" + stimulus dictionary containing at least key "img" intensity_min : float new minimal intensity value intensity_max : float @@ -155,8 +255,7 @@ def adapt_intensity_range(stim, intensity_min=0.0, intensity_max=1.0): and additional keys containing stimulus parameters """ - img = (stim["img"] - stim["img"].min()) / (stim["img"].max() - stim["img"].min()) - img = img * (intensity_max - intensity_min) + intensity_min + img = adapt_intensity_range(stim["img"], intensity_min, intensity_max) stim["img"] = img stim["intensity_range"] = (intensity_min, intensity_max)