Maschinelle Übersetzung, nicht von einem Muttersprachler geprüft. Englisch ist die maßgebliche Fassung.

APIs und IntegrationenAuf GitHub bearbeitenQuelle: docs/PYTHON_API.md

Python-API

Kshana liefert eine erstklassige Python-Programmierschnittstelle (API, application programming interface), gebaut mit PyO3 und maturin. Ihre abi3-Wheels werden gegen die stabile Python-Binärschnittstelle (ABI, application binary interface) gebaut, sodass ein Wheel je Plattform über CPython ≥ 3,9 hinweg funktioniert; die Wheels decken Linux, macOS und Windows ab, jeweils auf x86-64 und 64-Bit-ARM (siehe WHEEL_TAGS.md). Ein mitgeliefertes Typ-Stub (kshana.pyi + py.typed) gibt Editoren und mypy/pyright vollständige Typinformationen.

pip install kshana            # from the Python Package Index, PyPI (release wheels)
# or, from a checkout:
pip install maturin && maturin develop --features python

Schnellstart#

Führen Sie diese Snippets aus dem Wurzelverzeichnis eines Repository-Checkouts aus: Sie lesen Szenariodateien unter scenarios/. Die NumPy-Zeile braucht pip install numpy.

import kshana

toml = open("scenarios/clock-holdover.toml").read()

# Typed result with a parsed-dict accessor:
out = kshana.run_typed(toml)
print(out.summary)
data = out.data()                         # a Python dict — no JSON re-parsing
fom = data["quantum"]["fom"]              # figures of merit, quantum side
classical_fom = data["classical"]["fom"]  # … and the classical baseline
print(out.json[:80], "...")               # raw JSON also available
open("chart.svg", "w").write(out.svg)     # the chart SVG

# NumPy arrays straight from the result (NumPy is imported on call; it is not a
# dependency of the package):
curve = out.columns("quantum.adev_curve")  # {"tau_s": ndarray, "adev": ndarray, ...}
adev = curve["adev"]
everything = out.series()                  # every record series, keyed by path

Oberfläche#

