Skip to content

autora.experiment_runner.synthetic.psychophysics.stevens_power_law

stevens_power_law(name="Stevens' Power Law", resolution=100, proportionality_constant=1.0, modality_constant=0.8, maximum_stimulus_intensity=5.0)

Stevens' Power Law

Parameters:

Name Type Description Default
name

name of the experiment

"Stevens' Power Law"
resolution

number of allowed values for stimulus

100
modality_constant

power constant

0.8
proportionality_constant

constant multiplier

1.0
maximum_stimulus_intensity

maximum value for stimulus

5.0
Source code in autora/experiment_runner/synthetic/psychophysics/stevens_power_law.py
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
def stevens_power_law(
    name="Stevens' Power Law",
    resolution=100,
    proportionality_constant=1.0,
    modality_constant=0.8,
    maximum_stimulus_intensity=5.0,
):
    """
    Stevens' Power Law

    Args:
        name: name of the experiment
        resolution: number of allowed values for stimulus
        modality_constant: power constant
        proportionality_constant: constant multiplier
        maximum_stimulus_intensity: maximum value for stimulus
    """

    params = dict(
        name=name,
        resolution=resolution,
        proportionality_constant=proportionality_constant,
        modality_constant=modality_constant,
        maximum_stimulus_intensity=maximum_stimulus_intensity,
    )

    iv1 = IV(
        name="S",
        allowed_values=np.linspace(
            1 / resolution, maximum_stimulus_intensity, resolution
        ),
        value_range=(1 / resolution, maximum_stimulus_intensity),
        units="intensity",
        variable_label="Stimulus Intensity",
        type=ValueType.REAL,
    )

    dv1 = DV(
        name="perceived_intensity",
        value_range=(0, maximum_stimulus_intensity),
        units="sensation",
        variable_label="Perceived Intensity",
        type=ValueType.REAL,
    )

    variables = VariableCollection(
        independent_variables=[iv1],
        dependent_variables=[dv1],
    )

    def run(
        conditions: Union[pd.DataFrame, np.ndarray, np.recarray],
        added_noise: float = 0.01,
        random_state: Optional[int] = None,
    ):
        rng = np.random.default_rng(random_state)
        X = np.array(conditions)
        Y = np.zeros((X.shape[0], 1))
        for idx, x in enumerate(X):
            y = proportionality_constant * x[
                0
            ] ** modality_constant + rng.random.normal(0, added_noise)
            Y[idx] = y

        return Y

    ground_truth = partial(run, added_noise=0.0)

    def domain():
        s_values = variables.independent_variables[0].allowed_values

        X = np.array(np.meshgrid(s_values)).T.reshape(-1, 1)
        return X

    def plotter(
        model=None,
    ):
        import matplotlib.colors as mcolors
        import matplotlib.pyplot as plt

        colors = mcolors.TABLEAU_COLORS
        col_keys = list(colors.keys())
        X = domain()
        y = ground_truth(X)
        plt.plot(X, y, label="Original", c=colors[col_keys[0]])
        if model is not None:
            y = model.predict(X)
            plt.plot(X, y, label="Recovered", c=colors[col_keys[0]], linestyle="--")
        x_limit = [0, variables.independent_variables[0].value_range[1]]
        y_limit = [0, 4]
        x_label = "Stimulus Intensity"
        y_label = "Perceived Stimulus Intensity"

        plt.xlim(x_limit)
        plt.ylim(y_limit)
        plt.xlabel(x_label, fontsize="large")
        plt.ylabel(y_label, fontsize="large")
        plt.legend(loc=2, fontsize="medium")
        plt.title("Stevens' Power Law", fontsize="x-large")
        plt.show()

    collection = SyntheticExperimentCollection(
        name=name,
        description=stevens_power_law.__doc__,
        variables=variables,
        run=run,
        ground_truth=ground_truth,
        domain=domain,
        plotter=plotter,
        params=params,
        factory_function=stevens_power_law,
    )
    return collection