Traduction automatique, non relue par un locuteur natif. L'anglais fait foi.

API et intégrationsModifier sur GitHubSource : docs/PYTHON_API.md

API Python

Kshana livre une interface de programmation d'application (API) Python de premier plan, construite avec PyO3 et maturin. Ses wheels abi3 sont construits sur l'interface binaire d'application (ABI) stable de Python, de sorte qu'un seul wheel par plateforme fonctionne avec CPython ≥ 3,9 ; les wheels couvrent Linux, macOS et Windows, chacun en x86-64 et en ARM 64 bits (voir WHEEL_TAGS.md). Un stub de types fourni (kshana.pyi + py.typed) donne aux éditeurs et à mypy/pyright toute l'information de typage.

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

Démarrage rapide#

Exécutez ces extraits depuis la racine d'une copie du dépôt : ils lisent des fichiers de scénario sous scenarios/. La ligne NumPy nécessite 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

Surface#

Symbole Signature Renvoie
run_typed (toml: str) -> RunOutput résultat typé (.json, .svg, .summary, .csv, .data(), .array(), .columns(), .series(), .write_csv())
run (toml: str) -> str document de résultat sous forme de chaîne JSON (JavaScript Object Notation)
run_full (toml: str) -> tuple[str, str, str] (json, svg, summary)
scenario_kinds () -> list[dict] types de scénario disponibles + métadonnées (analysées)
list_kinds () -> str les mêmes métadonnées sous forme d'UNE chaîne de tableau JSON, et non d'une liste (conservée pour les appelants existants ; utilisez scenario_kinds pour la liste analysée)
validate_toml (toml: str) -> list[str] messages d'erreur (vide si valide)
error_kind (toml: str) -> str | None étiquette de catégorie d'échec (invalid_input, non_convergence, unsupported ou io_error), ou None en cas de succès
version / __version__ () -> str / str version du moteur
receiver_trust (toml: str) -> RunOutput évaluer un véritable journal de récepteur décrit par un scénario receiver-trust : document de résultat, CSV de confiance par époque, graphique et synthèse ; une table [platform] kind = "vessel" ajoute les moniteurs maritimes et le score de confiance de 0 à 100 avec ses motifs (à titre consultatif)
receiver_trust_replay (session_toml, nmea) -> dict un extrait NMEA borné évalué comme le mode en direct l'évalue : état par époque, score de 0 à 100 et motifs, une synthèse (ni socket ni passerelle ; à titre consultatif)
assess_vessel_log (session_toml, log) -> dict un journal NMEA de navire en exécution par lot : le modèle de score et le score de chaque époque avec ses déductions (à titre consultatif)
jammertest_import (catalog_json, plans, log_start_utc, location=None, local_offset_h=2.0, year=None) -> dict le catalogue et le plan Jammertest publiés sous forme d'événements de vérité planifiée (events_toml, events) ; créneaux prévus, et non heures d'émission réellement enregistrées
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 un journal de récepteur évalué par rapport à ce calendrier : latence par essai, manqués, temps de récupération, fausses alarmes (MODELLED ; un paquet signé nécessite la ligne de commande)
evidence_create (session_toml, log, from_s, to_s, title=None, created_utc=None, seed_hex=None) -> dict un paquet de preuves signé pour une fenêtre du journal, en mémoire : files, public_key, seed_hex (à garder privé) ; un dossier technique, non un avis juridique
evidence_verify (files, public_key=None, full_log=None, require_timestamp=False) -> dict vérifier un paquet : hachages, chaîne, signature, éventuellement le signataire de confiance, le journal complet et un horodatage ; verdict vaut verified, intact-signer-not-pinned (aucune clé publique fournie : intact, signataire non établi) ou failed
export_sp3, export_omm, export_oem (toml) -> str les artefacts --export-sp3/-omm/-oem de la CLI sous forme de texte
export_formats (toml) -> list[dict] quels formats d'interopérabilité s'appliquent à un scénario, sans l'exécuter
export_scenario (toml, format) -> dict czml, kml, geojson, stk ou sigmf en mémoire : {format, spec_url, files}, chaque fichier {suffix, bytes, sha256, encoding, content} (texte utf-8 ou base64)
import_route (toml, geojson) -> str un itinéraire GeoJSON écrit dans un scénario de trajectoire à points de passage (--import-route)
animate_scenario (toml, format="svg", fps=None, duration_s=None, width=None) -> dict les séries temporelles de l'exécution sous forme de SVG animé, de lecteur HTML ou d'un maximum de 120 images SVG : {summary, files}
list_examples, get_example (kind=None) -> dict, (name) -> str les scénarios de référence fournis et leur TOML
evidence_attach_timestamp (files, token, replace=False) -> dict lier un jeton RFC 3161 (octets ou base64) à un paquet en mémoire : {files, notes} ; le paquet doit toujours se vérifier ; la signature de l'autorité n'est pas contrôlée
evidence_keygen () -> dict une nouvelle clé de signature en mémoire : seed_hex (PRIVÉE), public_key, fingerprint, warning ; Python uniquement
iq_sweep (i, q, fs_hz, signal, prns, ..., pll_bws=None, dll_bws=None, spacings=None, coherents=None, design=None) -> dict rejouer un enregistrement sur plusieurs conceptions de boucle (iq sweep) : par conception et par PRN, gigue en régime permanent, fractions de verrouillage et C/N0 ; une acquisition par PRN, chaque canal sur les mêmes échantillons
iq_info, iq_inventory (path, hash=False) -> dict, (directory, recursive=False, hash=False) -> list décrire un enregistrement, ou chaque enregistrement d'un dossier (lit les fichiers ; hash les lit en entier)
bench_export (toml, epoch=None) -> dict le mouvement du véhicule et les événements d'un scénario pour un simulateur GNSS de laboratoire, en mémoire : {files: {suffix: text}, notes, notice} ; types de scénario gnss-ins, jamming, gnss-sim ; aucun signal n'est écrit, gardez notice avec les fichiers
compliance_report (runs) -> dict le rapprochement avec les cadres publics rempli à partir de textes de résultats : runs est une liste de dictionnaires {label, result, scenario?} (texte, au plus 64) ; renvoie {report, markdown} ; le status de chaque ligne indique que les exécutions apportent des éléments de preuve en faveur de ses capacités, non qu'un cadre est atteint ; conservez report["statement"] avec tout affichage
compliance_mapping (sources=False) -> str les tables de rapprochement statiques (ou les documents sources) en Markdown, ouvertes par la déclaration
standards_pack_list () -> dict les paquets de normes (identifiant, titre, cadre, nombre de tests) et un avis ; un paquet mesure des scénarios modélisés par rapport à des seuils énoncés avant l'exécution
standards_pack_run (pack_id) -> dict une exécution de paquet : chaque test MET, NOT MET ou NEEDS INPUT avec les valeurs mesurées et attendues, plus le rapport en Markdown sous markdown ; lève ValueError pour un identifiant inconnu
lunanet_afs_check_spec () -> dict l'implémentation LunaNet AFS vérifiée par rapport aux tables imprimées et aux exemples résolus de LSIS-AFS V1.0 (seuils B1 à B10 ; B4 rapporte un échec consigné)
lunanet_afs_check_symbols (symbols, max_sp_errors=0) -> dict un flux de symboles AFS (texte de 0 et de 1) contrôlé pour le motif de synchronisation, le décodage SB1, le FID, la continuité et l'espacement du TOI ; le LDPC et le CRC-24Q des sous-trames 2 à 4 ne sont pas vérifiés
lunanet_afs_generate (frames=1, toi0=0) -> str un flux de symboles d'essai avec des sous-trames fictives (pas une forme d'onde)
evidence_round_trip (scoring_toml, scenario_toml, conditions, log, from_s, to_s, title=None, created_utc=None, seed_hex=None) -> dict le paquet signé d'aller-retour de laboratoire reliant par hachage le scénario, les conditions d'essai (docs/spec/TEST-CONDITIONS.md), le journal du récepteur et le score ; sous la forme evidence_create
bench_score (truth_json, predictions_json, threshold=None) -> str un fichier de résultat kshana-bench (texte JSON) à partir d'un fichier de vérité et d'un fichier de prédictions ; MODELLED
bench_leaderboard (results: list[str]) -> str des fichiers de résultat kshana-bench rendus sous forme de page de classement statique (HTML)
osnma_verify (data, format="", start_gst=None, merkle_root_hex="", public_keys=None, reference_time=None, max_time_error=None) -> dict authentification OSNMA de Galileo de pages I/NAV ou d'un flux UBX en mémoire : le dictionnaire que kshana osnma verify --json affiche, avec la mention à titre consultatif dans son champ advisory ; à titre consultatif seulement, pas un service d'intégrité de la navigation
sky_geometry (request) -> dict les satellites qu'un site voit sous un horizon dépendant de l'azimut : par satellite visible / masked, GDOP, PDOP, HDOP, VDOP, TDOP, le cofacteur et la covariance est-nord-haut et les ellipses d'erreur horizontale ; request est un texte JSON ou TOML ou un dictionnaire (site, time_s, systems, tle, satellites, mask_deg, skyline, clock, sigma_uere_m, confidence) ; la décision de visibilité et l'ellipse sont vérifiées par rapport à des bibliothèques indépendantes, le reste est MODELLED, et le résultat porte la mention à titre consultatif (sky_source, sky_statement disent si le ciel est représentatif ou issu de jeux d'éléments)
sky_monte_carlo (request, seed=0, n=1000) -> dict n (1 à 5000) erreurs de moindres carrés à graine fixée sur l'ensemble visible de request, avec leur covariance empirique, leur RMS et la fraction à l'intérieur de l'ellipse à 95 %
skyline_presets () -> list[dict] les préréglages d'horizon (city-street, harbour-approach, fjord, container-terminal) avec leur étiquette REPRESENTATIVE, leur provenance et la coupure à chaque degré d'azimut ; des géométries représentatives, non des relevés
skyline_profile (skyline) -> dict une section d'horizon (table, canyon urbain, secteurs, terrain) ramenée à la table normalisée de 360 entrées qu'utilise le moteur
skyplot_svg (request) -> str le diagramme du ciel de request sous forme de texte SVG statique
trust_telemetry (input, format, host="", input_kind="jsonl", expose_position=False, syslog_all=False, unix_nano=0) -> str un flux de confiance (jsonl) ou un résultat receiver-trust sous forme de texte Prometheus, de lignes syslog CEF ou LEEF ou de charge utile JSON OTLP, avec les encodeurs kshana trust-telemetry ; rien n'est envoyé et aucune horloge n'est lue (les lignes syslog ne portent pas d'horodatage)
interference_map (source, csv, dataset, cell_deg=None, licence=None, licence_url=None, attribution=None, land_geojson=None) -> list[dict] une carte d'interférences GNSS à partir de texte CSV ADS-B ou AIS : un dictionnaire par jour UTC avec du GeoJSON kshana-interference-map/v1 (agrégat uniquement ; une cellule dégradée ne désigne pas l'interférence comme cause)
interference_emitter_regions (source, csv, dataset, licence=None, licence_url=None, attribution=None, land_geojson=None) -> dict régions d'émetteurs estimées à partir de texte CSV ADS-B ou AIS : {stem, geojson, summary, csv, svg, sessions_published, sessions_withheld}, chacune étiquetée MODELLED ; des régions à un niveau de confiance déclaré avec un centroïde et une ellipse d'incertitude, jamais un simple point ; agrégat seulement, et une région n'est la position de personne ni un constat de la cause
route_exposure (route, maps, date_from=None, date_to=None) -> str part d'un itinéraire traversant des cellules dégradées de ces cartes, en texte JSON (pas une prévision ; des cellules non observées ne prouvent pas qu'un itinéraire est dégagé)
nmea_training (toml, seed=None) -> dict NMEA de passerelle synthétiques pour la formation des équipages plus le journal de l'instructeur (nmea, log_json, log_text) ; texte seulement, jamais pour les systèmes de navigation réels d'un navire
iq_signals () -> list[str] les noms de signaux IQ GNSS qu'acceptent iq_scene, iq_acquire et iq_track (gps-l1ca, galileo-e1b, glonass-l1of, ...)
iq_scene (fs_hz, duration_s, signal, prns, **options) -> dict une scène IQ GNSS multi-satellites en mémoire : samples_i / samples_q et truth par époque
iq_scene_broadcast (fs_hz, window_s, nav_text, rx_lat, rx_lon, rx_alt, **options) -> dict la même, avec chaque satellite GPS selon sa géométrie d'éphéméride diffusée tirée d'un message de navigation RINEX (Receiver Independent Exchange Format)
iq_acquire (i, q, fs_hz, signal, prns, **options) -> list[dict] acquisition par FFT (transformée de Fourier rapide) de chaque PRN (code pseudo-aléatoire) : Doppler, phase de code, statistique, seuil
iq_acq_surface (i, q, fs_hz, signal, prn, **options) -> dict toute la surface d'acquisition d'un PRN (kshana.acq-surface/1) : puissance de corrélation rows[doppler][lag], le pic et deux affinements fins du Doppler (parabolic, fine_search)
iq_track (i, q, fs_hz, signal, prns, **options) -> dict acquérir, puis suivre chaque PRN : Doppler par époque, phase de code, indicateurs de verrouillage, C/N0, corrélateur ponctuel
iq_frontend (i, q, fs_hz, **options) -> dict la chaîne frontale du récepteur (passe-bande, réjecteur, blanking, excision, AGC (commande automatique de gain), quantificateur) sur des échantillons complexes
iq_labfit (toml: str) -> dict ajuster le modèle de perte de verrouillage de la boucle de poursuite à une chronologie de confiance du récepteur (un scénario iq-labfit)
iq_loop_designs (toml) -> list[dict] analyser un fichier kshana.loop-design/1 (un chemin ou du texte TOML) en ses conceptions résolues, chacune avec son name et son hash ; ValueError sur un fichier invalide
iq_read_epochs (path) -> dict lire un fichier binaire d'époques de poursuite (kshana.track-epoch/1, tel que l'écrit kshana iq track --epochs) : le header et un dictionnaire par époque dans records
iq_monitor (path, signal=None, prns=None, power=False, spectral=False, settings=None, ...) -> dict les moniteurs de détection IQ sur un enregistrement en un seul passage en flux (iq monitor) : series, events, spectra et notes ; lit un fichier
iq_test_conditions (conditions) -> dict valider un fichier de conditions d'essai de laboratoire (kshana.test-conditions/1, TOML ou JSON, un chemin ou du texte) et le renvoyer résolu, avec son hash
iq_campaign (campaign, out_dir, workers=0, resume=True, max_cells=None, dry_run=False) -> dict exécuter une campagne de rejeu de laboratoire (kshana.campaign/1) dans out_dir comme le fait kshana iq campaign ; les cellules terminées sont ignorées ; renvoie le nombre de cellules, les échecs et le digest une fois toutes les cellules terminées
iq_campaign_report (out_dir) -> dict reconstruire les fiches de score, le rapport HTML et le condensé d'une campagne à partir de ses cellules : le nombre de cellules et de lignes, les lignes qui échouent à un seuil et le digest

