Skip to content

ntpstats.simulate

Synthetic clocks and NTP exchanges with known ground truth.

Use these to validate estimators and synchronisation algorithms: every simulated measurement comes with the true offset, so filters can be scored objectively (see :func:ntpstats.analysis.compare).

Power-law noise is generated with the Kasdin & Walter (1992) fractional integration method, the approach commonly used by frequency-stability software.

ClockModel dataclass

Free-running local oscillator.

freq_offset (s/s), drift (s/s per s), and power-law noise magnitudes expressed as the ADEV they produce at tau = 1 s (flicker FM: its constant ADEV floor; flicker PM: phase rms). An optional sinusoidal temperature cycle drives frequency through tempco (fractional frequency per kelvin), the dominant wander of real crystal oscillators.

phase(t, rng=None)

Local clock error (local - true) at uniform times t.

PathEvent dataclass

A change of path behaviour between start and end (seconds from the beginning of the run): route change (base_delta, a step of the one-way propagation delay), congestion (queue_scale/load), or outage (loss=1).

PathModel dataclass

One-way network path: fixed propagation plus random queueing.

Queueing delay is exponential with mean queue_mean applied with probability load (else zero), which yields the characteristic "floor plus tail" delay distribution of real networks. events modify it over time.

loss_mask(rel, rng)

True where a packet on this path is lost because of an event.

ServerSpec dataclass

A time server as seen through its own network path.

bias makes it a falseticker (constant error of its clock); step_at / step add a time step of its clock at a given run time.

powerlaw_phase(n, alpha, sigma=1.0, rng=None)

Phase samples whose fractional-frequency PSD is ~ f^alpha.

sigma scales the driving white noise. For alpha=2 the result is white phase noise with standard deviation sigma; for alpha=0 (white FM) it is a random walk with step sigma.

simulate_ntp(sc=None, name='simulated')

Simulate SNTP exchanges against a perfect server.

Returns (measured, truth) time series. measured uses the ntpd sign convention (server - local) and has delay and true_offset columns; truth is the true offset at the same times. For multi-server scenarios this returns the first server; see :func:simulate_multi.

simulate_multi(sc, name='simulated')

One local clock measured against every server in sc.servers.

Returns (list_of_measured, truth); truth is the true offset on a fine common grid (poll / 4) so any estimator output can be scored.

noise_series(n=4096, tau0=1.0, alpha=0, sigma=1e-09, seed=None)

A pure power-law phase series (for estimator validation / teaching).

scenario_from_dict(d, base_dir='.')

Build a :class:Scenario from a plain dict (e.g. a TOML scenario file).

name = "wan-route-change"
duration = 86400
poll = 64
seed = 1
[clock]
freq_offset = 5e-6
tempco = 1e-7
temp_amplitude = 3
[forward]
base = 5e-3
events = [{start = 28800, base_delta = 4e-3}]
[backward]
base = 5e-3
queue_mean = 3e-3
[[servers]]            # optional: multi-server
name = "a"
bias = 0.0
forward = {base = 4e-3}
[trace]                # optional: real delays from a capture or log (replaces forward/backward)
file = "capture.pcap"  # relative to the scenario file
mode = "bootstrap"     # or "replay"