Skip to content

events

Anomaly and change-point detection for clock-offset logs.

Stability statistics assume stationarity; real logs contain events. This module locates and labels them, so they can be reviewed, excluded or explained before (or instead of) computing ADEV:

phase_step the offset jumps and stays (daemon step, reference switch, restart). spike an isolated outlier that returns to the previous level. frequency_change the offset slope (local frequency error) changes; binary segmentation of the local frequency with a standardised CUSUM statistic. delay_floor_change the minimum round-trip delay moves (route change). The offset shift at the same time is reported: a shift of about half the delay change means the new path is asymmetric in one direction. leap_smear a frequency plateau of about 11.6 ppm (1 s spread over 24 h) lasting 20-28 h, the signature of a smeared leap second upstream.

Phase steps and frequency changes are also marked path_changed when a delay-floor change happens nearby. An offset change without a path change points at the reference or the local clock (daemon behaviour, an upstream GNSS problem, spoofing), not the network.

All detectors are robust (MAD-scaled) and documented by their parameters; they return :class:Event objects and never modify the data.

phase_steps(s, k=8.0, window=5, trend_window=31)

Jumps of the offset larger than k robust sigmas of the sample-to-sample changes.

Changes are measured against a rolling median of the local slope, so a steady frequency error (or a leap smear) is not mistaken for steps.

frequency_changes(s, thresh=5.0, min_seg=16, min_change=1e-07)

Changes of the local frequency error (slope of the offset).

Binary segmentation on y = diff(offset) / diff(t) with a MAD-based sigma; changes smaller than min_change (fractional frequency, 0.1 ppm by default) are not reported. Phase steps are excluded from y first.

delay_floor_changes(s, block=16, thresh=5.0, min_blocks=3, min_change=None)

Steps of the minimum delay (route changes), from per-block minima.

leap_smears(freq_events, tolerance_ppm=1.5, min_hours=20.0, max_hours=28.0)

Pairs of opposite frequency changes of about 11.6 ppm, 20-28 h apart.

detect(s, step_k=8.0, freq_thresh=5.0, min_freq_change=1e-07, floor_block=16, path_window=None)

Run all detectors on one series; events sorted by time.

path_window (s) is how close a delay-floor change must be to a phase or frequency event to count as its cause (default: 2 floor blocks).