Symbol Signatur Rückgabe
run_typed (toml: str) -> RunOutput typisiertes Ergebnis (.json, .svg, .summary, .csv, .data(), .array(), .columns(), .series(), .write_csv())
run (toml: str) -> str Ergebnisdokument als JSON-String (JavaScript Object Notation)
run_full (toml: str) -> tuple[str, str, str] (json, svg, summary)
scenario_kinds () -> list[dict] verfügbare Szenarioarten + Metadaten (geparst)
list_kinds () -> str dieselben Metadaten als EIN JSON-Array-String, keine Liste (für bestehende Aufrufer beibehalten; verwenden Sie scenario_kinds für die geparste Liste)
validate_toml (toml: str) -> list[str] Fehlermeldungen (leer, wenn gültig)
error_kind (toml: str) -> str | None Tag der Fehlerkategorie (invalid_input, non_convergence, unsupported oder io_error), oder None bei Erfolg
version / __version__ () -> str / str Engine-Version
receiver_trust (toml: str) -> RunOutput ein reales Empfänger-Log bewerten, das durch ein Szenario receiver-trust beschrieben wird: Ergebnisdokument, CSV mit Vertrauenswert je Epoche, Diagramm und Zusammenfassung; eine Tabelle [platform] kind = "vessel" fügt die maritimen Monitore und den Vertrauenswert von 0 bis 100 mit Gründen hinzu (beratend)
receiver_trust_replay (session_toml, nmea) -> dict ein begrenzter NMEA-Auszug, so bewertet, wie der Live-Modus bewertet: Zustand je Epoche, Wert von 0 bis 100 und Gründe, eine Zusammenfassung (kein Socket, kein Gate; beratend)
assess_vessel_log (session_toml, log) -> dict das NMEA-Log eines Schiffes als Batch-Lauf: das Bewertungsmodell und der Wert jeder Epoche mit ihren Abzügen (beratend)
jammertest_import (catalog_json, plans, log_start_utc, location=None, local_offset_h=2.0, year=None) -> dict der veröffentlichte Jammertest-Katalog und -Plan als Ereignisse der geplanten Wahrheit (events_toml, events); geplante Slots, keine aufgezeichneten Sendezeiten
jammertest_score (session_toml, log, catalog_json, plans, location=None, local_offset_h=2.0, log_start_utc=None, year=None, recover_hold_s=10.0, guard_s=60.0) -> dict ein Empfänger-Log, bewertet gegen diesen Zeitplan: Latenz je Test, verpasst, Zeit bis zur Erholung, Fehlalarme (MODELLED; ein signiertes Paket braucht die Kommandozeile)
evidence_create (session_toml, log, from_s, to_s, title=None, created_utc=None, seed_hex=None) -> dict ein signiertes Nachweispaket für ein Fenster des Logs, im Speicher: files, public_key, seed_hex (privat halten); eine technische Aufzeichnung, keine Rechtsauffassung
evidence_verify (files, public_key=None, full_log=None, require_timestamp=False) -> dict ein Paket verifizieren: Hashes, Kette, Signatur, optional den vertrauenswürdigen Unterzeichner, das vollständige Log und einen Zeitstempel; verdict ist verified, intact-signer-not-pinned (kein öffentlicher Schlüssel angegeben: intakt, Unterzeichner nicht festgestellt) oder failed
export_sp3, export_omm, export_oem (toml) -> str die Artefakte --export-sp3/-omm/-oem der CLI als Text
export_formats (toml) -> list[dict] welche Interoperabilitätsformate für ein Szenario gelten, ohne es auszuführen
export_scenario (toml, format) -> dict czml, kml, geojson, stk oder sigmf im Speicher: {format, spec_url, files}, jede Datei {suffix, bytes, sha256, encoding, content} (utf-8-Text oder base64)
import_route (toml, geojson) -> str eine in ein Wegpunktkurs-Szenario geschriebene GeoJSON-Route (--import-route)
animate_scenario (toml, format="svg", fps=None, duration_s=None, width=None) -> dict die Zeitreihe des Laufs als animiertes SVG, HTML-Player oder bis zu 120 SVG-Bilder: {summary, files}
list_examples, get_example (kind=None) -> dict, (name) -> str die mitgelieferten Referenzszenarien und ihr TOML
evidence_attach_timestamp (files, token, replace=False) -> dict ein RFC-3161-Token (Bytes oder Base64) im Speicher an ein Paket binden: {files, notes}; das Paket muss weiterhin verifizieren; die Signatur der Autorität wird nicht geprüft
evidence_keygen () -> dict ein neuer Signaturschlüssel im Speicher: seed_hex (PRIVAT), public_key, fingerprint, warning; nur Python
iq_sweep (i, q, fs_hz, signal, prns, ..., pll_bws=None, dll_bws=None, spacings=None, coherents=None, design=None) -> dict eine Aufzeichnung über mehrere Schleifenentwürfe abspielen (iq sweep): je Entwurf und PRN Jitter im eingeschwungenen Zustand, Lock-Anteile und C/N0; eine Akquisition je PRN, jeder Kanal auf denselben Samples
iq_info, iq_inventory (path, hash=False) -> dict, (directory, recursive=False, hash=False) -> list eine Aufzeichnung oder jede Aufzeichnung in einem Ordner beschreiben (liest Dateien; hash liest sie vollständig)
bench_export (toml, epoch=None) -> dict die Fahrzeugbewegung und die Ereignisse eines Szenarios für einen GNSS-Laborsimulator, im Speicher: {files: {suffix: text}, notes, notice}; Arten gnss-ins, jamming, gnss-sim; es wird kein Signal geschrieben, behalten Sie notice bei den Dateien
compliance_report (runs) -> dict die Zuordnung zum öffentlichen Rahmenwerk, ausgefüllt aus Ergebnistexten: runs ist eine Liste von {label, result, scenario?}-Dicts (Text, höchstens 64); gibt {report, markdown} zurück; der status jeder Zeile besagt, dass die Läufe Belege für ihre Fähigkeiten liefern, nicht dass ein Rahmenwerk erfüllt ist; führen Sie report["statement"] bei jeder Anzeige mit
compliance_mapping (sources=False) -> str die statischen Zuordnungstabellen (oder die Quelldokumente) als Markdown, angeführt von der Aussage
standards_pack_list () -> dict die Standards-Packs (ID, Titel, Rahmenwerk, Testanzahlen) und ein Hinweis; ein Pack misst modellierte Szenarien an vor dem Lauf festgelegten Zielwerten
standards_pack_run (pack_id) -> dict ein Pack-Lauf: jeder Test MET, NOT MET oder NEEDS INPUT mit gemessenen und erwarteten Werten, plus der Bericht als Markdown unter markdown; löst ValueError bei einer unbekannten ID aus
lunanet_afs_check_spec () -> dict die LunaNet-AFS-Implementierung, geprüft gegen die gedruckten Tabellen und durchgerechneten Beispiele von LSIS-AFS V1.0 (Zielwerte B1 bis B10; B4 meldet eine festgehaltene Verfehlung)
lunanet_afs_check_symbols (symbols, max_sp_errors=0) -> dict ein AFS-Symbolstrom (Text aus 0 und 1), geprüft auf Synchronisationsmuster, SB1-Dekodierung, FID, TOI-Kontinuität und -Abstand; LDPC und CRC-24Q der Unterrahmen 2 bis 4 sind nicht verifiziert
lunanet_afs_generate (frames=1, toi0=0) -> str ein Test-Symbolstrom mit Platzhalter-Unterrahmen (keine Wellenform)
evidence_round_trip (scoring_toml, scenario_toml, conditions, log, from_s, to_s, title=None, created_utc=None, seed_hex=None) -> dict das signierte Labor-Round-Trip-Paket, das Szenario, Testbedingungen (docs/spec/TEST-CONDITIONS.md), Empfänger-Log und Bewertung per Hash verknüpft; als evidence_create
bench_score (truth_json, predictions_json, threshold=None) -> str eine Ergebnisdatei von kshana-bench (JSON-Text) aus einer Wahrheitsdatei und einer Vorhersagedatei; MODELLED
bench_leaderboard (results: list[str]) -> str Ergebnisdateien von kshana-bench, dargestellt als statische Bestenlisten-Seite (HTML)
osnma_verify (data, format="", start_gst=None, merkle_root_hex="", public_keys=None, reference_time=None, max_time_error=None) -> dict Galileo-OSNMA-Authentifizierung von I/NAV-Seiten oder eines UBX-Streams im Speicher: das Dict, das kshana osnma verify --json ausgibt, mit dem Hinweis in seinem Feld advisory; nur beratend, kein Dienst für Navigationsintegrität
sky_geometry (request) -> dict die Satelliten, die ein Standort unter einer azimutabhängigen Horizontlinie sieht: je Satellit visible / masked, GDOP, PDOP, HDOP, VDOP, TDOP, der Ost-Nord-Oben-Kofaktor und die Kovarianz sowie die horizontalen Fehlerellipsen; request ist JSON- oder TOML-Text oder ein Dict (site, time_s, systems, tle, satellites, mask_deg, skyline, clock, sigma_uere_m, confidence); die Sichtbarkeitsentscheidung und die Ellipse sind gegen unabhängige Bibliotheken geprüft, der Rest ist MODELLED, und das Ergebnis trägt den Hinweis (sky_source, sky_statement sagen, ob der Himmel repräsentativ ist oder aus Elementesätzen stammt)
sky_monte_carlo (request, seed=0, n=1000) -> dict n (1 bis 5000) Kleinste-Quadrate-Fehler mit Seed auf der sichtbaren Menge von request, mit ihrer empirischen Kovarianz, ihrem RMS und dem Anteil innerhalb der 95-%-Ellipse
skyline_presets () -> list[dict] die Horizontlinien-Presets (city-street, harbour-approach, fjord, container-terminal) mit ihrem Label REPRESENTATIVE, ihrer Herkunft und dem Schnitt für jedes Grad Azimut; repräsentative Geometrien, keine Vermessungen
skyline_profile (skyline) -> dict ein Horizontlinien-Abschnitt (Tabelle, Straßenschlucht, Sektoren, Gelände), reduziert auf die normalisierte Tabelle mit 360 Einträgen, die die Engine verwendet
skyplot_svg (request) -> str der Skyplot von request als statischer SVG-Text
trust_telemetry (input, format, host="", input_kind="jsonl", expose_position=False, syslog_all=False, unix_nano=0) -> str ein Vertrauens-Stream (jsonl) oder ein Ergebnis receiver-trust als Prometheus-Text, CEF- oder LEEF-Syslog-Zeilen oder OTLP-JSON-Nutzlast, mit den kshana trust-telemetry-Encodern; es wird nichts gesendet und keine Uhr gelesen (Syslog-Zeilen tragen keinen Zeitstempel)
interference_map (source, csv, dataset, cell_deg=None, licence=None, licence_url=None, attribution=None, land_geojson=None) -> list[dict] eine GNSS-Störungskarte aus ADS-B- oder AIS-CSV-Text: ein Dict je UTC-Tag mit kshana-interference-map/v1-GeoJSON (nur aggregiert; eine degradierte Zelle nennt keine Störung als Ursache)
interference_emitter_regions (source, csv, dataset, licence=None, licence_url=None, attribution=None, land_geojson=None) -> dict geschätzte Senderregionen aus ADS-B- oder AIS-CSV-Text: {stem, geojson, summary, csv, svg, sessions_published, sessions_withheld}, jede als MODELLED gekennzeichnet; Regionen bei genannter Konfidenz mit einem Schwerpunkt und einer Unsicherheitsellipse, nie ein bloßer Punkt; nur aggregiert, und eine Region ist nicht die Position von irgendjemandem und kein Befund der Ursache
route_exposure (route, maps, date_from=None, date_to=None) -> str Anteil einer Route durch degradierte Zellen dieser Karten, als JSON-Text (keine Vorhersage; nicht beobachtete Zellen sind kein Beleg für eine freie Route)
nmea_training (toml, seed=None) -> dict synthetisches Brücken-NMEA für die Besatzungsausbildung plus das Ausbilder-Log (nmea, log_json, log_text); nur Text, nie für die Live-Navigationssysteme eines Schiffes
iq_signals () -> list[str] die GNSS-IQ-Signalnamen, die iq_scene, iq_acquire und iq_track akzeptieren (gps-l1ca, galileo-e1b, glonass-l1of, ...)
iq_scene (fs_hz, duration_s, signal, prns, **options) -> dict eine GNSS-IQ-Szene mit mehreren Satelliten im Speicher: samples_i / samples_q und truth je Epoche
iq_scene_broadcast (fs_hz, window_s, nav_text, rx_lat, rx_lon, rx_alt, **options) -> dict dasselbe, mit jedem GPS-Satelliten in der Geometrie seiner Broadcast-Ephemeride aus einer RINEX-Navigationsnachricht (Receiver Independent Exchange Format)
iq_acquire (i, q, fs_hz, signal, prns, **options) -> list[dict] FFT-Akquisition (fast Fourier transform) jedes PRN (pseudorandom noise code): Doppler, Codephase, Statistik, Schwelle
iq_acq_surface (i, q, fs_hz, signal, prn, **options) -> dict die gesamte Akquisitionsfläche eines PRN (kshana.acq-surface/1): Korrelationsleistung rows[doppler][lag], der Peak und zwei Feinverfeinerungen des Dopplers (parabolic, fine_search)
iq_track (i, q, fs_hz, signal, prns, **options) -> dict akquirieren, dann jeden PRN nachführen: Doppler je Epoche, Codephase, Lock-Indikatoren, C/N0, Prompt-Korrelator
iq_frontend (i, q, fs_hz, **options) -> dict die Front-End-Kette des Empfängers (Bandpass, Notch, Blanking, Excision, AGC (automatic gain control), Quantisierer) über komplexe Samples
iq_labfit (toml: str) -> dict das Verlust-der-Nachführung-Modell der Nachführschleife an eine Zeitleiste des Empfängervertrauens anpassen (ein Szenario iq-labfit)
iq_loop_designs (toml) -> list[dict] eine Datei kshana.loop-design/1 (einen Pfad oder TOML-Text) in ihre aufgelösten Entwürfe parsen, jeder mit seinem name und hash; ValueError bei einer ungültigen Datei
iq_read_epochs (path) -> dict eine binäre Nachführ-Epochendatei lesen (kshana.track-epoch/1, wie kshana iq track --epochs sie schreibt): den header und ein Dict je Epoche in records
iq_monitor (path, signal=None, prns=None, power=False, spectral=False, settings=None, ...) -> dict die IQ-Detektionsmonitore über eine Aufzeichnung in einem Streaming-Durchlauf (iq monitor): series, events, spectra und notes; liest eine Datei
iq_test_conditions (conditions) -> dict eine Labor-Testbedingungsdatei validieren (kshana.test-conditions/1, TOML oder JSON, ein Pfad oder Text) und sie aufgelöst zurückgeben, mit ihrem hash
iq_campaign (campaign, out_dir, workers=0, resume=True, max_cells=None, dry_run=False) -> dict eine Lab-Replay-Kampagne (kshana.campaign/1) nach out_dir ausführen, wie es kshana iq campaign tut; abgeschlossene Zellen werden übersprungen; gibt die Zellanzahlen, Fehler und den digest zurück, sobald jede Zelle fertig ist
iq_campaign_report (out_dir) -> dict die Scorecards, den HTML-Bericht und den Digest einer Kampagne aus ihren Zellen neu aufbauen: die Zell- und Zeilenanzahlen, die Zeilen, die einen Zielwert verfehlen, und den digest

