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"