Formater for klokkelogger
src/clock_log.rs leser en målt klokkelogg til én normalisert faseserie: et jevnt rutenett av (time_s, phase_s)-samples, med sampleintervallet tau0 oppgitt eller funnet, hvert hull talt og enhetene i loggen navngitt. Åtte formater leses, hvert en dokumentert delmengde. Alt utenfor delmengden avvises med en feil som navngir det som ble funnet, i stedet for å leses omtrentlig.
Forkortelser. RINEX er Receiver Independent Exchange Format. TICC er TAPR-tidsintervalltelleren (Tucson Amateur Packet Radio). ADEV er den overlappende Allan-deviasjonen, TDEV tidsdeviasjonen og MTIE den maksimale tidsintervallfeilen. tau0 er sampleintervallet i sekunder.
Hvor en logg kan brukes#
telecom-timing:[series.clock_log]i stedet forseries.samplesellerseries.csv_path. Loggens fase, i ns, er tidsfeilserien som kontrolleres mot maskene, og rapporten får en blokkclock_logsom sier hvordan den ble lest.- Klokketypen: en tabell
[clock_log]legger til en blokkmeasuredi kjøringen: hvordan loggen ble lest, SHA-256 for tabellen (input_sha256; kjøringensscenario_hashdekker ikke tabellen) og for fasesamplene, og den overlappende ADEV, TDEV og MTIE ved oktavvise midlingsfaktorer. Den kreverruns = 1. Den simulerte holdoveren er uendret.
Uten tabellen parses, hashes og rapporteres begge typene nøyaktig som før.
[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
Formatene#
rinex-clk: RINEX-klokkefiler, versjon 2,00 og 3,00 til 3,04 (inkludert navnefeltet på ni tegn i 3,04). Posten RINEX VERSION / TYPE kontrolleres, og enhver annen versjon avvises med navnet på versjonen som ble funnet: IGS publiserer klokkeformatet (rinex_clock300.txt, 302, 304) opp til 3,04, og dokumentene RINEX 4,00, 4,01 og 4,02 definerer bare observasjons-, navigasjons- og meteorologifiler, så det finnes ingen versjon 4,00 av klokkefilen å lese. Headeren leses bare for sin TIME SYSTEM ID og hoppes over frem til END OF HEADER. Av datapostene beholdes bare postene AS (satellitt) og AR (mottaker eller stasjon) for én klokke, valgt etter navn. Det første verdifeltet deres, klokkebiasen i sekunder, er fasen. Fortsettelseslinjer og postene CR, DR og MS hoppes over. Epoker er postens kalenderfelt, som sekunder fra 1980-01-06 00:00:00 i filens eget tidssystem, uten konvertering.
timelab: ASCII-fase- eller frekvenslogger i TimeLab-stil, tekstformen som TimeLab eksporterer og som ASCII-importen og Stable32 leser. Det er én avlesning per linje: enten én kolonne ved et jevnt tau0, eller to kolonner time value. Kolonner kan skilles med blanktegn, komma eller semikolon.
- Linjer som starter med
#,;eller%er kommentarer. En kommentar på formenkey = value(ellerkey: value) settertau0(s),units(s,ms,us,nsellerps, for fase),data(phaseellerfrequency) ellertime_units(sellermjd, for den første av to kolonner). - Én innledende ikke-numerisk linje tas som kolonneoverskrift.
- Frekvensdata (relativ frekvens) godtas bare som én enkelt kolonne. De integreres til fase som
x[i+1] = x[i] + y[i]·tau0(NIST SP 1065, 2008, §4,1). - TimeLabs binære prosjektfiler og prosjektfiler av typen
.timleses ikke.
ticc: logger fra TAPR TICC-telleren (TICC Operation Manual, revisjoner av 23 november 2016 og 15 desember 2025, «measurement modes»). Hvert datafelt er sekunder med 12 desimaler (11 som standard fra firmware 20251101: ethvert antall opp til 15 leses). Et tidsstempel leses fra sin desimaltekst som et helt antall femtosekunder, ikke som et binært flyttall, så fasen i en logg tatt dager etter at telleren startet beholder tellerens egen oppløsning: et tidsstempel av typen f64 ved 3.0e5 s har en avstand på 5.8e-11 s, omtrent tellerens 60 ps.
- Linjer i tidsstempelmodus (
<seconds> chA,<seconds> chB) og TimeLab-modusens pseudo-tidsstempelkanal (chC) er tidsstempler for hendelser. Fasen til den valgte kanalen er tidsstempelet minus den nominelle tikken:x[k] = t[k] − t[0] − n[k]·tau0, dern[k]er det hele antallettau0siden den første hendelsen. En hendelse som uteblir er et hull. - Linjer i intervallmodus (
<seconds> TI(A->B), eller en hvilken som helst etikett som starter medTI) leses direkte som fase, én avlesning pertau0. Scenarioet må oppgitau0_s, fordi linjen ikke bærer noe tidspunkt. - Paired Timestamp-modus skriver ut de samme linjene i kanalrekkefølge og leses som Timestamp-modus; 3-Corner Hat-modus legger til den syntetiserte
chC, lest som over. - Utdata i periodemodus og feilsøkingsmodus avvises. En kanal der avlesningene ikke øker rapporteres som periodemodus. Binær Timestamp-modus er ikke tekst, og en fil av den avvises med en melding som sier det.
- Linjer som starter med
#, og linjer som ikke er<number> <label>(for eksempel oppstartsmenyen), hoppes over og telles.
Logger fra linuxptp og chrony#
Disse fem formatene leser det en kjørende tidsdaemon skriver om sin egen klokke. De er til for å kontrollere en tidskjede i etterkant (en boundary clock, en grandmasters PHC, en chrony-klient) med de samme estimatorene som for de andre loggene. De leser ikke en daemons konfigurasjon, og ingenting her snakker med en daemon.
ptp4l, phc2sys, ts2phc: servolinjene til linuxptp, der hvert format bare leser linjer fra sitt eget program. En avlesning er en linje på formen
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
- Tidsstempelet er den første
[seconds.fraction]i linjen (daemonens monotone klokke). Det leses også etter et syslog-prefiks, der en prosess-ID somptp4l[812]:ikke har noen brøkdel og ikke tas. - Fasen er den loggførte
offset, i nanosekunder, konvertert til sekunder. Det er daemonens målte tidsfeil for slaveklokken mot referansen, slik den er loggført: positiv når slaven ligger foran. Det er feilen som er igjen under servostyring, ikke driften til en fritt løpende klokke. - Ordene mellom tidsstempelet og
offsetnavngir kilden (master,eth0 masterfor et prefiks[eth0],CLOCK_REALTIME phc,/dev/ptp0). En logg med mer enn én kilde trengerclock = "<that text>"; feilen lister dem. - Avlesninger før servoen første gang rapporterer
s2(låst) utelates og telles in_skipped_lines:s0ogs1er de ulåste tilstandene og steg-tilstandene, hvis avvik er innsvingningstransienter. En servo som aldri nårs2avvises. En linje uten tilstandsfelt leses som den er. - Sammendragslinjer (
rms ... max ...), meldinger omdelayogselected best master, og linjer fra andre programmer hoppes over og telles. - Tidsstempler som går bakover (en daemon som er startet på nytt) avvises; del opp loggen.
chrony-tracking, chrony-statistics: chronys filer log tracking og log statistics, lest etter kolonneposisjon. En avlesning er en linje med minst 14 kolonner (tracking) eller 13 (statistics) som starter med en UTC-dato og et UTC-klokkeslett på formen YYYY-MM-DD HH:MM:SS. Kolonneoverskriftslinjen hoppes over og telles; regelen ==== under den hoppes over uten å telles.
- Tracking: kolonne 7, det lokale avviket ved klokkeoppdateringen, i sekunder. IP-adressen eller referanse-ID-en endres med den valgte kilden, så uten
clockleses hver linje som én lokal klokke.clock = "<id>"beholder én referanse-ID. - Statistics: kolonne 5, det estimerte avviket for en kilde, i sekunder. Det er én serie per kildeadresse, og loggen trenger
clock = "<address>"når den inneholder mer enn én. - Epoker er sekunder fra 1980-01-06 00:00:00 UTC, uten håndtering av skuddsekunder. Chrony skriver en linje per oppdatering eller per kildesample, så avstanden er ikke jevn.
tau0er medianavstanden; en avlesning under et halvttau0etter den som ble beholdt før den, forkastes og telles in_duplicates, og en lengre avstand er et hull, somgaps = "refuse"rapporterer. Oppgitau0_soggaps = "linear"for en logg med jevnt pollingintervall.
Chrony-kolonnene og linjeoppsettene til linuxptp er de fra daemonenes offentlige dokumentasjon. Fiksene i tests/fixtures/clock_log/linuxptp_chrony/ er skrevet for Kshana med oppdiktede verdier (se NOTICE.md); ingen ekte logg ble lest, så et oppsett som er ulikt mellom daemonversjoner kan fortsatt bli avvist eller feiltolket. En linje som ikke passer hoppes over og telles, aldri gjettet.
tau0 og hull#
Når loggen bærer tidsstempler og ingen tau0 er oppgitt, er tau0 medianavstanden mellom påfølgende tidsstempler, avrundet til fire gjeldende siffer, og kilden rapporteres som median-spacing. En tellers avstand avviker fra den nominelle med referansens frekvensavvik, deler per 10^6 eller mindre. Et tau0_s i scenarioet vinner alltid (kilde input), deretter en header-kommentar tau0 (kilde header).
Samples plasseres på rutenettet t0 + i·tau0, og en manglende epoke er et hull. Avlesninger som ligger mer enn 1 % av tau0 utenfor rutenettet forkastes og telles, det samme gjør duplikater (den første beholdes). Hullpolicyen er én av:
refuse(standard): ethvert hull er en feil som teller hullene;longest: behold den lengste hullfrie perioden;linear: fyll indre hull med lineær interpolasjon, og rapporter hvor mange som ble fylt.
Estimatorene trenger en hullfri registrering, og derfor løses hull her.
Din egen klokke#
En tabell [clock_log] på klokketypen rapporterer hvor stabil din egen klokke var, ved siden av simuleringen: scenarios/clock-measured-log.toml (kshana example clock-measured-log) er clock-holdover.toml med et utdrag på 96 avlesninger av en IGS-satellittklokke som en innebygd TimeLab-logg. Erstatt text med path og format for din egen fil. Blokken measured i resultatet inneholder hvordan loggen ble lest (format, tau0 og hvor den kom fra, hvert gap) og dens ADEV, TDEV og MTIE; den endrer ikke simuleringen.
Å drive holdoveren med din egen klokke: [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
Loggen tilpasses med enhetskortprosedyren i src/clock_library/card.rs (kondisjonering, kvadratisk ledd fjernet, støyidentifikasjon med lag 1, vektet minste kvadraters metode i hvit PM, hvit FM, flicker FM og random-walk FM ved de midlingstidene som har minst 30 frihetsgrader). Den navngitte klokken tar deretter q_wf = h_0 / 2, q_rw = 2 pi^2 h_-2, flicker_floor = sqrt(2 ln 2 h_-1) og den tilpassede drift; y0 forblir som scenarioet har det, fordi en logg bærer offsetten til sin referanse, ikke klokkens etter disiplinering. Hvit fasestøy tilpasses og rapporteres, men simuleres ikke. Resultatet får en blokk fitted (koeffisientene, tilpasningspunktene, verdiene kjøringen brukte, hva som ble utelatt, loggens SHA-256), og klokken får id-en measured:<12 hex of the phase hash>. Med runs > 1 trekker ensemblet fra den tilpassede klokken (blokken measured trenger runs = 1). En tilpasning uten frekvensstøy, en logg for kort til å tilpasses og en replaces som er noe annet enn quantum eller classical er feil som sier det. scenarios/clock-fitted-log.toml er et eksempel (6 timer av en IGS-satellittklokke).
Hva sammenligningen på kjent støy (tests/fixtures/clock_fit/RESULTS.md) viser, og hva man bør ha i bakhodet:
- Nådd: nivået for hvit FM gjenfinnes innenfor 5 % på hver syntetiske serie som har det; det tilpassede kortet gjengir det sanne Allan-avviket innenfor en faktor på 1,35 ved hver midlingstid det ble tilpasset ved; støyeksponenten tilpasningen identifiserer er lik den til allantools ved hvert punkt (på 5071A-serien, når fasespranget som kondisjoneringen fjerner også er fjernet fra inndataene til allantools).
- Ikke nådd, og festet av testen: random-walk FM gjenfinnes bare når den dominerer de lengste midlingstidene i serien, og selv da i én av tre poster av en serie på 131 072 s med et krysningspunkt ved 3 000 s, ga tilpasningen den til flicker FM og til driften. Skillet mellom random-walk FM og flicker FM er ikke pålitelig fra én post. Kjøringen gjengir loggens stabilitet over de midlingstidene loggen dekker; utover dem divergerer de to valgene (flicker FM er et konstant gulv, random-walk FM vokser som kvadratroten av midlingstiden).
- MODELLED: et hva-hvis for den klokkens støy slik loggen viser den, ikke en kalibrering av klokken og ikke en prediksjon av dens fremtidige oppførsel.
En feilformet logg er en feil som navngir det som ble funnet (linjen, versjonen, den manglende velgeren), aldri et delvis resultat: tests/clock_log_real_allantools.rs fester 24 slike tilfeller.
Evidens#
MODELLED. Dette er en parser, og utdataene mater estimatorer som er validert andre steder mot allantools. Enhetstestene i src/clock_log.rs bruker små håndskrevne logger, og for formatene linuxptp og chrony fiksene i tests/fixtures/clock_log/linuxptp_chrony/. tests/clock_log_allantools.rs kjører sammenligningen som er forhåndsregistrert i tests/fixtures/clock_log/PREREGISTRATION.md: tre seedede syntetiske logger, én per format, lest tilbake av en uavhengig leser skrevet ut fra denne siden av den samme forfatteren, med ADEV, TDEV og MTIE kontrollert mot allantools 2024,6; den sammenligningen dekker bare de tre første formatene, og leserne for linuxptp og chrony har parsertester, men ingen sammenligning mot en uavhengig referanse. Loggene i den sammenligningen er syntetiske, så ingenting der beskriver en ekte klokke eller teller; sammenligningen på målte serier er beskrevet nedenfor.
På målte data#
tests/clock_log_real_allantools.rs kjører sammenligningen som er forhåndsregistrert i tests/fixtures/clock_log_real/PREREGISTRATION.md (innsjekket før noen fixtur eller kjøring) på fire målte serier: Stable32-filen PHASE.DAT, de første 65 536 avlesningene av en 5071A-cesiumklokke mot et hydrogenmaser, og klokkene til IGS-satellitt G01 (30 s) og stasjon ABMF (300 s) fra den endelige IGS-klokkefilen for 2026-08-02, som et medfølgende utsnitt med sin NOTICE. De to første har ingen tillatelse til videredistribusjon: loggene skrevet fra dem ligger i den git-ignorerte realdata-cache/ (scripts/gen_clock_log_real_ref.py), og testen sier det og består når de mangler med mindre KSHANA_REQUIRE_REALDATA=1. Hver logg leses av motoren og av en uavhengig leser, og ADEV, TDEV og MTIE sammenlignes med allantools 2024,6. Registrert i tests/fixtures/clock_log_real/RESULTS.md: på den leverte leseren feilet TICC-loggene, headerversjonen og fem feilmeldinger de forhåndsregistrerte tersklene; de ble rettet og sammenligningen kjørt på nytt uendret. Nådd, bortsett fra ett par: MTIE for en frekvenslogg avviker fra den til allantools, fordi allantools integrerer frekvensen minus middelverdien (festet som NOT MET; sammenligningen på like vilkår er nådd). Raden forblir MODELLED: TICC-loggene er målte klokkedata kodet om til tellerens layout av vårt skript (ingen virkelig TICC-opptak ble funnet), og referanseleseren har samme forfatter som motorens.