Skip to content

Utilities Module

utilities

residual_fun(abs_dist, motor_noise, lr_noise)

Computes updating noise (residuals) as a combination of two noise components.

The noise variable is returned in terms of von-Mises concentration, which is a measure of precision, where variance = 1/concentration.

Parameters:

Name Type Description Default
abs_dist ndarray

Absolute distance in radians (predicted update or prediction error).

required
motor_noise ndarray

Motor-noise parameter (imprecise motor control).

required
lr_noise ndarray

Learning-rate-noise parameter (more noise for larger updates).

required

Returns:

Type Description
ndarray

Updating noise expressed as von Mises concentration.

Source code in rbmpy/utilities.py
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
def residual_fun(
    abs_dist: np.ndarray, motor_noise: float, lr_noise: float
) -> np.ndarray:
    """Computes updating noise (residuals) as a combination of two noise components.

    The noise variable is returned in terms of von-Mises concentration,
    which is a measure of precision, where variance = 1/concentration.

    Parameters
    ----------
    abs_dist : np.ndarray
        Absolute distance in radians (predicted update or prediction error).
    motor_noise : np.ndarray
        Motor-noise parameter (imprecise motor control).
    lr_noise : np.ndarray
        Learning-rate-noise parameter (more noise for larger updates).

    Returns
    -------
    np.ndarray
        Updating noise expressed as von Mises concentration.
    """

    # Check that abs_dist is positive
    if np.any(abs_dist < 0):
        raise ValueError("abs_dist must be positive (non-negative values only)")

    # Compute updating noise expressed as variance
    # (1) motor noise is updating variance due to imprecise motor control and
    # (2) learning-rate noise models more noise for larger updates
    up_noise = motor_noise + lr_noise * (np.rad2deg(abs_dist))

    # Convert std of update distribution to radians and kappa
    up_noise_radians = np.deg2rad(up_noise)
    up_var_radians = up_noise_radians**2
    kappa_up = 1 / up_var_radians

    return kappa_up

compute_persprob(intercept, slope, abs_pred_up)

Computes perseveration probability.

Parameters:

Name Type Description Default
intercept float

Logistic function intercept.

required
slope float

Logistic function slope.

required
abs_pred_up ndarray

Absolute predicted update or prediction error.

required

Returns:

Type Description
ndarray

Computed perseveration probability.

Source code in rbmpy/utilities.py
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
def compute_persprob(
    intercept: float, slope: float, abs_pred_up: np.ndarray
) -> np.ndarray:
    """Computes perseveration probability.

    Parameters
    ----------
    intercept : float
        Logistic function intercept.
    slope : float
        Logistic function slope.
    abs_pred_up : np.ndarray
        Absolute predicted update or prediction error.

    Returns
    -------
    np.ndarray
        Computed perseveration probability.
    """

    # expit(x) = 1/(1+exp(-x)), i.e., (1/(1+exp(-slope*(abs_pred_up-int))))
    return expit(slope * (abs_pred_up - intercept))

get_sel_coeffs(items, fixed_coeffs, coeffs)

Extracts the model coefficients.

Parameters:

Name Type Description Default
items ItemsView[str, bool]

Free parameters, specified based on which_vars dict.

required
fixed_coeffs dict

Dictionary of fixed coefficients.

required
coeffs ndarray

Dictionary of free model coefficients.

required

Returns:

Type Description
dict

Dictionary of selected model coefficients.

Source code in rbmpy/utilities.py
 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
def get_sel_coeffs(items: ItemsView[str, bool], fixed_coeffs: dict, coeffs) -> dict:
    """Extracts the model coefficients.

    Parameters
    ----------
    items : ItemsView[str, bool]
        Free parameters, specified based on which_vars dict.
    fixed_coeffs : dict
        Dictionary of fixed coefficients.
    coeffs : np.ndarray
        Dictionary of free model coefficients.

    Returns
    -------
    dict
        Dictionary of selected model coefficients.
    """

    # Initialize coefficient dictionary and counters
    sel_coeffs = dict()  # initialize list with regressor names
    i = 0  # initialize counter

    # Put selected coefficients in list that is used for the regression
    for key, value in items:
        if value:
            sel_coeffs[key] = coeffs[i]
            i += 1
        else:
            sel_coeffs[key] = fixed_coeffs[key]

    return sel_coeffs

parameter_summary(parameters, param_labels, grid_size, axis_labels=None)

Creates a simple plot showing parameter values.

Parameters:

Name Type Description Default
parameters DataFrame

All parameters.

required
param_labels list

Labels for the plot.

required
grid_size tuple

Grid size for subplots (rows, cols).

required
axis_labels str

Y-axis labels.

None

Returns:

Type Description
None

This function does not return any value.

