-
Notifications
You must be signed in to change notification settings - Fork 0
Writing a Plugin
github-actions[bot] edited this page Oct 1, 2026
·
1 revision
Add support for your instrument, daemon or algorithm without forking ntpstats. Ship it as a small Python package that declares entry points. Once it is installed, ntpstats finds it:
| Entry-point group | Object | Appears in |
|---|---|---|
ntpstats.parsers |
ntpstats.plugins.ParserPlugin |
-f/--format, auto-detection, the UI's format list |
ntpstats.estimators |
an ntpstats.estimators.Estimator (class or instance) |
ntpstats bench |
ntpstats.detectors |
ntpstats.plugins.DetectorPlugin |
ntpstats events, the UI's event list, audit --events
|
ntpstats.masks |
mask text (tau,tdev CSV), a Mask, or a callable returning one |
--mask NAME |
ntpstats.profiles |
a dict with the keys of a TOML import profile | -f profile:NAME |
ntpstats plugins # what is installed; exit code 1 if a plugin failed to load
ntpstats plugins --all # including the built-ins# my_pkg/__init__.py
import numpy as np
from ntpstats.plugins import ParserPlugin
from ntpstats.series import TimeSeries
def detect(lines): # confidence 0..1 from the first lines
return 1.0 if lines and lines[0].startswith("#TOYCSV") else 0.0
def parse(lines, name):
rows = [ln.split(";") for ln in lines[1:] if ln.strip()]
t = np.array([int(ms) / 1000 for ms, _ in rows])
x = np.array([-float(us) * 1e-6 for _, us in rows]) # local - reference -> reference - local
return [TimeSeries(t, x, name=name, source_format="toycsv")]
PARSER = ParserPlugin("toycsv", parse, detect, "Toy CSV dialect", example="#TOYCSV 1\n1790000000000;12.5\n...")# pyproject.toml
[project.entry-points."ntpstats.parsers"]
toycsv = "my_pkg:PARSER"Rules:
-
Conventions. Times are POSIX seconds (UTC). Offsets are reference − local, in seconds.
Extra per-sample columns go in
extra. -
Detection.
detectscores 0.9 or more only when sure; a plugin that is sure wins over the built-in detection. From 0.5 it is tried before the generic CSV fallback. It must never claim other formats with certainty. - Built-in names. A plugin cannot replace a built-in format name.
-
Failures. A plugin that raises while loading is listed by
ntpstats pluginswith its error and otherwise ignored.
The built-in research formats (CGGTTS, Circular T, RIPE Atlas, …) are registered as
ParserPlugins too, so the API is used in-house.
pip install -e . # your plugin
pytest --pyargs ntpstats.testing.plugin_contract # ntpstats' checks for every installed plugin
NTPSTATS_PLUGIN=toycsv pytest --pyargs ntpstats.testing.plugin_contract # only oneThe suite checks the following:
- the example parses into sorted, finite series;
- detection recognises the example and does not claim unrelated formats;
-
load()and auto-detection work; - detectors return
Events; - masks and profiles validate.
Add it to your plugin's CI.
examples/plugins/ntpstats-toy-csv
is a complete plugin with a parser, a detector, a mask and a profile. ntpstats' own CI installs
it and runs the contract suite. Copy it, rename the package and replace the functions. Then share
it, and open an issue so it can be listed here.
ntpstats
- Home
- Getting started
- CLI reference
- In your browser
- Input formats
- Statistics
- Network & estimators
- Trace replay & PTP chains
- PTP & time error
- Sources & bounds
- Audit, events & CI
- Monitoring
- Protocols
- Metrology
- Research data
- Dataframes & Parquet
- Writing a plugin
- Notebooks & gallery
- Validation
- API reference
- Live interop
- State of the art
- Tools landscape
- Changelog
- Roadmap