Signaturen für GNSS-IQ und Empfängervertrauen#

Die vollständigen Signaturen, wie kshana.pyi sie angibt (jedes Schlüsselwort nach den erforderlichen Argumenten hat einen Standardwert; die Docstrings im Stub geben jeweils die Bedeutung an). Umhüllen Sie die Listen samples_i / samples_q und die Eingaben i / q für Arrays mit numpy.asarray(...).

def receiver_trust(toml: str) -> RunOutput: ...

def receiver_trust_replay(session_toml: str, nmea: str | bytes) -> dict: ...
def assess_vessel_log(session_toml: str, log: str | bytes) -> dict: ...
def jammertest_import(catalog_json: str, plans: list[str], log_start_utc: str, location: int | None = None,
                      local_offset_h: float = 2.0, year: int | None = None) -> dict: ...
def jammertest_score(session_toml: str, log: str | bytes, catalog_json: str, plans: list[str],
                     location: int | None = None, local_offset_h: float = 2.0,
                     log_start_utc: str | None = None, year: int | None = None,
                     recover_hold_s: float = 10.0, guard_s: float = 60.0) -> dict: ...
def evidence_create(session_toml: str, log: str | bytes, from_s: float, to_s: float,
                    title: str | None = None, created_utc: str | None = None,
                    seed_hex: str | None = None) -> dict: ...
