mne_rt.protocols.UpDownStaircaseProtocol#

class mne_rt.protocols.UpDownStaircaseProtocol(initial_threshold: float, direction: str = 'up', n_up: int = 1, n_down: int = 2, step_size: float = 0.05, step_factor: float = 0.5, n_reversals_before_halving: int = 4, min_step: float = 0.0001, smoothing: float = 0.0, max_reversals: int | None = None)#

Bases: object

Up-down adaptive staircase threshold protocol.

Adjusts the reward threshold after each window based on consecutive success/failure runs, converging the difficulty to a target performance level determined by the ratio n_up/n_down.

Parameters:
initial_thresholdfloat

Starting threshold.

direction{“up”, “down”}, default “up”

“up” → reward when value > threshold; “down” → reward when value < threshold.

n_upint, default 1

Consecutive successes needed to increase difficulty (tighten threshold).

n_downint, default 2

Consecutive failures needed to decrease difficulty (loosen threshold). The rule (n_up=1, n_down=2) converges to approximately 70.7 % success rate (Levitt, 1971).

step_sizefloat, default 0.05

Initial threshold step size per reversal.

step_factorfloat, default 0.5

Multiplicative factor applied to step_size after n_reversals_before_halving reversals (standard Levitt procedure to zoom in on the threshold).

n_reversals_before_halvingint, default 4

Number of reversals before step_size is multiplied by step_factor.

min_stepfloat, default 1e-4

Floor for step_size to prevent it collapsing to zero.

smoothingfloat, default 0.0

EMA smoothing coefficient for the input value before thresholding. Must be in [0, 1).

max_reversalsint | None, default None

If set, stop adapting after this many reversals (threshold freezes at its current value).

Attributes:
thresholdfloat

Current threshold.

n_reversalsint

Number of reversals so far.

reversal_thresholdslist[float]

Threshold value recorded at each reversal point.

Raises:
ValueError

If any parameter is outside its valid range.

Examples

1-up/2-down staircase targeting ~70.7 % success rate:

from mne_rt.protocols.staircase import UpDownStaircaseProtocol

proto = UpDownStaircaseProtocol(
    initial_threshold=0.5,
    direction="up",
    n_up=1,
    n_down=2,
    step_size=0.05,
)
for value in nf_stream:
    crossed, magnitude = proto.evaluate(value)

Added in version 1.0.0.

__init__(initial_threshold: float, direction: str = 'up', n_up: int = 1, n_down: int = 2, step_size: float = 0.05, step_factor: float = 0.5, n_reversals_before_halving: int = 4, min_step: float = 0.0001, smoothing: float = 0.0, max_reversals: int | None = None) None[source]#

Methods

__init__(initial_threshold[, direction, ...])

evaluate(value)

Evaluate one NF value and update the staircase.

reset()

Reset all state to initial conditions.

evaluate(value: float) tuple[bool, float][source]#

Evaluate one NF value and update the staircase.

Applies EMA smoothing, compares against the current threshold, updates consecutive-run counters, and adjusts the threshold when an up or down rule is triggered. A reversal is recorded whenever the direction of threshold change flips.

Parameters:
valuefloat

Current NF feature value.

Returns:
crossedbool

True if the threshold was crossed in the target direction.

magnitudefloat

Distance from the threshold (absolute difference) when crossed is True; 0.0 otherwise.

reset() None[source]#

Reset all state to initial conditions.

Restores the threshold to initial_threshold, clears reversal history, and resets all counters. The step_size is restored to its value from construction (stored as _initial_step_size).