Signatures de l'IQ GNSS et de la confiance du récepteur#

Les signatures complètes, telles que kshana.pyi les énonce (chaque mot-clé après les arguments obligatoires a une valeur par défaut ; les docstrings du stub donnent le sens de chacun). Encapsulez les listes samples_i / samples_q et les entrées i / q avec numpy.asarray(...) pour obtenir des tableaux.

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]: ...

Une campagne de rejeu de laboratoire depuis Python, puis son rapport (le fichier de campagne et ses enregistrements sont les vôtres ; une cellule terminée est ignorée à l'appel suivant ; iq_read_epochs lit un fichier d'époques de poursuite écrit par une exécution de kshana iq track --epochs) :

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

Le acq_coherent de iq_track fixe le nombre de périodes de code que l'acquisition de transfert intègre de façon cohérente. À partir de 0.33.0, il vaut par défaut None, ce qui signifie automatique : environ 4 ms (4 périodes pour un code de 1 ms comme le GPS L1 C/A, 1 pour un code de 4 ms ou plus), de sorte que le canal démarre assez près pour que la boucle de fréquence s'accroche ; acq_coherent=1 conserve la recherche à une période de 0,32.

Types#

kshana.pyi type les vocabulaires fermés pour les vérificateurs (mypy, pyright) : ScenarioKind (chaque nom de type de scénario, un Literal), ErrorKind (les quatre étiquettes que renvoie error_kind), ProvenanceClass, et les TypedDict KindMeta (dont scenario_kinds() renvoie une liste) et FieldUnit (une entrée du bloc units d'un résultat, qui étend la base de clés obligatoires _FieldUnitBase). Ils n'existent que pour les vérificateurs de types et ne sont pas importables à l'exécution ; tests/typed_api_sync.rs les maintient égaux aux listes du moteur.

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#

Membre Type Notes
.json str document de résultat complet (JSON)
.svg str SVG (Scalable Vector Graphics) autonome du graphique
.summary str résumé lisible d'une ligne
.csv str | None la table de reproductibilité, pour les types de scénario qui en émettent une (voir ci-dessous)
.data() dict le résultat analysé en dictionnaire Python (voir la note sur la forme ci-dessous)
.array(path) numpy.ndarray la liste numérique à path (pointée, "points.0.coords", ou pointeur JSON, "/points/0/coords") : 1D pour des nombres, 2D pour des listes numériques de même longueur
.columns(path) dict[str, numpy.ndarray] la liste d'enregistrements à path (une série temporelle), un tableau par champ qui est un nombre dans chaque enregistrement
.series() dict[str, dict[str, numpy.ndarray]] chaque liste d'enregistrements avec un champ numérique, indexée par chemin pointé, chacune sous la forme .columns
.write_csv(path) int écrire cette table dans path ; renvoie le nombre d'octets écrits, ou 0 (et n'écrit rien) lorsque le type de scénario n'émet aucune table