def evidence_verify(files: dict[str, str | bytes], public_key: str | None = None,
                    full_log: str | bytes | None = None,
                    require_timestamp: bool = False) -> dict: ...
def interference_map(source: str, csv: str, dataset: str, cell_deg: float | None = None,
                     licence: str | None = None, licence_url: str | None = None,
                     attribution: str | None = None, land_geojson: str | None = None) -> list[dict]: ...
def route_exposure(route: str, maps: list[str], date_from: str | None = None,
                   date_to: str | None = None) -> str: ...
def export_sp3(toml: str) -> str: ...
def export_omm(toml: str) -> str: ...
def export_oem(toml: str) -> str: ...
def export_formats(toml: str) -> list[dict]: ...
def export_scenario(toml: str, format: str) -> dict: ...
def import_route(toml: str, geojson: str) -> str: ...
def animate_scenario(toml: str, format: str = "svg", fps: int | None = None,
                     duration_s: float | None = None, width: int | None = None) -> dict: ...
def list_examples(kind: str | None = None) -> dict: ...
def get_example(name: str) -> str: ...
def evidence_attach_timestamp(files: dict[str, str | bytes], token: str | bytes,
                              replace: bool = False) -> dict: ...
def evidence_keygen() -> dict: ...
def iq_sweep(i: list[float], q: list[float], fs_hz: float, signal: str, prns: list[int],
             **options) -> dict: ...
