SpeedyStatSplit
SpeedyStatSplit is a variance-based recursive segmentation algorithm
optimized in Cython. It finds boundaries where the signal’s statistical
properties change — making it ideal for resolving multi-level current
sub-states within already-detected events.
Note
SpeedyStatSplit is not an event detector. Use an event detector
(AutoSquareParser, SpikeParser, or lambda_event_parser) first
to find translocation events, then apply SpeedyStatSplit to segment
current levels within those events.
The algorithm recursively splits a signal at the point that maximizes the reduction in total variance, stopping when segments are too narrow or the gain is below a threshold.
Typical two-stage workflow:
from ionique.parsers import AutoSquareParser, SpeedyStatSplit
# Stage 1: detect blockade events
detector = AutoSquareParser(threshold_baseline=0.7, expected_conductance=1.9)
trace.parse(detector, newrank="event", at_child_rank="vstep")
# Stage 2: segment sub-states within each event
splitter = SpeedyStatSplit(
sampling_freq=100000,
min_width=100,
window_width=10000,
)
trace.parse(splitter, newrank="state", at_child_rank="event")
Parameters
Parameter |
Default |
Description |
|---|---|---|
|
(required) |
Sampling frequency in Hz. |
|
|
Minimum segment width in samples. Segments shorter than this will not be split further. Controls over-segmentation. |
|
|
Maximum segment width in samples. |
|
|
Sliding window width for split-point search. Larger values detect broader features; smaller values detect finer changes. |
|
|
Legacy threshold: minimum log-likelihood gain per sample to accept a
split. Set this or |
|
|
Expected false positive splits per second. Automatically calculates the gain threshold. |
|
|
Prior expected segment rate for Bayesian threshold calculation. |
|
|
Apply a lowpass filter at this frequency before splitting. |
Parameter sensitivity
min_width
Controls the minimum size of detected segments. Small values allow fine-grained splitting but risk over-segmentation on noise. Large values merge adjacent states.
# Fine-grained: resolve brief sub-states within events
parser = SpeedyStatSplit(sampling_freq=100000, min_width=50)
# Coarse: only detect major current-level changes
parser = SpeedyStatSplit(sampling_freq=100000, min_width=3000)
window_width
The window within which split candidates are evaluated. Affects the scale of detectable transitions.
Sensitivity tuning
The overall sensitivity depends on the interaction between min_width and
the gain threshold (set via false_positive_rate or
min_gain_per_sample).
# High sensitivity — resolve small, brief sub-states
splitter = SpeedyStatSplit(
sampling_freq=100000,
min_width=50,
false_positive_rate=10.0,
)
# Low sensitivity — only split on large, clear level changes
splitter = SpeedyStatSplit(
sampling_freq=100000,
min_width=1500,
false_positive_rate=0.01,
)
Full example
from ionique.parsers import AutoSquareParser, SpeedyStatSplit
# First detect events
detector = AutoSquareParser(threshold_baseline=0.7, expected_conductance=1.9)
trace.parse(detector, newrank="event", at_child_rank="vstep")
# Then segment sub-states within each event
splitter = SpeedyStatSplit(
sampling_freq=100000,
min_width=200,
window_width=10000,
)
trace.parse(splitter, newrank="state", at_child_rank="event")
states = trace.traverse_to_rank("state")
print(f"Resolved {len(states)} sub-states across all events")
for st in states[:5]:
print(f" [{st.start}:{st.end}] mean={st.mean:.3f}, std={st.std:.4f}")
Additional methods
SpeedyStatSplit exposes lower-level methods through its Cython backend:
# Get MetaSegment objects directly (more memory-efficient)
segments = parser.parse_meta(current_array)
# Find the single best split point
best_index = parser.best_single_split(current_array)
Tip
SpeedyStatSplit works best on segments that already contain a single blockade event with multi-level structure. Running it directly on a full voltage step will segment the entire signal (baseline + events together), which is usually not what you want. Detect events first, then split within them.