La table de reproductibilité#

realtime-frame-eop, lunar-time-budget, lunar-jamming, telecom-timing et leo-navmsg publient toujours une table ; moonlight-service-volume en publie une lorsqu'un site d'export (export_site_lat_deg + export_site_lon_deg) est configuré. Tout autre type de scénario renvoie csv = None. Le texte est constitué des mêmes octets que ceux que la CLI (interface en ligne de commande) écrit sous <scenario>.table.csv, de sorte qu'un relecteur qui reproduit une table publiée à partir du wheel n'a jamais à passer à la ligne de commande :

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")

Forme du résultat#

Les indicateurs de performance et les séries temporelles se trouvent par côté d'exécution, et non au niveau supérieur. Pour une exécution d'horloge, le document est :

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

de sorte que les indicateurs de performance sont data["quantum"]["fom"], jamais data["figures_of_merit"]. D'autres types de scénario émettent leurs propres paquets ; la référence complète champ par champ, avec unités et pointeur vers la source, est field-units-schema.json et le guide du lecteur est SCHEMA.md.

Notes#

  • validate_toml et error_kind exécutent le scénario, de sorte qu'ils font remonter les erreurs d'analyse, de configuration et d'exécution. Ils ne lèvent jamais d'exception.
  • run / run_typed lèvent ValueError sur un scénario invalide.
  • Les résultats sont reproductibles : un scénario porte sa seed et le moteur enregistre un scenario_hash, de sorte que la même entrée donne une sortie identique octet pour octet sur la même plateforme (voir REPRODUCIBILITY.md).
  • .array, .columns et .series renvoient exactement numpy.asarray(...) des mêmes valeurs que donne .data() (même dtype, identiques au bit près ; tests/python/test_numpy_runoutput.py). Ils importent NumPy lorsqu'on les appelle et lèvent ImportError sans lui ; NumPy reste en dehors des dépendances d'exécution du paquet. KeyError signifie que le chemin est absent, ValueError que la valeur qui s'y trouve n'est pas un tableau numérique (ou pas une liste d'enregistrements). Des notebooks exécutables se trouvent dans notebooks/.

Pas en Python : les processus de longue durée#

kshana receiver-trust live (un processus de flux avec une passerelle et un serveur TCP --listen facultatif) et les exportateurs de télémétrie (Prometheus, OTLP, syslog ; docs/TRUST-TELEMETRY.md) et le flux kshana nmea-scenario --tcp/--udp relèvent uniquement de la ligne de commande : une liaison rend la main quand l'appel se termine et ne garde pas de socket ouvert. Python couvre la forme par lot de chacun : receiver_trust pour un journal, receiver_trust_replay pour un extrait de flux (scores et états ; la passerelle n'est pas appliquée), nmea_training pour le texte généré.