def iq_info(path: str, hash: bool = False) -> dict: ...
def iq_inventory(directory: str, recursive: bool = False, hash: bool = False) -> list[dict]: ...
def bench_export(toml: str, epoch: str | None = None) -> dict: ...
def compliance_report(runs: list[dict[str, str]]) -> dict: ...
def compliance_mapping(sources: bool = False) -> str: ...
def standards_pack_list() -> dict[str, Any]: ...
def standards_pack_run(pack_id: str) -> dict[str, Any]: ...
def lunanet_afs_check_spec() -> dict[str, Any]: ...
def lunanet_afs_check_symbols(symbols: str, max_sp_errors: int = 0) -> dict[str, Any]: ...
def lunanet_afs_generate(frames: int = 1, toi0: int = 0) -> str: ...
def evidence_round_trip(scoring_toml: str, scenario_toml: str, conditions: str, log: str | bytes, from_s: float, to_s: float, title: Optional[str] = None, created_utc: Optional[str] = None, seed_hex: Optional[str] = None) -> dict[str, Any]: ...
def bench_score(truth_json: str, predictions_json: str, threshold: float | None = None) -> str: ...
def bench_leaderboard(results: list[str]) -> str: ...
def osnma_verify(data: bytes | str, format: str = "", start_gst: int | None = None,
                 merkle_root_hex: str = "", public_keys: list[str] | None = None,
                 reference_time: int | None = None, max_time_error: int | None = None) -> dict: ...