Source code in rbmpy/utilities.py
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
def parameter_summary(
    parameters: pd.DataFrame,
    param_labels: list,
    grid_size: tuple,
    axis_labels: str = None,
) -> None:
    """Creates a simple plot showing parameter values.

    Parameters
    ----------
    parameters : pd.DataFrame
        All parameters.
    param_labels : list
        Labels for the plot.
    grid_size : tuple
        Grid size for subplots (rows, cols).
    axis_labels : str
        Y-axis labels.

    Returns
    -------
    None
        This function does not return any value.
    """

    # Figure size
    fig_width = 15
    fig_height = 10

    # Create figure
    plt.figure(figsize=cm2inch(fig_width, fig_height))

    # Cycle over parameters
    for i, label in enumerate(param_labels):

        # Create subplot
        plt.subplot(grid_size[0], grid_size[1], i + 1)

        ax = plt.gca()
        sns.boxplot(
            y=label,
            data=parameters,
            notch=False,
            showfliers=False,
            linewidth=0.8,
            width=0.15,
            boxprops=dict(alpha=1),
            ax=ax,
            showcaps=False,
        )
        sns.swarmplot(y=label, data=parameters, color="gray", alpha=0.7, size=3, ax=ax)

        ttest_result = stats.ttest_1samp(parameters[label], 0)
        if axis_labels is None:
            plt.ylabel(f"{label}")
        else:
            label = axis_labels[i]
            plt.ylabel(f"{label}")
        plt.title("p = " + str(np.round(ttest_result.pvalue, 3)))
        sns.despine()

    # Adjust layout and show plot
    plt.tight_layout()

circ_dist(x, y)

Compute the pairwise signed circular distance between angles x and y.

The distance is the signed shortest distance on the circle between each pair of angles, returned in the range (-π, π].

Parameters:

Name Type Description Default
x array_like

Sample of linear random variables (in radians).

required
y array_like or float

Sample of linear random variables (in radians), or a single constant angle.

required

Returns:

Name Type Description
r ndarray

Matrix or array of pairwise signed circular differences.

Notes

This is a direct translation of the MATLAB function circ_dist from the Circular Statistics Toolbox for MATLAB (Berens, 2009). Reference: Berens, P. (2009). "CircStat: A MATLAB Toolbox for Circular Statistics."

See Also

numpy.angle, numpy.exp

Examples:

>>> circ_dist(np.pi/4, np.pi/2)
-0.7853981633974483
Source code in rbmpy/utilities.py
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
def circ_dist(x, y):
    """Compute the pairwise signed circular distance between angles x and y.

    The distance is the signed shortest distance on the circle between each pair of angles,
    returned in the range (-π, π].

    Parameters
    ----------
    x : array_like
        Sample of linear random variables (in radians).
    y : array_like or float
        Sample of linear random variables (in radians), or a single constant angle.

    Returns
    -------
    r : ndarray
        Matrix or array of pairwise signed circular differences.

    Notes
    -----
    This is a direct translation of the MATLAB function `circ_dist` from
    the Circular Statistics Toolbox for MATLAB (Berens, 2009).
    Reference: Berens, P. (2009). "CircStat: A MATLAB Toolbox for Circular Statistics."

    See Also
    --------
    numpy.angle, numpy.exp

    Examples
    --------
    >>> circ_dist(np.pi/4, np.pi/2)
    -0.7853981633974483
    """

    x = np.asarray(x)
    y = np.asarray(y)

    if x.shape != y.shape and y.size != 1:
        raise ValueError("Input dimensions do not match.")

    r = np.angle(np.exp(1j * x) / np.exp(1j * y))
    return r

compute_bic(llh, n_params, n_trials)

Computes the Bayesian information criterion (BIC).

See Stephan et al. (2009). Bayesian model selection for group studies. NeuroImage.

Parameters:

Name Type Description Default
llh float

Negative log-likelihood.

required
n_params int

Number of free parameters.

required
n_trials int

Number of trials.

required

Returns:

Type Description
float

Computed BIC.

Source code in rbmpy/utilities.py
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
def compute_bic(llh: float, n_params: int, n_trials: int) -> float:
    """Computes the Bayesian information criterion (BIC).

    See Stephan et al. (2009). Bayesian model selection for group studies. NeuroImage.

    Parameters
    ----------
    llh : float
        Negative log-likelihood.
    n_params : int
        Number of free parameters.
    n_trials : int
        Number of trials.

    Returns
    -------
    float
        Computed BIC.
    """

    return (-1 * llh) - (n_params / 2) * np.log(n_trials)

normalize_angle(angle_rad)

Normalizes circular angles (in radians).

Parameters:

Name Type Description Default
angle_rad ndarray

Raw values in radians.

required

Returns:

Type Description
ndarray

Normalized values in radians.

Source code in rbmpy/utilities.py
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
def normalize_angle(angle_rad: np.ndarray) -> np.ndarray:
    """Normalizes circular angles (in radians).

    Parameters
    ----------
    angle_rad : np.ndarray
        Raw values in radians.

    Returns
    -------
    np.ndarray
        Normalized values in radians.
    """

    # Translate to degrees
    angle_deg = np.rad2deg(angle_rad)

    # Ensure the angle is within the range -180 to 180 degrees
    # futuretodo: do everything in radians
    corr_angle = (angle_deg + 180) % 360 - 180

    return np.deg2rad(corr_angle)