Formater for urlogs
src/clock_log.rs læser en målt urlog til én normaliseret faseserie: et ensartet gitter af samples (time_s, phase_s), med samplingsintervallet tau0 angivet eller fundet, hvert hul talt og logens enheder navngivet. Otte formater læses, hver en dokumenteret delmængde. Alt uden for delmængden afvises med en fejl, der navngiver det, der blev fundet, i stedet for at blive læst omtrentligt.
Forkortelser. RINEX er Receiver Independent Exchange Format. TICC er TAPR's (Tucson Amateur Packet Radio) tidsintervaltæller. ADEV er den overlappende Allan-deviation, TDEV tidsdeviationen og MTIE den maksimale tidsintervalfejl. tau0 er samplingsintervallet i sekunder.
Hvor en log kan bruges#
telecom-timing:[series.clock_log]i stedet forseries.samplesellerseries.csv_path. Logens fase i ns er tidsfejlsserien, der kontrolleres mod maskerne, og rapporten får en blokclock_log, der beskriver, hvordan den blev læst.- Urtypen: en tabel
[clock_log]tilføjer en blokmeasuredtil kørslen: hvordan logen blev læst, SHA-256 af tabellen (input_sha256; kørslensscenario_hashdækker ikke tabellen) og af fasesamplene samt den overlappende ADEV, TDEV og MTIE ved gennemsnitsfaktorer i oktaver. Den kræverruns = 1. Den simulerede holdover er uændret.
Uden tabellen parses, hashes og rapporteres begge typer nøjagtigt 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
Formaterne#
rinex-clk: RINEX-urfiler, version 2,00 og 3,00 til 3,04 (herunder navnefeltet med ni tegn i 3,04). Posten RINEX VERSION / TYPE kontrolleres, og enhver anden version afvises med angivelse af den fundne version: IGS udgiver urformatet (rinex_clock300.txt, 302, 304) op til 3,04, og dokumenterne RINEX 4,00, 4,01 og 4,02 definerer kun observations-, navigations- og meteorologiske filer, så der findes ingen version 4,00 af urfilen at læse. Headeren læses kun for sit TIME SYSTEM ID og springes over til END OF HEADER. Af dataposterne beholdes kun posterne AS (satellit) og AR (modtager eller station) for ét ur, valgt efter navn. Deres første værdifelt, urbiasen i sekunder, er fasen. Fortsættelseslinjer og posterne CR, DR og MS springes over. Epoker er postens kalenderfelter, som sekunder fra 1980-01-06 00:00:00 i filens eget tidssystem, uden konvertering.
timelab: ASCII-fase- eller frekvenslogs i TimeLab-stil, den almindelige tekstform, som TimeLab eksporterer, og som dets ASCII-import og Stable32 læser. Der er én måling pr. linje: enten én kolonne ved et ensartet tau0 eller to kolonner time value. Kolonner kan adskilles af blanktegn, kommaer eller semikoloner.
- Linjer, der begynder med
#,;eller%, er kommentarer. En kommentar på formenkey = value(ellerkey: value) sættertau0(s),units(s,ms,us,nsellerps, for fase),data(phaseellerfrequency) ellertime_units(sellermjd, for den første af to kolonner). - Én indledende ikke-numerisk linje opfattes som kolonneoverskrift.
- Frekvensdata (fraktionel frekvens) accepteres kun som én kolonne. De integreres til fase som
x[i+1] = x[i] + y[i]·tau0(NIST SP 1065, 2008, §4,1). - TimeLabs binære projektfiler og projektfiler af typen
.timlæses ikke.
ticc: logs fra TAPR TICC-tælleren (TICC Operation Manual, revisioner af 23 november 2016 og 15 december 2025, "measurement modes"). Hvert datafelt er sekunder med 12 decimaler (11 som standard fra firmware 20251101: ethvert antal op til 15 læses). Et tidsstempel læses fra sin decimaltekst som et helt antal femtosekunder, ikke som et binært flydende tal, så fasen i en log optaget dage efter tællerens start bevarer tællerens egen opløsning: et f64-tidsstempel ved 3.0e5 s har en afstand på 5.8e-11 s, omkring tællerens 60 ps.
- Linjer i timestamp-tilstand (
<seconds> chA,<seconds> chB) og TimeLab-tilstandens pseudotidsstempelkanal (chC) er hændelsestidsstempler. Fasen for den valgte kanal er dens tidsstempel minus den nominelle tick:x[k] = t[k] − t[0] − n[k]·tau0, hvorn[k]er det hele antaltau0siden den første hændelse. En overset hændelse er et hul. - Linjer i interval-tilstand (
<seconds> TI(A->B)eller en vilkårlig etiket, der begynder medTI) læses direkte som fase, én måling pr.tau0. Scenariet skal angivetau0_s, fordi linjen ikke indeholder noget tidspunkt. - Tilstanden Paired Timestamp udskriver de samme linjer i kanalrækkefølge og læses som tilstanden Timestamp; tilstanden 3-Corner Hat tilføjer den syntetiserede
chC, læst som ovenfor. - Output i periode-tilstand og debug-tilstand afvises. En kanal, hvis målinger ikke vokser, rapporteres som periode-tilstand. Binær Timestamp-tilstand er ikke tekst, og en fil i den afvises med en meddelelse, der siger det.
- Linjer, der begynder med
#, og linjer, der ikke er<number> <label>(som opstartsmenuen), springes over og tælles.
linuxptp- og chrony-logs#
Disse fem formater læser det, en kørende tidsdæmon skriver om sit eget ur. De er til at kontrollere en tidskæde bagefter (et boundary-ur, en grandmasters PHC, en chrony-klient) med de samme estimatorer som de øvrige logs. De læser ikke en dæmons konfiguration, og intet her taler med en dæmon.
ptp4l, phc2sys, ts2phc: servolinjerne fra linuxptp, hvor hvert format kun læser linjer fra sit eget program. En måling 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
- Tidsstemplet er den første
[seconds.fraction]i linjen (dæmonens monotone ur). Det læses også efter et syslog-præfiks, hvor et proces-id somptp4l[812]:ikke har nogen brøkdel og ikke tages med. - Fasen er den loggede
offseti nanosekunder, omregnet til sekunder. Det er dæmonens målte tidsfejl for dens slave-ur i forhold til dens reference, som logget: positiv, når slaven er forud. Det er den fejl, der er tilbage under servostyring, ikke et frit løbende urs drift. - Ordene mellem tidsstemplet og
offsetangiver kilden (master,eth0 masterfor et præfiks[eth0],CLOCK_REALTIME phc,/dev/ptp0). En log med mere end én kilde kræverclock = "<that text>"; fejlen opregner dem. - Målinger, før servoen første gang rapporterer
s2(låst), udelades og tælles in_skipped_lines:s0ogs1er tilstandene ulåst og trin, hvis offsets er indsvingningstransienter. En servo, der aldrig nårs2, afvises. En linje uden tilstandsfelt læses, som den er. - Oversigtslinjer (
rms ... max ...), meddelelsernedelayogselected best masterog linjer fra andre programmer springes over og tælles. - Tidsstempler, der går baglæns (en genstartet dæmon), afvises; del logen.
chrony-tracking, chrony-statistics: chronys filer log tracking og log statistics, læst efter kolonneposition. En måling er en linje med mindst 14 kolonner (tracking) eller 13 (statistics), der begynder med en UTC-dato og -tid på formen YYYY-MM-DD HH:MM:SS. Linjen med kolonneoverskrifter springes over og tælles; stregen ==== under den springes over uden at blive talt.
- Tracking: kolonne 7, det lokale offset ved opdateringen af uret, i sekunder. IP-adressen eller reference-id'et skifter med den valgte kilde, så uden
clocklæses hver linje som ét lokalt ur.clock = "<id>"beholder ét reference-id. - Statistics: kolonne 5, en kildes estimerede offset, i sekunder. Der er én serie pr. kildeadresse, og logen kræver
clock = "<address>", når den indeholder mere end én. - Epoker er sekunder fra 1980-01-06 00:00:00 UTC uden håndtering af skudsekunder. Chrony skriver en linje pr. opdatering eller pr. kildesample, så afstanden er ikke ensartet.
tau0er medianafstanden; en måling under et halvttau0efter den foregående beholdte måling droppes og tælles in_duplicates, og en længere afstand er et hul, somgaps = "refuse"rapporterer. Angivtau0_soggaps = "linear"for en log med et stabilt pollinginterval.
Chrony-kolonnerne og linuxptp-linjelayoutene er dem fra dæmonernes offentlige dokumentation. Fixturerne i tests/fixtures/clock_log/linuxptp_chrony/ er skrevet til Kshana med opdigtede værdier (se dens NOTICE.md); ingen rigtig log er læst, så et layout, der afviger mellem dæmonversioner, stadig kan blive afvist eller læst forkert. En linje, der ikke passer, springes over og tælles, aldrig gættet.
tau0 og huller#
Når logen har tidsstempler og der ikke er angivet tau0, er tau0 medianafstanden mellem på hinanden følgende tidsstempler, afrundet til fire betydende cifre, og kilden rapporteres som median-spacing. En tællers afstand afviger fra den nominelle med referencens frekvensforskydning, dele pr. 10^6 eller mindre. Et tau0_s i scenariet vinder altid (kilde input), derefter en headerkommentar tau0 (kilde header).
Samples placeres på gitteret t0 + i·tau0, og en manglende epoke er et hul. Målinger, der ligger mere end 1 % af tau0 fra gitteret, droppes og tælles, det samme gælder dubletter (den første beholdes). Hulpolitikken er en af følgende:
refuse(standard): ethvert hul er en fejl, der tæller hullerne;longest: behold den længste hulfrie række;linear: udfyld indre huller ved lineær interpolation, og rapportér antallet udfyldt.
Estimatorerne kræver en hulfri optagelse, og derfor løses hullerne her.
Dit eget ur#
En tabel [clock_log] på urtypen rapporterer, hvor stabilt dit eget ur var, ved siden af simuleringen: scenarios/clock-measured-log.toml (kshana example clock-measured-log) er clock-holdover.toml med et udtræk på 96 aflæsninger af et IGS-satellitur som en indlejret TimeLab-log. Erstat text med path og format for din egen fil. Blokken measured i resultatet rummer, hvordan loggen blev læst (format, tau0 og hvor den kom fra, hvert hul) og dens ADEV, TDEV og MTIE; den ændrer ikke simuleringen.
At drive holdoveren med dit eget ur: [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 enhedskortets procedure fra src/clock_library/card.rs (konditionering, kvadratisk led fjernet, lag-1-støjidentifikation, vægtet mindste kvadraters metode i hvid PM, hvid FM, flicker-FM og random-walk-FM ved de middelingstider, der har mindst 30 frihedsgrader). Det navngivne ur får derefter 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 forbliver, som scenariet har det, fordi en log bærer referencens offset, ikke urets efter disciplinering. Hvid fasestøj tilpasses og rapporteres, men simuleres ikke. Resultatet får en blok fitted (koefficienterne, tilpasningspunkterne, de værdier, kørslen brugte, hvad der blev udeladt, logens SHA-256), og uret bærer id'et measured:<12 hex of the phase hash>. Med runs > 1 trækker ensemblet fra det tilpassede ur (blokken measured kræver runs = 1). En tilpasning uden frekvensstøj, en log for kort til at tilpasse og en replaces andre end quantum eller classical er fejl, der siger det. scenarios/clock-fitted-log.toml er et eksempel (6 timer af et IGS-satellitur).
Hvad sammenligningen på kendt støj (tests/fixtures/clock_fit/RESULTS.md) viser, og hvad man bør huske:
- Nået: niveauet af hvid FM genfindes inden for 5 % på hver syntetisk optagelse, der har den; det tilpassede kort gengiver den sande Allan-deviation inden for en faktor 1,35 ved hver middelingstid, det blev tilpasset ved; støjeksponenten, som tilpasningen identificerer, er lig med allantools' i hvert punkt (på 5071A-optagelsen, når fasetrinnet, som konditioneringen fjerner, også er fjernet fra allantools' input).
- Ikke nået og fastholdt af testen: random-walk-FM genfindes kun, når den dominerer rækkens længste middelingstider, og selv da kun i én af tre optagelser; i en serie på 131.072 s med et krydsningspunkt ved 3.000 s gav tilpasningen den til flicker-FM og til driften. Fordelingen mellem random-walk-FM og flicker-FM er ikke pålidelig ud fra én optagelse. Kørslen gengiver logens stabilitet over de middelingstider, loggen dækker; ud over dem divergerer de to valg (flicker-FM er et konstant gulv, random-walk-FM vokser som kvadratroden af middelingstiden).
- MODELLED: et hvad-nu-hvis for det urs støj, som loggen viser den, ikke en kalibrering af uret og ikke en forudsigelse af dets fremtidige adfærd.
En ugyldig log er en fejl, der nævner, hvad der blev fundet (linjen, versionen, den manglende vælger), aldrig et delvist resultat: tests/clock_log_real_allantools.rs fastholder 24 sådanne tilfælde.
Evidens#
MODELLED. Dette er en parser, og dens output føder estimatorer, der er valideret andetsteds mod allantools. Enhedstestene i src/clock_log.rs bruger små håndskrevne logs og for formaterne linuxptp og chrony fixturerne i tests/fixtures/clock_log/linuxptp_chrony/. tests/clock_log_allantools.rs kører den sammenligning, der er præregistreret i tests/fixtures/clock_log/PREREGISTRATION.md: tre seedede syntetiske logs, én pr. format, læst tilbage af en uafhængig læser skrevet ud fra denne side af samme forfatter, med ADEV, TDEV og MTIE kontrolleret mod allantools 2024,6; den sammenligning dækker kun de tre første formater, og læserne af linuxptp og chrony har parsertests, men ingen sammenligning med en uafhængig reference. Logs i den sammenligning er syntetiske, så intet dér beskriver et virkeligt ur eller en virkelig tæller; sammenligningen på målte serier beskrives nedenfor.
På målte data#
tests/clock_log_real_allantools.rs kører den sammenligning, der er præregistreret i tests/fixtures/clock_log_real/PREREGISTRATION.md (indlagt før nogen fixture eller kørsel), på fire målte serier: Stable32-filen PHASE.DAT, de første 65.536 aflæsninger af et 5071A-cæsiumur mod en brintmaser samt urene i IGS-satellitten G01 (30 s) og stationen ABMF (300 s) fra IGS' endelige urfil for 2026-08-02, som et medleveret udsnit med sin NOTICE. De to første bærer ingen tilladelse til videredistribution: de logs, der er skrevet ud fra dem, ligger i det git-ignorerede realdata-cache/ (scripts/gen_clock_log_real_ref.py), og testen siger det og bestås, når de mangler, medmindre KSHANA_REQUIRE_REALDATA=1. Hver log læses af motoren og af en uafhængig læser, og ADEV, TDEV og MTIE sammenlignes med allantools 2024,6. Optaget i tests/fixtures/clock_log_real/RESULTS.md: på den udleverede læser fejlede TICC-logs, headerversionen og fem fejlmeddelelser de præregistrerede tærskler; de blev rettet, og sammenligningen blev kørt igen uændret. Nået, bortset fra ét par: MTIE for en frekvenslog afviger fra allantools', fordi allantools integrerer frekvensen minus dens middelværdi (fastholdt som NOT MET; sammenligningen på sammenlignelig basis er nået). Rækken forbliver MODELLED: TICC-logs er målte urdata, omkodet til tællerens layout af vores script (ingen virkelig TICC-optagelse blev fundet), og referencelæseren har samme forfatter som motorens.