def sky_geometry(request: str | dict[str, Any]) -> dict[str, Any]: ...
def sky_monte_carlo(request: str | dict[str, Any], seed: int = 0, n: int = 1000) -> dict[str, Any]: ...
def skyline_presets() -> list[dict[str, Any]]: ...
def skyline_profile(skyline: str | dict[str, Any]) -> dict[str, Any]: ...
def skyplot_svg(request: str | dict[str, Any]) -> str: ...
def trust_telemetry(input: str, format: str, host: str = "", input_kind: str = "jsonl",
                    expose_position: bool = False, syslog_all: bool = False,
                    unix_nano: int = 0) -> str: ...
def nmea_training(toml: str, seed: int | None = None) -> dict[str, str]: ...

def iq_signals() -> list[str]: ...

def iq_scene(
    fs_hz: float,
    duration_s: float,
    signal: str,
    prns: list[int],
    dopplers: Optional[list[float]] = ...,
    cn0_dbhz: Optional[float] = ...,
    center_hz: Optional[float] = ...,
    if_hz: float = ...,
    noise: bool = ...,
    noise_figure_db: float = ...,
    seed: int = ...,
    data: bool = ...,
    threads: int = ...,
    iono_stec: Optional[float] = ...,
    iono_vtec: Optional[float] = ...,
    iono_klobuchar: bool = ...,
    tropo: bool = ...,
    tropo_doy: float = ...,
    s4: Optional[float] = ...,
    scint_tau0: float = ...,
    sigma_phi: float = ...,
    multipath_height: Optional[float] = ...,
    multipath_ground: str = ...,
    land_mobile: bool = ...,
    nlos: bool = ...,
) -> dict[str, Any]: ...

def iq_scene_broadcast(
    fs_hz: float,
    window_s: float,
    nav_text: str,
    rx_lat: float,
    rx_lon: float,
    rx_alt: float,
    prns: Optional[list[int]] = ...,
    start_tow: float = ...,
    cn0_dbhz: Optional[float] = ...,
    center_hz: Optional[float] = ...,
    if_hz: float = ...,
    noise: bool = ...,
    noise_figure_db: float = ...,
    seed: int = ...,
    mask_deg: float = ...,
    threads: int = ...,
) -> dict[str, Any]: ...

def iq_acquire(
    i: list[float],
    q: list[float],
    fs_hz: float,
    signal: str,
    prns: list[int],
    if_hz: float = ...,
    center_hz: Optional[float] = ...,
    coherent: int = ...,
    noncoherent: int = ...,
    doppler_max: float = ...,
    doppler_step: Optional[float] = ...,
    pfa: float = ...,
) -> list[dict[str, Any]]: ...

def iq_acq_surface(
    i: list[float],
    q: list[float],
    fs_hz: float,
    signal: str,
    prn: int,
    if_hz: float = ...,
    center_hz: Optional[float] = ...,
    coherent: int = ...,
    noncoherent: int = ...,
    doppler_max: float = ...,
    doppler_step: Optional[float] = ...,
    pfa: float = ...,
) -> dict[str, Any]: ...

