Formáty záznamů hodin
src/clock_log.rs čte změřený záznam hodin do jedné normalizované fázové řady: rovnoměrné mřížky vzorků (time_s, phase_s), s uvedeným nebo zjištěným intervalem vzorků tau0, se započítanou každou mezerou a s pojmenovanými jednotkami záznamu. Čte se osm formátů, každý jako zdokumentovaná podmnožina. Cokoli mimo podmnožinu se odmítne chybou, která uvádí, co bylo nalezeno, místo aby se to četlo přibližně.
Zkratky. RINEX je Receiver Independent Exchange Format. TICC je čítač časových intervalů TAPR (Tucson Amateur Packet Radio). ADEV je překrývající se Allanova odchylka, TDEV časová odchylka a MTIE maximální chyba časového intervalu. tau0 je interval vzorků v sekundách.
Kde lze záznam použít#
telecom-timing:[series.clock_log]místoseries.samplesneboseries.csv_path. Fáze záznamu v ns je řada časové chyby kontrolovaná proti maskám a zpráva získává blokclock_log, který říká, jak byl záznam přečten.- Druh clock: tabulka
[clock_log]přidává k běhu blokmeasured: jak byl záznam přečten, SHA-256 tabulky (input_sha256;scenario_hashběhu tabulku nepokrývá) a fázových vzorků a překrývající se ADEV, TDEV a MTIE při oktávových faktorech průměrování. Vyžadujeruns = 1. Simulovaný holdover se nemění.
Bez tabulky se oba druhy zpracovávají, hashují a uvádějí přesně jako dříve.
[clock_log] # or [series.clock_log] in a telecom-timing scenario
format = "ticc" # "rinex-clk", "timelab", "ticc", "ptp4l", "phc2sys", "ts2phc",
# "chrony-tracking" or "chrony-statistics"
path = "logs/ticc.txt" # or text = "..." inline (the only choice in WebAssembly)
channel = "chA" # TICC: needed when the log holds more than one channel
gaps = "linear" # "refuse" (default), "longest" or "linear"
# clock = "G08" # RINEX, linuxptp, chrony: needed when the log holds more than one clock or source
# tau0_s = 1.0 # overrides a header and the detected spacing
# units = "ns" # TimeLab phase units: s (default), ms, us, ns, ps
# data = "phase" # TimeLab: phase (default) or frequency
Formáty#
rinex-clk: soubory hodin RINEX, verze 2,00 a 3,00 až 3,04 (včetně devítiznakového pole jména ve verzi 3,04). Záznam RINEX VERSION / TYPE se kontroluje a každá jiná verze je odmítnuta s uvedením nalezené verze: IGS zveřejňuje formát hodin (rinex_clock300.txt, 302, 304) až do 3,04 a dokumenty RINEX 4,00, 4,01 a 4,02 definují jen soubory pozorování, navigace a meteorologické, takže verze 4,00 souboru hodin ke čtení neexistuje. Hlavička se čte jen kvůli TIME SYSTEM ID a přeskakuje se až po END OF HEADER. Z datových záznamů se ponechávají jen záznamy AS (družice) a AR (přijímač nebo stanice) jedněch hodin vybraných podle jména. Jejich první hodnotové pole, předpětí hodin v sekundách, je fáze. Pokračovací řádky a záznamy CR, DR a MS se přeskakují. Epochy jsou kalendářní pole záznamu, jako sekundy od 1980-01-06 00:00:00 ve vlastní časové soustavě souboru, bez převodu.
timelab: ASCII záznamy fáze nebo frekvence ve stylu TimeLab, prostá textová forma, kterou TimeLab exportuje a kterou čtou jeho import ASCII a Stable32. Na řádku je jedno čtení: buď jediný sloupec s rovnoměrným tau0, nebo dva sloupce time value. Sloupce mohou být odděleny mezerami, čárkami nebo středníky.
- Řádky začínající
#,;nebo%jsou komentáře. Komentář ve tvarukey = value(nebokey: value) nastavujetau0(s),units(s,ms,us,nsnebops, pro fázi),data(phasenebofrequency) nebotime_units(snebomjd, pro první ze dvou sloupců). - Jeden úvodní nečíselný řádek se bere jako záhlaví sloupců.
- Frekvenční data (relativní frekvence) se přijímají pouze jako jediný sloupec. Integrují se na fázi jako
x[i+1] = x[i] + y[i]·tau0(NIST SP 1065, 2008, §4,1). - Binární soubory TimeLab a projektové soubory
.timse nečtou.
ticc: záznamy čítače TAPR TICC (TICC Operation Manual, revize z 23. listopadu 2016 a 15. prosince 2025, „measurement modes“). Každé datové pole jsou sekundy s 12 desetinnými místy (výchozí 11 od firmwaru 20251101: čte se libovolný počet až 15). Časové razítko se čte z desetinného textu jako celé číslo femtosekund, nikoli jako binární číslo s plovoucí řádovou čárkou, takže fáze záznamu pořízeného dny po spuštění čítače zachovává vlastní rozlišení čítače: časové razítko f64 při 3.0e5 s má rozestup 5.8e-11 s, asi 60 ps čítače.
- Řádky režimu Timestamp (
<seconds> chA,<seconds> chB) a kanál pseudočasových značek režimu TimeLab (chC) jsou časové značky událostí. Fáze vybraného kanálu je jeho časová značka minus nominální tik:x[k] = t[k] − t[0] − n[k]·tau0, kden[k]je celý počettau0od první události. Zmeškaná událost je mezera. - Řádky režimu Interval (
<seconds> TI(A->B)nebo jakýkoli štítek začínajícíTI) se čtou přímo jako fáze, jedno čtení natau0. Scénář musí uvésttau0_s, protože řádek nenese čas. - Režim Paired Timestamp tiskne stejné řádky v pořadí kanálů a čte se jako režim Timestamp; režim 3-Corner Hat přidává syntetizovaný
chC, čtený jak je uvedeno výše. - Výstup režimů Period a Debug je odmítnut. Kanál, jehož odečty neroste, je hlášen jako režim Period. Binární režim Timestamp není text a soubor v něm je odmítnut se zprávou, která to říká.
- Řádky začínající
#a řádky, které nemají tvar<number> <label>(například úvodní nabídka), se přeskakují a počítají.
Záznamy linuxptp a chrony#
Těchto pět formátů čte, co běžící démon času zapisuje o svých vlastních hodinách. Slouží ke zpětné kontrole časovacího řetězce (hraniční hodiny, PHC grandmastera, klient chrony) týmiž estimátory jako ostatní záznamy. Nečtou konfiguraci démona a nic zde s démonem nekomunikuje.
ptp4l, phc2sys, ts2phc: servořídicí řádky linuxptp, přičemž každý formát čte jen řádky vlastního programu. Čtení je řádek ve tvaru
ptp4l[5003.000]: master offset 40 s2 freq +1480 path delay 497
phc2sys[7000.000]: CLOCK_REALTIME phc offset -30 s2 freq +100 delay 1200
ts2phc[8000.000]: /dev/ptp0 offset 3 s2 freq -2
- Časová značka je první
[seconds.fraction]na řádku (monotónní hodiny démona). Čte se i za předponou syslogu, kde identifikátor procesu jakoptp4l[812]:nemá zlomek a nebere se. - Fáze je zaznamenaný
offsetv nanosekundách, převedený na sekundy. Je to změřená časová chyba podřízených hodin démona vůči jeho referenci, tak jak byla zaznamenána: kladná, když podřízené hodiny předbíhají. Je to chyba zbývající pod servořízením, nikoli drift volně běžících hodin. - Slova mezi časovou značkou a
offsetpojmenovávají zdroj (master,eth0 masterpro předponu[eth0],CLOCK_REALTIME phc,/dev/ptp0). Záznam s více než jedním zdrojem vyžadujeclock = "<that text>"; chyba je vypíše. - Čtení před tím, než servo poprvé ohlásí
s2(uzamčeno), se vynechávají a počítají vn_skipped_lines:s0as1jsou stavy neuzamčeno a skok, jejichž offsety jsou přechodové jevy při náběhu. Servo, kterés2nikdy nedosáhne, se odmítne. Řádek bez pole stavu se čte tak, jak je. - Souhrnné řádky (
rms ... max ...), zprávydelayaselected best mastera řádky jiných programů se přeskakují a počítají. - Časové značky, které jdou zpět (restartovaný démon), se odmítají; záznam rozdělte.
chrony-tracking, chrony-statistics: soubory log tracking a log statistics programu chrony, čtené podle pozice sloupce. Čtení je řádek s alespoň 14 sloupci (tracking) nebo 13 (statistics), který začíná datem a časem UTC ve tvaru YYYY-MM-DD HH:MM:SS. Řádek záhlaví sloupců se přeskakuje a počítá; čára ==== pod ním se přeskakuje bez započtení.
- Tracking: sloupec 7, místní offset při aktualizaci hodin, v sekundách. IP adresa nebo id reference se mění s vybraným zdrojem, takže bez
clockse každý řádek čte jako jedny místní hodiny.clock = "<id>"ponechá jedno id reference. - Statistics: sloupec 5, odhadnutý offset zdroje, v sekundách. Na adresu zdroje připadá jedna řada a záznam potřebuje
clock = "<address>", pokud jich obsahuje více. - Epochy jsou sekundy od 1980-01-06 00:00:00 UTC, bez zpracování přestupných sekund. Chrony zapisuje řádek na každou aktualizaci nebo vzorek zdroje, takže rozestup není rovnoměrný.
tau0je mediánový rozestup; čtení méně než půltau0po uchovaném předchozím se zahodí a započítá don_duplicatesa delší rozestup je mezera, kterou hlásígaps = "refuse". U záznamu s ustáleným intervalem dotazování zadejtetau0_sagaps = "linear".
Sloupce chrony a rozvržení řádků linuxptp odpovídají veřejné dokumentaci démonů. Fixtures v tests/fixtures/clock_log/linuxptp_chrony/ byly pro Kshana napsány s vymyšlenými hodnotami (viz jeho NOTICE.md); žádný skutečný záznam se nečetl, takže rozvržení lišící se mezi verzemi démonů může být stále odmítnuto nebo špatně přečteno. Řádek, který neodpovídá, se přeskočí a započítá, nikdy se nehádá.
tau0 a mezery#
Když záznam nese časové značky a není zadáno tau0, je tau0 mediánový rozestup po sobě jdoucích časových značek zaokrouhlený na čtyři platné číslice a zdroj se uvádí jako median-spacing. Rozestup čítače se od nominálního liší o frekvenční offset reference, o 10^6 dílů nebo méně. tau0_s ve scénáři vždy vyhrává (zdroj input), poté komentář záhlaví tau0 (zdroj header).
Vzorky se umísťují na mřížku t0 + i·tau0 a chybějící epocha je mezera. Čtení vzdálenější od mřížky než 1 % z tau0 se zahodí a započítá, stejně jako duplicity (první se ponechá). Politika mezer je jedna z těchto:
refuse(výchozí): jakákoli mezera je chyba, která mezery spočítá;longest: ponechat nejdelší souvislý úsek bez mezer;linear: doplnit vnitřní mezery lineární interpolací a uvést počet doplněných.
Estimátory potřebují záznam bez mezer, a proto se mezery řeší zde.
Vaše vlastní hodiny#
Tabulka [clock_log] u druhu clock uvádí, jak stabilní byly vaše vlastní hodiny, vedle simulace: scenarios/clock-measured-log.toml (kshana example clock-measured-log) je clock-holdover.toml s výřezem 96 odečtů hodin družice IGS jako vloženým záznamem TimeLab. Nahraďte text hodnotami path a format pro svůj soubor. Blok measured ve výsledku obsahuje, jak byl záznam přečten (formát, tau0 a odkud pochází, každá mezera) a jeho ADEV, TDEV a MTIE; simulaci nemění.
Řízení holdoveru vlastními hodinami: [clock_fit]#
[clock_log] # the measured series, as above
format = "ticc"
path = "my-clock.txt"
channel = "chA"
[clock_fit]
replaces = "classical" # or "quantum": the simulated clock whose noise the log replaces
Záznam se fituje postupem karty zařízení z src/clock_library/card.rs (úprava, odstranění kvadratické složky, identifikace šumu s lagem 1, vážené nejmenší čtverce v bílém PM, bílém FM, flicker FM a random-walk FM při časech průměrování s alespoň 30 stupni volnosti). Pojmenované hodiny pak přebírají q_wf = h_0 / 2, q_rw = 2 pi^2 h_-2, flicker_floor = sqrt(2 ln 2 h_-1) a nafitovaný drift; y0 zůstává, jak jej má scénář, protože záznam nese ofset své reference, nikoli hodin po disciplinaci. Bílý fázový šum se fituje a uvádí, ale nesimuluje. Výsledek získává blok fitted (koeficienty, body fitu, hodnoty, které běh použil, co bylo vynecháno, SHA-256 záznamu) a hodiny nesou id measured:<12 hex of the phase hash>. S runs > 1 čerpá soubor běhů z nafitovaných hodin (blok measured potřebuje runs = 1). Fit bez frekvenčního šumu, záznam příliš krátký na fit a replaces jiný než quantum nebo classical jsou chyby, které to říkají. scenarios/clock-fitted-log.toml je příklad (6 hodin hodin družice IGS).
Co ukazuje srovnání na známém šumu (tests/fixtures/clock_fit/RESULTS.md) a co mít na paměti:
- Splněno: úroveň bílého FM se obnoví do 5 % na každém syntetickém záznamu, který jej má; nafitovaná karta reprodukuje skutečnou Allanovu odchylku v rozmezí faktoru 1,35 při každém času průměrování, pro který byla fitována; exponent šumu, který fit identifikuje, se rovná exponentu z allantools v každém bodě (na záznamu 5071A poté, co je fázový skok, který úprava odstraní, odstraněn i ze vstupu allantools).
- Nesplněno a zafixováno testem: random-walk FM se obnoví jen tehdy, když dominuje nejdelším časům průměrování záznamu, a i tehdy jen u jednoho ze tří záznamů řady o 131 072 s s překřížením při 3 000 s; fit jej přiřadil flicker FM a driftu. Rozdělení mezi random-walk FM a flicker FM není z jednoho záznamu spolehlivé. Běh reprodukuje stabilitu záznamu v časech průměrování, které záznam pokrývá; za nimi se obě volby rozcházejí (flicker FM je konstantní podlaha, random-walk FM roste jako druhá odmocnina času průměrování).
- MODELLED: scénář „co kdyby“ pro šum těchto hodin tak, jak jej záznam ukazuje, nikoli kalibrace hodin ani předpověď jejich budoucího chování.
Chybně utvořený záznam je chyba, která uvádí, co bylo nalezeno (řádek, verzi, chybějící volič), nikdy částečný výsledek: tests/clock_log_real_allantools.rs zafixovává 24 takových případů.
Důkazy#
MODELLED. Toto je parser a jeho výstup krmí odhadovače, které jsou jinde validovány proti allantools. Jednotkové testy v src/clock_log.rs používají malé ručně psané záznamy a pro formáty linuxptp a chrony fixtury v tests/fixtures/clock_log/linuxptp_chrony/. tests/clock_log_allantools.rs spouští srovnání předregistrované v tests/fixtures/clock_log/PREREGISTRATION.md: tři syntetické záznamy se seedem, po jednom na formát, načtené zpět nezávislou čtečkou napsanou podle této stránky týmž autorem, s ADEV, TDEV a MTIE zkontrolovanými proti allantools 2024,6; toto srovnání pokrývá jen první tři formáty a čtečky linuxptp a chrony mají testy parseru, ale žádné srovnání s orákulem. Záznamy tohoto srovnání jsou syntetické, takže nic z toho nepopisuje skutečné hodiny ani čítač; srovnání na změřených řadách je popsáno níže.
Na změřených datech#
tests/clock_log_real_allantools.rs spouští srovnání předregistrované v tests/fixtures/clock_log_real/PREREGISTRATION.md (odevzdané před jakoukoli fixturou či během) na čtyřech změřených řadách: PHASE.DAT ze Stable32, prvních 65 536 odečtů cesiových hodin 5071A proti vodíkovému maseru a hodinách družice IGS G01 (30 s) a stanice ABMF (300 s) z finálních hodin IGS ze 2026-08-02, jako vendorovaný výřez s jeho NOTICE. První dvě nenesou povolení k redistribuci: záznamy z nich zapsané jsou v realdata-cache/ ignorovaném gitem (scripts/gen_clock_log_real_ref.py) a test to uvádí a při jejich nepřítomnosti projde, pokud není KSHANA_REQUIRE_REALDATA=1. Každý záznam čte engine i nezávislá čtečka a ADEV, TDEV a MTIE se porovnávají s allantools 2024,6. Zaznamenáno v tests/fixtures/clock_log_real/RESULTS.md: u dodávané čtečky selhaly na předregistrovaných prazích záznamy TICC, verze hlavičky a pět chybových zpráv; byly opraveny a srovnání bylo znovu spuštěno beze změny. Splněno kromě jednoho páru: MTIE frekvenčního záznamu se liší od allantools, protože allantools integruje frekvenci minus její střední hodnotu (zafixováno jako NOT MET; srovnání na stejném základě je splněno). Řádek zůstává MODELLED: záznamy TICC jsou změřená data hodin překódovaná naším skriptem do rozvržení čítače (žádný skutečný záznam z TICC nebyl nalezen) a referenční čtečka má stejného autora jako ta v enginu.