blinklinmult.train.phases¶
Derive blink phase and event shape from a predicted eye-state signal.
The model emits one continuous value per frame. That value alone is ambiguous – 0.5 could be an eye halfway shut or halfway open – but its trajectory is not: falling means closing, rising means opening, flat-and-low means closed. This module reads phase off the signal’s derivative rather than off the annotation’s geometry, which matters because no corpus annotates phase and inventing it from interval position would assert a closure shape rather than measure one.
The same trajectory separates event kinds. A complete blink descends, holds briefly, and ascends; an incomplete one reverses before it bottoms out; a double blink shows two minima inside one elevated span – which no single-threshold extractor can split, because thresholding sees one run either way.
These categories are derived, not annotated. They are measurements of the predicted signal and carry no ground truth, so they belong in analysis and in downstream state estimation, never in a benchmark column.
Attributes¶
the eye is open and not moving. |
|
the lid is descending. |
|
the lid is down and still. |
|
the lid is rising. |
|
Human-readable phase names, for reports and plots. |
|
Per-frame change below which the lid counts as still. |
|
Signal value above which a still frame is closed rather than open. |
Exceptions¶
Raised when a signal cannot be analysed. |
Functions¶
|
Moving average, for a derivative that is not dominated by noise. |
|
Label every frame open, closing, closed, or opening. |
|
Measure the shape of one predicted event. |
|
Name an event from its measured shape. |
Module Contents¶
- blinklinmult.train.phases.OPEN = 0¶
the eye is open and not moving.
- Type:
Phase
- blinklinmult.train.phases.CLOSING = 1¶
the lid is descending.
- Type:
Phase
- blinklinmult.train.phases.CLOSED = 2¶
the lid is down and still.
- Type:
Phase
- blinklinmult.train.phases.OPENING = 3¶
the lid is rising.
- Type:
Phase
- blinklinmult.train.phases.PHASE_NAMES: dict[int, str]¶
Human-readable phase names, for reports and plots.
- blinklinmult.train.phases.MOTION_EPSILON = 0.02¶
Per-frame change below which the lid counts as still.
Separates a plateau from a ramp. Small enough that a genuine closure – which moves through most of its range in three or four frames – is never called still, large enough that prediction noise on an open eye is not called motion.
- blinklinmult.train.phases.CLOSED_LEVEL = 0.5¶
Signal value above which a still frame is closed rather than open.
- exception blinklinmult.train.phases.PhaseError[source]¶
Bases:
ValueErrorRaised when a signal cannot be analysed.
Initialize self. See help(type(self)) for accurate signature.
- blinklinmult.train.phases.smooth(signal: numpy.ndarray, window: int = 3) numpy.ndarray[source]¶
Moving average, for a derivative that is not dominated by noise.
- Parameters:
signal (np.ndarray) –
(T,)per-frame values.window (int) – Frames to average over;
1disables smoothing.
- Returns:
(T,)smoothed, same length as the input.- Return type:
np.ndarray
- Raises:
PhaseError – If the window is not a positive odd integer.
- blinklinmult.train.phases.phases(signal: numpy.ndarray, window: int = 3, motion_epsilon: float = MOTION_EPSILON, closed_level: float = CLOSED_LEVEL) numpy.ndarray[source]¶
Label every frame open, closing, closed, or opening.
Phase comes from the sign of the smoothed derivative, with the value used only to tell a still-and-low frame from a still-and-high one. That ordering is deliberate: the value is ambiguous mid-blink and the direction is not.
- Parameters:
signal (np.ndarray) –
(T,)predicted eye-state values, higher meaning more closed.window (int) – Smoothing window before differentiating.
motion_epsilon (float) – Per-frame change below which the lid is still.
closed_level (float) – Value above which a still frame is closed.
- Returns:
- Return type:
np.ndarray
- blinklinmult.train.phases.describe_event(signal: numpy.ndarray, start: int, stop: int) dict[str, float][source]¶
Measure the shape of one predicted event.
What distinguishes a complete blink from an incomplete or a double one is the curve, not the extent: peak depth says whether the lid ever really shut, the minima count says whether it shut twice, and the asymmetry says whether it reopened as fast as it closed (real blinks close faster than they open).
- Parameters:
signal (np.ndarray) –
(T,)values for the whole recording.start (int) – First frame of the event, inclusive.
stop (int) – Last frame, inclusive.
- Returns:
frames,peak,mean,n_peaks,rise_frames,fall_frames, andasymmetry– the fall minus the rise, in frames, positive when reopening takes longer.- Return type:
dict[str, float]
- Raises:
PhaseError – If the span is empty or outside the signal.
- blinklinmult.train.phases.classify_event(shape: dict[str, float], complete_peak: float = 0.7, min_frames: float = 2.0) str[source]¶
Name an event from its measured shape.
- Parameters:
shape (dict[str, float]) – As
describe_event()returns.complete_peak (float) – Peak below which the lid never fully shut.
min_frames (float) – Spans shorter than this are too brief to judge.
- Returns:
"double","incomplete","long","brief", or"complete". Derived from the prediction, never from an annotation.- Return type:
str