def iq_track(
    i: list[float],
    q: list[float],
    fs_hz: float,
    signal: str,
    prns: list[int],
    if_hz: float = ...,
    center_hz: Optional[float] = ...,
    pll_bw: Optional[float] = ...,
    fll_bw: Optional[float] = ...,
    dll_bw: Optional[float] = ...,
    spacing: Optional[float] = ...,
    coherent: Optional[int] = ...,
    periods_per_bit: Optional[int] = ...,
    acq_coherent: Optional[int] = ...,
    acq_noncoherent: int = ...,
    doppler_max: float = ...,
    max_seconds: Optional[float] = ...,
) -> dict[str, Any]: ...

def iq_frontend(
    i: list[float],
    q: list[float],
    fs_hz: float,
    bandpass_lo: Optional[float] = ...,
    bandpass_hi: Optional[float] = ...,
    bandpass_transition: Optional[float] = ...,
    bandpass_atten: float = ...,
    notch: bool = ...,
    notch_r: float = ...,
    notch_mu: float = ...,
    blank: Optional[float] = ...,
    blank_hold: int = ...,
    excise: bool = ...,
    excise_fft: int = ...,
    excise_pfa: float = ...,
    agc: bool = ...,
    agc_tau: float = ...,
    bits: Optional[int] = ...,
    quant_step: Optional[float] = ...,
    no_agc: bool = ...,
) -> dict[str, Any]: ...

def iq_labfit(toml: str) -> dict[str, Any]: ...
def iq_loop_designs(toml: str) -> list[dict[str, Any]]: ...
def iq_read_epochs(path: str) -> dict[str, Any]: ...
def iq_monitor(path: str, signal: Optional[str] = ..., prns: Optional[list[int]] = ...,
               power: bool = ..., spectral: bool = ..., settings: Optional[str] = ...,
               **options) -> dict[str, Any]: ...
def iq_test_conditions(conditions: str) -> dict[str, Any]: ...
def iq_campaign(campaign: str, out_dir: str, workers: int = 0, resume: bool = True,
                max_cells: Optional[int] = None, dry_run: bool = False) -> dict[str, Any]: ...
def iq_campaign_report(out_dir: str) -> dict[str, Any]: ...

Eine Lab-Replay-Kampagne aus Python, dann ihr Bericht (die Kampagnendatei und ihre Aufzeichnungen sind Ihre; eine abgeschlossene Zelle wird beim nächsten Aufruf übersprungen; iq_read_epochs liest eine Nachführ-Epochendatei, die ein Lauf von kshana iq track --epochs geschrieben hat):

import kshana

summary = kshana.iq_campaign("lab.campaign.toml", "campaign-out", workers=4)
report = kshana.iq_campaign_report("campaign-out")
print(report["digest"])          # None until every cell is done

acq_coherent von iq_track legt fest, über wie viele Codeperioden die Übergabe-Akquisition kohärent integriert. Ab 0.33.0 ist der Standardwert None, also automatisch: etwa 4 ms (4 Perioden bei einem Code von 1 ms wie GPS L1 C/A, 1 bei einem Code von 4 ms oder länger), sodass der Kanal nahe genug startet, damit die Frequenzschleife einrasten kann; acq_coherent=1 behält die Ein-Perioden-Suche von 0,32 bei.

Typen#

kshana.pyi typisiert die geschlossenen Vokabulare für Prüfprogramme (mypy, pyright): ScenarioKind (jeder Artname, ein Literal), ErrorKind (die vier Tags, die error_kind zurückgibt), ProvenanceClass und die TypedDicts KindMeta (wovon scenario_kinds() eine Liste zurückgibt) und FieldUnit (ein Eintrag im Block units eines Ergebnisses, der die Basis _FieldUnitBase mit den Pflichtschlüsseln erweitert). Sie existieren nur für Typprüfer und sind zur Laufzeit nicht importierbar; tests/typed_api_sync.rs hält sie gleich mit den Listen der Engine.

from typing import TYPE_CHECKING
import kshana
if TYPE_CHECKING:
    from kshana import ScenarioKind

names: "list[ScenarioKind]" = [k["name"] for k in kshana.scenario_kinds()]

RunOutput#

Mitglied Typ Hinweise
.json str vollständiges Ergebnisdokument (JSON)
.svg str eigenständiges Diagramm-SVG (Scalable Vector Graphics)
.summary str einzeilige Zusammenfassung für Menschen
.csv str | None die Reproduzierbarkeitstabelle, für die Arten, die eine ausgeben (siehe unten)
.data() dict das in ein Python-Dict geparste Ergebnis (siehe den Hinweis zur Form unten)
.array(path) numpy.ndarray die numerische Liste bei path (gepunktet, "points.0.coords", oder ein JSON-Pointer, "/points/0/coords"): 1D für Zahlen, 2D für numerische Listen gleicher Länge
.columns(path) dict[str, numpy.ndarray] die Liste von Datensätzen bei path (eine Zeitreihe), ein Array je Feld, das in jedem Datensatz eine Zahl ist
.series() dict[str, dict[str, numpy.ndarray]] jede Liste von Datensätzen mit einem numerischen Feld, nach gepunktetem Pfad geschlüsselt, jede als .columns
.write_csv(path) int diese Tabelle nach path schreiben; gibt die geschriebenen Bytes zurück, oder 0 (und schreibt nichts), wenn die Art keine Tabelle ausgibt

Die Reproduzierbarkeitstabelle#

realtime-frame-eop, lunar-time-budget, lunar-jamming, telecom-timing und leo-navmsg veröffentlichen immer eine Tabelle; moonlight-service-volume veröffentlicht eine, wenn ein Exportstandort (export_site_lat_deg + export_site_lon_deg) konfiguriert ist. Jede andere Art gibt csv = None zurück. Der Text hat dieselben Bytes, die die CLI (command-line interface) als <scenario>.table.csv schreibt, sodass ein Prüfer, der eine veröffentlichte Tabelle aus dem Wheel reproduziert, nie auf die Kommandozeile wechseln muss:

import kshana

out = kshana.run_typed(open("scenarios/realtime-frame-eop.toml").read())
if out.csv is not None:
    print(out.write_csv("table.csv"), "bytes written")

Form des Ergebnisses#

Die Gütemaße und die Zeitreihen liegen je Lauf-Seite, nicht auf oberster Ebene. Für einen Uhrenlauf lautet das Dokument:

schema_version  engine_version  scenario_hash  seed  threshold_ns  units  figure_tiers
quantum   → spec · series · fom · adev_curve · filter_health
classical → spec · series · fom · adev_curve · filter_health

die Gütemaße sind also data["quantum"]["fom"], nie data["figures_of_merit"]. Andere Arten geben ihre eigenen Packs aus; die vollständige Referenz je Feld, mit Einheiten und einem Quellverweis, ist field-units-schema.json, und der Leitfaden für Leser ist SCHEMA.md.

Hinweise#

  • validate_toml und error_kind führen das Szenario aus, sodass sie Parse-, Konfigurations- und Laufzeitfehler sichtbar machen. Sie lösen nie eine Ausnahme aus.
  • run / run_typed lösen bei einem ungültigen Szenario ValueError aus.
  • Ergebnisse sind reproduzierbar: Ein Szenario trägt seinen seed, und die Engine erfasst einen scenario_hash, sodass dieselbe Eingabe auf derselben Plattform byte-identische Ausgabe liefert (siehe REPRODUCIBILITY.md).
  • .array, .columns und .series geben genau numpy.asarray(...) derselben Werte zurück, die .data() liefert (gleicher dtype, bit-identisch; tests/python/test_numpy_runoutput.py). Sie importieren NumPy beim Aufruf und lösen ohne es ImportError aus; NumPy bleibt aus den Laufzeitanforderungen des Pakets heraus. KeyError bedeutet, dass der Pfad fehlt, ValueError, dass der Wert dort kein numerisches Array ist (oder keine Liste von Datensätzen). Lauffähige Notebooks stehen in notebooks/.

Nicht in Python: langlaufende Prozesse#

kshana receiver-trust live (ein Stream-Prozess mit einem Gate und einem optionalen TCP-Server --listen) und die Telemetrie-Exporter (Prometheus, OTLP, Syslog; docs/TRUST-TELEMETRY.md) sowie das Streaming von kshana nmea-scenario --tcp/--udp gibt es nur auf der Kommandozeile: Ein Binding kehrt zurück, wenn der Aufruf zurückkehrt, und hält keinen Socket offen. Python deckt die Batch-Form von jedem ab: receiver_trust für ein Log, receiver_trust_replay für einen Stream-Auszug (Werte und Zustände; das Gate wird nicht angewendet), nmea_training für den erzeugten Text.