Skip to main content

Voyant API - Python Bindings

Python bindings for Voyant Photonics LiDAR sensors, providing high-performance access to point cloud data.

Installation

pip install voyant-api

Sensor compatibility

Sensor Client
Carbon CarbonClient + CarbonConfig

Meadowlark support ended in v1.0.0. The deprecated VoyantClient has been removed — Carbon users use CarbonClient (above). If you still run a Meadowlark sensor, pin voyant-api < 1.0.0.

Breaking changes in v1.0.0

v1.0.0 moves to a new recording format and reworks the frame API around it. Code written against 0.x needs the following changes.

points() returns different columns. It was a (N, 7) float32 array of [x, y, z, radial_vel, snr_linear, nanosecs_since_frame, drop_reason]. It is now a (N, 12) float64 array with one column per recorded field, in the order they are stored — beginning [range_m, azimuth_rad, elevation_rad, ...]. Slicing points()[:, :3] for positions now returns spherical coordinates, not x/y/z, and will not raise. Either pass cartesian=True to get [x, y, z] in those three slots, or use xyz(). Index columns by name via VoyantFrame.points_columns() rather than by position.

Removed frame accessors. spherical(), spherical_v(), points_extended() and special_test() are gone; every field they exposed is a points() column. xyz(), xyzv() and their valid_* forms are unchanged. The deprecated voyant_api.utils shim is also removed — import from voyant_api.pandas_utils / voyant_api.pcd_utils directly.

Recorder buffer knob removed. VoyantRecorder no longer takes buffer_size_mb — the write buffer sizes itself. (The C++ bufferSizeMb field and the voyant_logger_binary --buffer-size-mb flag are gone too.)

Recordings must be converted. The bindings read only the native .vynt format. VoyantPlayback.open() raises IOError on a pre-v1.0.0 recording, naming the command that converts it:

voyant_recording_migrate --input drive_01.bin   # writes drive_01.vynt alongside the input

The pre-v1.0.0 format stored no sensor state, so converted frames report carries_state == False and return None from sensor_state() / host_state(). Their points, device identity and timestamps are real.

Pre-v1.0.0 tools cannot read v1.0.0 recordings. Upgrade readers and writers together.

Quick Start

Receiving live data (Carbon)

import time
from voyant_api import CarbonClient, CarbonConfig, init_voyant_logging

init_voyant_logging()

config = CarbonConfig()
config.set_bind_addr("0.0.0.0:5678")
config.set_group_addr("239.255.48.84")
config.set_interface_addr("192.168.1.100")

client = CarbonClient(config)
client.start()

# Press Ctrl+C to stop
while client.is_running():
    frame = client.try_receive_frame()
    if frame is not None:
        print(frame)

        # Get point cloud as numpy array (N x 4: x, y, z, doppler_mps)
        xyzv = frame.xyzv()
        print(f"Points shape: {xyzv.shape}")
    else:
        time.sleep(0.001)

Config can also be loaded from a JSON file — see CarbonConfig JSON format below.

Recording data

import time
from voyant_api import CarbonClient, CarbonConfig, VoyantRecorder, RecordStatus, init_voyant_logging

init_voyant_logging()

config = CarbonConfig()
config.set_bind_addr("0.0.0.0:5678")
config.set_group_addr("239.255.48.84")
config.set_interface_addr("192.168.1.100")

client = CarbonClient(config)
client.start()

with VoyantRecorder(
    output_path="my_recording.vynt",
    timestamp_filename=True,
    max_total_frames=1000,  # Optional: stop after 1000 frames
) as recorder:
    while client.is_running():
        frame = client.try_receive_frame()
        if frame is not None:
            status = recorder.record_frame(frame)
            if status == RecordStatus.STOP:
                break
        else:
            time.sleep(0.001)

Playing back recordings

from voyant_api import VoyantPlayback, init_voyant_logging
from voyant_api.pandas_utils import frame_to_dataframe

init_voyant_logging()

with VoyantPlayback() as playback:
    playback.open("my_recording.vynt")

    for frame in playback:
        if frame is None:
            break

        print(frame)

        # Convert to pandas DataFrame
        df = frame_to_dataframe(frame)
        print(df.head())

Editing frames

frame.with_points(matrix) builds a new frame from an edited points() matrix, keeping everything else — state snapshots, timestamps, frame index, device identity — from the frame it came from, so the result records exactly like the original. It works on any frame, live from a CarbonClient or replayed from a file. The default (spherical) matrix is stored bit-exactly; untouched rows survive the round trip unchanged.

Editing a recording:

from voyant_api import VoyantFrame, VoyantPlayback, VoyantRecorder, init_voyant_logging

init_voyant_logging()
cols = VoyantFrame.points_columns()

# Invalid returns are dropped as the frames are read, so the output holds only
# valid points. Pass keep_invalid_points=True to carry them through as well.
with VoyantPlayback() as playback, VoyantRecorder(
    "edited.vynt", timestamp_filename=False
) as recorder:
    playback.open("my_recording.vynt")
    for frame in playback:
        if frame is None:
            break
        matrix = frame.points()
        matrix = matrix[matrix[:, cols.index("range_m")] <= 50.0]  # any numpy edit
        recorder.record_frame(frame.with_points(matrix))

The same flow processes a live stream as it records — here keeping only valid, near points to cut file size. Any edit works, e.g. stamping per-point results from a live perception pipeline into the user_data column:

# Continues the live-streaming example above (client, time and cols already set up).
with VoyantRecorder("filtered.vynt") as recorder:
    while client.is_running():
        frame = client.try_receive_frame()
        if frame is None:
            time.sleep(0.001)
            continue
        matrix = frame.valid_points()
        matrix = matrix[matrix[:, cols.index("range_m")] <= 50.0]
        recorder.record_frame(frame.with_points(matrix))

Pass the same cartesian flag you pass to points() — cartesian geometry is converted back to the stored spherical form (~1e-5 accuracy), and a basis mismatch cannot be detected: a cartesian=True matrix passed without the flag stores x, y, z into the range and angle fields. Invalid returns may have no meaningful x, y, z either — one dropped before a range was measured loses its angles that way, so edit in the default spherical basis if you are keeping those. A cartesian row that names no position — all-zero, or carrying NaN/inf — stores as range 0 rather than propagating.

From a pandas DataFrame, select columns by name — column order then can't drift, and a basis mismatch raises KeyError on the missing geometry columns instead of silently storing the wrong coordinates:

edited = frame.with_points(df[VoyantFrame.points_columns()].to_numpy())

See py/edit_recording_example.py for a complete script.

Converting recordings to PCD

from voyant_api import VoyantPlayback, init_voyant_logging
from voyant_api.pcd_utils import save_frame_to_pcd, frame_to_pcd

init_voyant_logging()

with VoyantPlayback() as playback:
    playback.open("my_recording.vynt")

    for frame in playback:
        if frame is None:
            break

        # Save directly to .pcd file
        save_frame_to_pcd(frame, f"frame_{frame.frame_index}.pcd")

        # Or get a PointCloud object for further processing
        pc = frame_to_pcd(frame)
        pc.save(f"frame_{frame.frame_index}.pcd")

Sending SDL commands

SDL (Software Defined Lidar) commands configure the sensor at runtime — changing operating state, field of view, frame rate, and waveform parameters.

The recommended Python flow is to start from the latest heartbeat read back, modify only the fields you want to change, then call send_sdl_blocking(). This preserves the sensor's current SDL settings and, when the sensor is already streaming point clouds, applies the requested settings while transitioning through Idle, then resumes PointCloud unless the command requests Idle.

from voyant_api import (
    CarbonClient, CarbonConfig,
    SdlState, SdlStatus,
    init_voyant_logging,
)

init_voyant_logging()

config = CarbonConfig()
config.set_bind_addr("0.0.0.0:5678")
config.set_group_addr("239.255.48.84")
config.set_interface_addr("192.168.1.100")

client = CarbonClient(config)
client.start()

# Wait for the first heartbeat so sensor_state() reflects the live read back.
# See py/sdl_example.py for a complete polling helper.
state = client.sensor_state()
cmd = state.to_sdl_command()
cmd.req_state = SdlState.PointCloud
cmd.hfov_deg = 60.0
cmd.hfov_center_deg = 0.0
cmd.frame_rate_fps = 10.0

# Blocks until the sensor confirms the command or the SDL timeout expires.
status = client.send_sdl_blocking(cmd)
if status == SdlStatus.Applied:
    print("Command applied.")
else:
    print(f"Command failed: {status}")

API Overview

CarbonClient

Receives live data from Carbon sensors. Construct with a CarbonConfig and call start() before polling for frames.

config = CarbonConfig()
config.set_bind_addr("0.0.0.0:5678")
config.set_group_addr("239.255.48.84")
config.set_interface_addr("192.168.1.100")
config.set_range_max(50.0)

client = CarbonClient(config)
client.start()

CarbonConfig

Configuration for the Carbon pipeline. Construct with defaults and setters, or load from JSON.

# From defaults
config = CarbonConfig()
config.set_bind_addr("0.0.0.0:5678")

# Observer-only: passively receive the point stream without sending anything to the
# sensor (no SDL, time-sync, or comms-health). Use this when another (primary) client
# already owns the sensor, so multiple clients can share one multicast stream. Exactly
# one primary (non-observer) client should be connected.
config.set_observer_only(True)

# Stream transport: how the sensor delivers its push stream. Unicast (the default) makes
# the sensor reply only to this client and arrives reliably even when the host has several
# network connections active at once. Multicast streams to a shared group so several clients
# can view one sensor (use observer-only for the extra ones).
from voyant_api import StreamTransport
config.set_stream_transport(StreamTransport.Multicast)

# From a JSON file
config = CarbonConfig.from_json("config.json")

CarbonConfig JSON format

All fields are optional and fall back to their defaults when omitted. To see all available fields and their current defaults, run:

from voyant_api import CarbonConfig
print(CarbonConfig())

This prints the full nested config with all current defaults, for example:

CarbonConfig { receiver: ReceiverConfig { multicast: MulticastReceiverConfig { bind_addr: "0.0.0.0:5678", group_addr: "239.255.48.84", interface_addr: "192.168.1.100" }, batch_size: 32, ... }, dsp: DspConfig { vel_corr_factor: 1.0, bandwidth_hz: None, elevation_fov_deg: 30.0, ... }, ... }

Any field shown in that output can be set in the JSON file. Fields showing None are unset and use sensor defaults.

SdlCommand

Configures sensor parameters at runtime. For read-modify-write updates, start from client.sensor_state().to_sdl_command() after the first heartbeat, then override only the fields you need. All setters validate the value immediately and raise ValueError if it is out of range.

from voyant_api import SdlState

 # Assumes `client` has already been constructed, started, and has received
 # its first heartbeat before calling `sensor_state()` / `to_sdl_command()`.

state = client.sensor_state()
cmd = state.to_sdl_command()
cmd.req_state = SdlState.PointCloud        # Operating state
cmd.hfov_deg = 60.0                        # Horizontal FOV (0.0 – 120.0°)
cmd.hfov_center_deg = 0.0                  # FOV center (−60.0 – 60.0°)
cmd.frame_rate_fps = 10.0                  # Frame rate (1.0 – 20.0 fps)
cmd.ramp_bandwidth_ghz = 6.0               # Ramp bandwidth (0.5 – 10.0 GHz)

(ramp_length is firmware-fixed at 16.384 µs, so it is read-only — exposed as cmd.ramp_length for inspection but not settable.)

You can also build a command in one validated call with configure():

cmd = SdlCommand()
cmd.configure(SdlState.PointCloud, 10.0, 60.0, 0.0, 6.0)
#             req_state, frame_rate_fps, hfov_deg, hfov_center_deg, ramp_bandwidth_ghz

Static line (linescan). Use the linescan() constructor to park the beam (HFOV 0°). There is no frame-rate argument — the firmware fixes the line rate at 900 fps. The per-field hfov_deg/frame_rate_fps setters raise if used to switch between swept and static-line mode; use linescan()/configure() for that. cmd.is_linescan reports whether a command is a static line.

Note: Linescan beam steering is temporarily unsupported — the sensor centers the mirror regardless — so hfov_center_deg must be 0.0; send_sdl rejects a non-zero center.

cmd = SdlCommand.linescan(SdlState.PointCloud, 6.0)
#                         req_state, ramp_bandwidth_ghz

In linescan mode cmd.frame_rate_fps reads back the firmware-fixed line rate 900.0 — the wire field carries a sentinel, not a real fps. A static-line SdlDeviceState reports the same frame_rate_fps == 900.0 on read-back.

Send with client.send_sdl_blocking(cmd) for the recommended blocking path. It returns Applied on success or a failure status if any step fails. If the sensor is currently in PointCloud and the command requests Idle, it sends the command once and leaves the sensor in Idle. Otherwise, it sends the requested settings with req_state = Idle, then sends the same settings with req_state = PointCloud.

For event-loop or real-time callers that cannot block, use client.send_sdl(cmd) and poll for confirmation with client.poll_sdl().

send_sdl returns a status immediately:

Status Meaning
Pending Command sent, awaiting heartbeat confirmation
InvalidParameter A value is out of range — not sent
BadFovCenterCombo FOV/center combination is invalid — not sent
FovFpsError FOV/FPS combination exceeds hardware limits — not sent
SendFailed UDP send failed — check logs
PreviousCommandPending Another command is already in flight — wait for it to resolve

poll_sdl returns Idle when nothing is in flight, Pending while waiting for confirmation, and a resolved status once the sensor confirms or the command times out:

Status Meaning
Idle No command is currently in flight
Pending Waiting for heartbeat confirmation
Applied Sensor confirmed the command was applied
Timeout No heartbeat confirmation within the timeout window
MaxRetriesExceeded Retransmitted the maximum number of times without confirmation
StreamReset Heartbeat frame counter jumped backwards — stream was reset
Any rejection status Sensor rejected the command

Note: Only one SDL command can be in flight at a time. Idle means nothing is pending and you can send immediately. While a command is in flight, poll_sdl returns Pending — keep polling until you receive a terminal status before sending another command.

Background-noise calibration

Two blocking operations configure the sensor's background-noise mask. The box is identified from the sensor's heartbeat — no serial argument needed. Both require the sensor to be in Idle and leave it in Idle (they do not start streaming):

  • client.wait_for_heartbeat() — block until the first heartbeat arrives (needed for the box serial). Raises RuntimeError on timeout.
  • client.ensure_idle_for_calibration() — drive the sensor to Idle from any state (both operations require it). Raises RuntimeError if the transition does not confirm.
  • client.apply_default_background_noise() — write the compiled-in default mask for the connected box. Fast (a few seconds); does not change the sensor's state.
  • client.refine_background_noise(iterations=None) — refine the mask from a covered-window capture. The sensor window must be covered first (the capture assumes background noise only). Cycles the sensor internally and returns it to Idle (~10–20 s). iterations defaults when omitted.
# Both operations require a heartbeat (for the box serial) and Idle on entry.
client.wait_for_heartbeat()
client.ensure_idle_for_calibration()

# Apply the built-in default calibration.
client.apply_default_background_noise()

# Or refine it (cover the sensor window first).
client.refine_background_noise()

All four raise RuntimeError if a precondition fails (sensor not Idle, no calibration embedded for the box, no heartbeat, or the operation itself fails).

While a calibration is running, SDL commands and diagnostic captures on the same client are rejected (the client drives the sensor itself during refine). Do not run a second client against the same sensor while calibrating — the two would issue conflicting commands.

Diagnostic capture

For Voyant support: with diagnostic_mode enabled, frames keep invalid points (with drop reasons), and a diagnostic capture writes the raw peak stream to a .vynt sidecar log while the point cloud keeps streaming. Record frames alongside it with VoyantRecorder — together the two files form the support bundle. The client must be running (start() first); the writer runs on its own thread, so start_diagnostic_capture() returns immediately.

  • client.start_diagnostic_capture(path, overwrite=False) — begin a capture; path is used verbatim, so name it after the frame recording it accompanies (e.g. my_recording_peaks.vynt). overwrite allows replacing an existing sidecar file — match the recorder's setting. Runs until stop_diagnostic_capture(). Raises RuntimeError if diagnostic_mode is off, the client is not running, or a capture is already in progress.
  • client.stop_diagnostic_capture() — request the active capture to stop. Returns immediately; the file ends on a whole frame.
  • client.is_diagnostic_capturing() — True while a capture is running.
  • client.diagnostic_capture_error() — why the last capture ended badly, or None for a capture that completed or is still running — so a caller polling is_diagnostic_capturing() can tell a finished capture from a broken one.
import time

from voyant_api import CarbonClient, CarbonConfig, VoyantRecorder

config = CarbonConfig()
config.set_diagnostic_mode(True)  # before start()
client = CarbonClient(config)
client.start()

with VoyantRecorder("my_recording.vynt", timestamp_filename=False) as recorder:
    # Started after the recorder opens, so a refused recording path leaves no
    # orphan sidecar running.
    client.start_diagnostic_capture("my_recording_peaks.vynt")
    frames = 0
    while frames < 100:
        frame = client.try_receive_frame()
        if frame is None:
            time.sleep(0.001)
            continue
        recorder.record_frame(frame)
        frames += 1

client.stop_diagnostic_capture()
while client.is_diagnostic_capturing():
    time.sleep(0.01)

SensorState

client.sensor_state() returns a snapshot of the latest heartbeat-derived sensor state in physical units. It is updated on each heartbeat, independently of the frame pipeline — it is not synchronized with any particular frame. Values are zero/default until the first heartbeat arrives; check state.last_heartbeat_frame > 0 before treating contents as valid.

Note: For state that belongs to a specific frame, use frame.sensor_state() and frame.host_state() — they return the snapshot recorded with that frame. Use client.sensor_state() when you want the latest reading regardless of frame.

decode_sensor_state(payload) returns the same SensorState from a stored state payload — the bytes frame.state_payload() hands back. Use it to read a snapshot that did not come from a frame you already have, and state_payload() to carry one the other way.

Typical uses are sensor health monitoring, confirming SDL commands were applied, and logging device identity — not per-frame processing.

state = client.sensor_state()

# Device identity
print(state.device.device_id)        # e.g. "CAR-30-005"
print(state.device.fpga_version)     # e.g. "v1.2.3"
print(state.device.mcu_version)      # e.g. "v1.0.0"

# Current SDL configuration confirmed by sensor
print(state.sdl.device_state)        # e.g. SdlState.PointCloud
print(state.sdl.frame_rate_fps)      # e.g. 10.0
print(state.sdl.hfov_deg)            # e.g. 60.0

# Health / temperatures
print(state.health.fpga_temp_c)
print(state.health.clarity_board_temp_c)

# Frame counters
print(state.counters.total_frame_count)
print(state.counters.total_drops_count)
print(state.counters.any_drops_sticky)

# Timing
print(state.peaks_per_frame)
print(state.last_heartbeat_frame)

# Readiness: laser linearization restarts on every SDL change, and performance is not
# fully stable until it converges. `SdlStatus.Applied` means the command was accepted, not
# that the data is trustworthy yet.
print(state.is_linearization_settling)   # True while performance is still stabilizing

Wait for state.is_linearization_settling to read False before trusting measurements. The underlying threshold varies with the configured ramp bandwidth, so use the flag rather than testing health.ll_fom_smoothed yourself.

TimeSyncState

client.time_sync_state() returns a snapshot of the host↔FPGA clock synchronization health. The client keeps the FPGA clock aligned to the host in the background (enabled by default); this reports how well it is tracking. Reads SyncQuality.Unsynced until the first measurement lands.

from voyant_api import SyncQuality

ts = client.time_sync_state()

print(ts.quality)         # SyncQuality.{Unsynced, Poor, Fair, Good, Excellent}
print(ts.valid)           # True once a fresh measurement exists
print(ts.offset_ns)       # host − FPGA clock difference (ns); >0 means the FPGA is behind
print(ts.jitter_ns)       # std-dev of the offset over the rolling window (ns)
print(ts.round_trip_ns)   # register round-trip of the kept measurement (ns)
print(ts.sample_count)    # measurements in the rolling window
print(ts.age_ms)          # ms since the last fresh measurement

if ts.quality >= SyncQuality.Good:
    print("timestamps are trustworthy")

VoyantRecorder

Records frames to binary files with automatic splitting options.

recorder = VoyantRecorder(
    output_path="recording.vynt",
    timestamp_filename=True,         # Add timestamp to filename
    frames_per_file=None,            # Split after N frames
    duration_per_file=None,          # Split after N seconds
    size_per_file_mb=None,           # Split after N megabytes
    max_total_frames=None,           # Stop after N total frames
    max_total_duration=None,         # Stop after N total seconds
    max_total_size_mb=None,          # Stop after N total megabytes
    overwrite=False,                 # Replace an existing file instead of failing
)

recorder.current_file_path reports the file being written with timestamp and split naming already applied — the path a caller cannot predict, and the one to build on when another file has to pair with the recording. It stays readable after finalize().

VoyantPlayback

Plays back recorded data with rate control.

playback = VoyantPlayback(
    rate=1.0,              # Playback speed (0.0 or None = as fast as possible)
    loopback=False,        # Loop continuously
    keep_invalid_points=False,  # True keeps invalid points instead of dropping them
)
playback.open("recording.vynt")

keep_invalid_points=True reveals invalid points during playback (the same flag on pcd_utils/pandas_utils carries them into converted output). A recording holds them if it was captured with the client's diagnostic_mode enabled, or if it was written from frames you constructed or edited yourself; an ordinary recording has none, and the flag changes nothing for it.

playback.api_version reports the version of the API that wrote the open recording, including its release status — "1.0.0", "1.0.0-alpha", or None if no file is open. A converted recording reports the version that produced the original, not the one that converted it.

Frame data access

frame.points() returns one float64 column per recorded point field, in field order — VoyantFrame.points_columns() gives the names:

[range_m, azimuth_rad, elevation_rad, doppler_mps, snr, calibrated_reflectance, timestamp_nanosecs, azimuth_idx, elevation_idx, drop_reason, combine_method, user_data]

  • range_m in meters; azimuth_rad / elevation_rad in radians, 0 at boresight, positive left and up; doppler_mps positive moving away; snr linear (not dB); calibrated_reflectance in dB
  • azimuth_idx / elevation_idx — scan grid position; (0, 0) is the frame's top-left, matching camera image conventions
  • drop_reason — numeric code; 1 means a valid return, any other value means the point was dropped
  • combine_method — numeric code; 0 = unknown, non-zero identifies how the point was produced
  • user_data — the point's two user-owned bytes read as one little-endian u16; opaque to the API

Pass cartesian=True to swap the geometry columns for [x, y, z] (derived; the default spherical matrix is the exact recorded data).

# NumPy arrays
pts   = frame.points()               # (N x 12): every recorded point field, float64 (exact)
cart  = frame.points(cartesian=True) # (N x 12): geometry columns as x, y, z
xyz   = frame.xyz()                  # (N x 3):  [x, y, z], float32, derived from spherical
xyzv  = frame.xyzv()                 # (N x 4):  [x, y, z, doppler_mps]
mask  = frame.valid_mask()           # (N,) bool — e.g. frame.points()[frame.valid_mask()]
edited = frame.with_points(pts)      # new frame from an edited matrix; state/metadata carry over
# Each accessor has a valid_* variant restricted to valid returns,
# e.g. frame.valid_points(), frame.valid_xyz().

# Pandas DataFrames (via voyant_api.pandas_utils)
from voyant_api.pandas_utils import frame_to_dataframe
df = frame_to_dataframe(frame)  # points_columns() columns; also takes cartesian=

# PCD PointCloud objects (via voyant_api.pcd_utils)
from voyant_api.pcd_utils import frame_to_pcd, save_frame_to_pcd
pc = frame_to_pcd(frame)  # default fields: x, y, z + all non-geometry fields
save_frame_to_pcd(frame, "out.pcd")
# Choose your own fields (any set including a full geometry trio,
# x/y/z or range/azimuth/elevation — the rest ride along as attributes):
save_frame_to_pcd(frame, "slim.pcd", fields=["x", "y", "z", "doppler_mps", "snr"])

# Frame metadata
print(frame.frame_index)
print(frame.timestamp)             # seconds since the Unix epoch; convenient, ~240 ns resolution
print(frame.timestamp_seconds)     # the exact recorded frame-start time...
print(frame.timestamp_nanoseconds) # ...as integers
print(frame.n_points)
print(frame.n_valid_points)
print(frame.device_id)

# Per-frame state snapshots (also available live via client.sensor_state()).
# Both return None for a recording that never stored state — see below.
state = frame.sensor_state()  # converted from the raw snapshot on each call
if state is not None:
    print(state.device)      # DeviceInfo: serial, product, firmware versions
    print(state.sdl)         # SdlDeviceState: confirmed FOV, fps, state
    print(state.health)      # HealthState: temperatures, error words
    print(state.counters)    # CounterState: frame/ramp/drop counts
    print(state.calibration) # CalibrationState: doppler, chirp bandwidth, datum
    print(state.dsp_header)  # DspHeaderState: timestamp, frame start toggle

host = frame.host_state()  # what the host knew when it sealed the frame
if host is not None:
    print(host.state_age_frames)  # snapshot staleness in frames (0 = fresh)
    print(host.dropped_ramps)     # data-plane ramp drops within this frame
    print(host.sync_valid)        # time-sync fields hold a fresh measurement

# The same snapshot as the bytes a recording stores, and back again. Also None when
# the frame carries no state.
payload = frame.state_payload()
if payload is not None:
    # State objects have no value equality, so compare the fields you care about.
    decoded = voyant_api.decode_sensor_state(payload)
    assert decoded.device.serial_number == state.device.serial_number
    assert decoded.calibration.chirp_bandwidth_hz == state.calibration.chirp_bandwidth_hz

# One-screen summary of the frame and whatever state it has
print(frame.describe())

Recordings without sensor state

The recording format used before v1.0.0 stored no sensor or host state. Those files must be converted with voyant_recording_migrate before the bindings will read them (see Breaking changes in v1.0.0), and in the converted file every frame reports:

frame.carries_state    # False
frame.sensor_state()   # None
frame.host_state()     # None
frame.state_payload()  # None

Point data, device identity, timestamps and frame indices are real in those files; health, calibration, SDL settings and time-sync figures were never recorded. They are reported as absent rather than as zeros, because zeros convert into plausible-looking physical values (a zeroed temperature register becomes -273.15 °C) that are easy to mistake for readings. Guard on carries_state when a script has to handle both:

if frame.carries_state:
    print(frame.sensor_state().health.fpga_temp_c)

Re-recording such a frame keeps it marked stateless — at the entry and in the file header — so a converted log can never be mistaken for one captured with state.

VoyantFrame.stateless(matrix, source=..., serial_number=..., timestamp_seconds=..., timestamp_nanoseconds=..., frame_index=...) builds one directly, for points that reached you without the sensor's heartbeat — a ROS bag, a CSV, any transport that carried the points alone. The timeline, frame index and device_id record and replay intact; the frame reports the three fields above as absent, so a reader sees "none was recorded" instead of defaults that look like readings. Naming a real sensor is allowed here, unlike synthetic — a frame claiming no measurements may still say where its points came from — and an out-of-epoch timestamp clamps instead of raising.

Synthetic frames are different: they are state-carrying frames from a software source, marked by their sim device_id. VoyantFrame.synthetic(matrix, source=..., timestamp_seconds=..., timestamp_nanoseconds=..., frame_index=...) builds a frame from bare points (the points() layout) — source is the generator's ProductId (e.g. ProductId.IsaacSim, ProductId.SoftwareSimulator; real sensor ids are rejected), and the per-frame identity records and replays intact, so a generated scene — say, a Python-wrapped Isaac Sim run — becomes an analyzable .vynt log. Chain .with_sdl(cmd) with a configured SdlCommand to declare the configuration the points were generated under; unauthored state fields hold defaults, not measurements (a zeroed FPGA temperature reads -273.15 °C). create_test_frame() frames follow the same model under "SIM-SW". See py/synthetic_scene_example.py for a complete scene-recording script.

Version introspection

from voyant_api import api_version, interface_contract_version

api_version()                 # the voyant-api library backing this package, e.g. "1.0.0"
interface_contract_version()  # FPGA interface contract it was built for, e.g. "1.5.6"

Both are compiled in, so they report what is actually installed. The interface contract pins the sensor wire protocol, so report the pair in bug reports and in any metadata a downstream system publishes. A sensor's own firmware versions come from a frame instead:

device = frame.sensor_state().device
print(device.fpga_version_major, device.mcu_version_major)

VoyantPlayback.api_version is a different fact again — the version that wrote an open recording, not the one replaying it.


Features

  • High performance: Rust-based implementation, no serialization at the language boundary
  • NumPy integration: Direct conversion to NumPy arrays via frame.points() / frame.xyzv()
  • Pandas support: DataFrame conversion via voyant_api.pandas_utils
  • PCD support: Point Cloud Data export via voyant_api.pcd_utils
  • Type hints: Full type annotations for IDE support (.pyi stubs included)
  • Recording & playback: Save and replay sensor data with timestamp preservation
  • Network streaming: Multicast UDP support for live sensor data
  • SDL commands: Runtime sensor configuration via SdlCommand

Complete examples

Full example scripts are available in the voyant-sdk repository:

  • carbon_client_example.py — Live data streaming with CarbonClient
  • recorder_example.py — Recording with all options
  • playback_example.py — Playback and processing
  • edit_recording_example.py — Filtering a recording and saving it back
  • pcd_conversion_example.py — Converting recordings to PCD files
  • sdl_example.py — Sending SDL commands (blocking and non-blocking paths)
  • synthetic_scene_example.py — Generating a synthetic scene and recording it to .vynt
  • background_noise_calibration_example.py — Applying and refining the noise calibration

System requirements

  • Python: 3.9 or later (ARM64/aarch64 Linux wheels currently cover 3.9–3.12)
  • Dependencies: NumPy 2.0+, Pandas 2.0+, pypcd4 1.4+
  • Platforms: Linux (x86-64 and ARM64/aarch64, including Raspberry Pi and Jetson), Windows (x86-64), macOS (Apple Silicon)
  • Firmware: match your sensor's firmware to the API release via the compatibility table in the release notes

Documentation

Support

License

Proprietary — for use with Voyant Photonics hardware products only.

Copyright © 2025 Voyant Photonics, Inc. All rights reserved.

Metadata

Release files for voyant-api 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for voyant-api 1.0.1
File
voyant_api-1.0.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl PyPy 3.11 PyPy 3.11 7.3 Linux glibc 2.28+ ARM64 Details
voyant_api-1.0.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl PyPy 3.10 PyPy 3.10 7.3 Linux glibc 2.28+ ARM64 Details
voyant_api-1.0.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl PyPy 3.9 PyPy 3.9 7.3 Linux glibc 2.28+ ARM64 Details
voyant_api-1.0.1-cp314-cp314t-manylinux_2_28_aarch64.whl CPython 3.14 CPython 3.14 free-threading Linux glibc 2.28+ ARM64 Details
voyant_api-1.0.1-cp314-cp314-win_amd64.whl CPython 3.14 CPython 3.14 Windows x86-64 Details
voyant_api-1.0.1-cp314-cp314-manylinux_2_34_x86_64.whl CPython 3.14 CPython 3.14 Linux glibc 2.34+ x86-64 Details
voyant_api-1.0.1-cp314-cp314-manylinux_2_28_aarch64.whl CPython 3.14 CPython 3.14 Linux glibc 2.28+ ARM64 Details
voyant_api-1.0.1-cp314-cp314-macosx_11_0_arm64.whl CPython 3.14 CPython 3.14 macOS 11.0+ ARM64 Details
voyant_api-1.0.1-cp313-cp313-win_amd64.whl CPython 3.13 CPython 3.13 Windows x86-64 Details
voyant_api-1.0.1-cp313-cp313-manylinux_2_34_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.34+ x86-64 Details
voyant_api-1.0.1-cp313-cp313-manylinux_2_28_aarch64.whl CPython 3.13 CPython 3.13 Linux glibc 2.28+ ARM64 Details
voyant_api-1.0.1-cp313-cp313-macosx_11_0_arm64.whl CPython 3.13 CPython 3.13 macOS 11.0+ ARM64 Details
voyant_api-1.0.1-cp312-cp312-win_amd64.whl CPython 3.12 CPython 3.12 Windows x86-64 Details
voyant_api-1.0.1-cp312-cp312-manylinux_2_34_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.34+ x86-64 Details
voyant_api-1.0.1-cp312-cp312-manylinux_2_28_aarch64.whl CPython 3.12 CPython 3.12 Linux glibc 2.28+ ARM64 Details
voyant_api-1.0.1-cp312-cp312-macosx_11_0_arm64.whl CPython 3.12 CPython 3.12 macOS 11.0+ ARM64 Details
voyant_api-1.0.1-cp311-cp311-win_amd64.whl CPython 3.11 CPython 3.11 Windows x86-64 Details
voyant_api-1.0.1-cp311-cp311-manylinux_2_34_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.34+ x86-64 Details
voyant_api-1.0.1-cp311-cp311-manylinux_2_28_aarch64.whl CPython 3.11 CPython 3.11 Linux glibc 2.28+ ARM64 Details
voyant_api-1.0.1-cp311-cp311-macosx_11_0_arm64.whl CPython 3.11 CPython 3.11 macOS 11.0+ ARM64 Details
voyant_api-1.0.1-cp310-cp310-win_amd64.whl CPython 3.10 CPython 3.10 Windows x86-64 Details
voyant_api-1.0.1-cp310-cp310-manylinux_2_34_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.34+ x86-64 Details
voyant_api-1.0.1-cp310-cp310-manylinux_2_28_aarch64.whl CPython 3.10 CPython 3.10 Linux glibc 2.28+ ARM64 Details
voyant_api-1.0.1-cp310-cp310-macosx_11_0_arm64.whl CPython 3.10 CPython 3.10 macOS 11.0+ ARM64 Details
voyant_api-1.0.1-cp39-cp39-win_amd64.whl CPython 3.9 CPython 3.9 Windows x86-64 Details
voyant_api-1.0.1-cp39-cp39-manylinux_2_34_x86_64.whl CPython 3.9 CPython 3.9 Linux glibc 2.34+ x86-64 Details
voyant_api-1.0.1-cp39-cp39-manylinux_2_28_aarch64.whl CPython 3.9 CPython 3.9 Linux glibc 2.28+ ARM64 Details
voyant_api-1.0.1-cp39-cp39-macosx_11_0_arm64.whl CPython 3.9 CPython 3.9 macOS 11.0+ ARM64 Details

Total release size: 58.9 MB

Release files / voyant_api-1.0.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl

Download URL voyant_api-1.0.1-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl
Size 2.2 MB
Tags Linux glibc 2.28+ ARM64 PyPy 3.11 PyPy 3.11 7.3
SHA-256 checksum
How to use checksums
4ce64c47756107b714c5cb4aa3ca9372d931174093b72c7f075053fa818cb1ee
BLAKE2b-256 checksum
How to use checksums
c5e4a28bae17d3fcefac6b490a2c730cd4a8693195a031c0bf941d8f9ada972a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl

Download URL voyant_api-1.0.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl
Size 2.2 MB
Tags Linux glibc 2.28+ ARM64 PyPy 3.10 PyPy 3.10 7.3
SHA-256 checksum
How to use checksums
f22a2e40ab747daa4dfcf612ab740087f7877ab6555a4d774fde1bf9bbd3b06a
BLAKE2b-256 checksum
How to use checksums
c6d8d7d1abf2946d1019b2ca6ee6ad1b68b5de9d86043c5ce431939cbcf5b983
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl

Download URL voyant_api-1.0.1-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl
Size 2.2 MB
Tags Linux glibc 2.28+ ARM64 PyPy 3.9 PyPy 3.9 7.3
SHA-256 checksum
How to use checksums
b6643e8243b3348de92db36c1dd45427a52f98b60b83923d978ccde039e60878
BLAKE2b-256 checksum
How to use checksums
1338ff9b1779101f01e50b8556d759a989758c2b0c278e81e7b451d5657141e0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp314-cp314t-manylinux_2_28_aarch64.whl

Download URL voyant_api-1.0.1-cp314-cp314t-manylinux_2_28_aarch64.whl
Size 2.2 MB
Tags CPython 3.14 CPython 3.14 free-threading Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
ec8bd120ae842ef5a9726f2f47d458f3af4d859492fba2131e9472cae1ad2f07
BLAKE2b-256 checksum
How to use checksums
d7e995cc18caf9a019355f314efad6b01a8003260653eb0b8131133abba30fb8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp314-cp314-win_amd64.whl

Download URL voyant_api-1.0.1-cp314-cp314-win_amd64.whl
Size 1.9 MB
Tags CPython 3.14 Windows x86-64
SHA-256 checksum
How to use checksums
b8baead7ade3c25cc2b4b9d348830e83b103bdbf8f7d6ae9c50872eb718f577e
BLAKE2b-256 checksum
How to use checksums
61c7cd61fbbdf7443aef45e3c9fe14c47114be46154a61cb3f3091606dc65a0e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp314-cp314-manylinux_2_34_x86_64.whl

Download URL voyant_api-1.0.1-cp314-cp314-manylinux_2_34_x86_64.whl
Size 2.2 MB
Tags CPython 3.14 Linux glibc 2.34+ x86-64
SHA-256 checksum
How to use checksums
9d51e7f38eda4542931119fb1ecdb429f2b6f64590a9fd364114fda084b5dff7
BLAKE2b-256 checksum
How to use checksums
21bff68dbc507e190310906c82814f72eae7324a4414c2ade1b1db66b36d62ae
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp314-cp314-manylinux_2_28_aarch64.whl

Download URL voyant_api-1.0.1-cp314-cp314-manylinux_2_28_aarch64.whl
Size 2.2 MB
Tags CPython 3.14 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
433d376d88845a1e7fc37a60d163153f2bea2e060ed57b563e147ef47b68ff91
BLAKE2b-256 checksum
How to use checksums
1e59546e1fb685fc41afc9c68a7736f4062d0e5b464330f1395ad51990f2e945
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp314-cp314-macosx_11_0_arm64.whl

Download URL voyant_api-1.0.1-cp314-cp314-macosx_11_0_arm64.whl
Size 2.0 MB
Tags CPython 3.14 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
04f5b7fef1e13d10641022cceeadd7ec9813fa5f44071f5306b6b87c6d15b5bd
BLAKE2b-256 checksum
How to use checksums
945eec74cdf165a0a486baaaa241cd0c72cc0115f9cd0e50225d0a244d49a73b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp313-cp313-win_amd64.whl

Download URL voyant_api-1.0.1-cp313-cp313-win_amd64.whl
Size 1.9 MB
Tags CPython 3.13 Windows x86-64
SHA-256 checksum
How to use checksums
8a31a8f2a774b485f68740aafe3890e84f33d92d3547009105d09af0760318b9
BLAKE2b-256 checksum
How to use checksums
20a0603f1c14867188d3295eace0f8a613ea6bb7ee03af2c1f960a4a659220c5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp313-cp313-manylinux_2_34_x86_64.whl

Download URL voyant_api-1.0.1-cp313-cp313-manylinux_2_34_x86_64.whl
Size 2.2 MB
Tags CPython 3.13 Linux glibc 2.34+ x86-64
SHA-256 checksum
How to use checksums
1cfa418c5657ebf91c30f3ad66dc7c1c608d05d06205008a5c7e4ad75ce8f4da
BLAKE2b-256 checksum
How to use checksums
03a8f5ea9d31a78c18a9292cca488562fd04332d3de1fcd69dacbb1cb95ab1e3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp313-cp313-manylinux_2_28_aarch64.whl

Download URL voyant_api-1.0.1-cp313-cp313-manylinux_2_28_aarch64.whl
Size 2.2 MB
Tags CPython 3.13 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
b3d74f19b4821f02546fe5cd5b61b63cbc012c4032ff076bc4c67c58228641ee
BLAKE2b-256 checksum
How to use checksums
d5f370974f5f5bf32415f3bde03dbc9841384959287baf5dc4a238901a1a0827
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp313-cp313-macosx_11_0_arm64.whl

Download URL voyant_api-1.0.1-cp313-cp313-macosx_11_0_arm64.whl
Size 2.0 MB
Tags CPython 3.13 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
7d824524cd57b572e9f7c384e23cca78b90014838f5b8be3e4da590251182d8c
BLAKE2b-256 checksum
How to use checksums
6f19d599f06218b7775b2a43d3ac556527a25ae9c019e7efd459debc80297ea3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp312-cp312-win_amd64.whl

Download URL voyant_api-1.0.1-cp312-cp312-win_amd64.whl
Size 1.9 MB
Tags CPython 3.12 Windows x86-64
SHA-256 checksum
How to use checksums
0950feb1dad6277e94fb6a1afe5b6c3741d2eb057133c5217fb3724568bd1e86
BLAKE2b-256 checksum
How to use checksums
2fd3ab0efafead0ec75b4fbffe3784ce668b5d662e825725d6313503ad3b07dd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp312-cp312-manylinux_2_34_x86_64.whl

Download URL voyant_api-1.0.1-cp312-cp312-manylinux_2_34_x86_64.whl
Size 2.2 MB
Tags CPython 3.12 Linux glibc 2.34+ x86-64
SHA-256 checksum
How to use checksums
4b48fedf6d8ef18a0977418068266943a1f97aaeddd3c8eabb1245a5a8348599
BLAKE2b-256 checksum
How to use checksums
2717c277270e37fc15b5a7c86535ff8433d76a7740e886eeae4ad43072d8642e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp312-cp312-manylinux_2_28_aarch64.whl

Download URL voyant_api-1.0.1-cp312-cp312-manylinux_2_28_aarch64.whl
Size 2.2 MB
Tags CPython 3.12 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
56d28f88000b4a90b489bc1891122327e361681023c01417ee9d362c0f28ca5b
BLAKE2b-256 checksum
How to use checksums
d78d7b6c4d4e15ed4312fb66c07cdaf1e9c2eaf3e3d679e7a5c3776faa5d2623
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp312-cp312-macosx_11_0_arm64.whl

Download URL voyant_api-1.0.1-cp312-cp312-macosx_11_0_arm64.whl
Size 2.0 MB
Tags CPython 3.12 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
a791a3d691c3d624b63dd752011979991870cbc530464aad1f98e88dadb482ce
BLAKE2b-256 checksum
How to use checksums
a56239aac6f98e06153ef0b11b95cb1043fe170baa7e0b7049c2a5971414ea7a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp311-cp311-win_amd64.whl

Download URL voyant_api-1.0.1-cp311-cp311-win_amd64.whl
Size 1.8 MB
Tags CPython 3.11 Windows x86-64
SHA-256 checksum
How to use checksums
cfcefd51137df9cc3823daa08bec4cb5d62ff8d5098ba76ae915f2b2151054d1
BLAKE2b-256 checksum
How to use checksums
eaf01e808d12bd7e73abbb3f63785a9030b8240c59259c0b2d5a1b60c798e2c1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp311-cp311-manylinux_2_34_x86_64.whl

Download URL voyant_api-1.0.1-cp311-cp311-manylinux_2_34_x86_64.whl
Size 2.2 MB
Tags CPython 3.11 Linux glibc 2.34+ x86-64
SHA-256 checksum
How to use checksums
106aa1990cebbb0f9c3df28607c2d9bd7a88cab51fa67a214f85d2e66831b99d
BLAKE2b-256 checksum
How to use checksums
da82e4d19a556d6b148024d10db5a594daee93a2efb607d02287eb49e6b56014
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp311-cp311-manylinux_2_28_aarch64.whl

Download URL voyant_api-1.0.1-cp311-cp311-manylinux_2_28_aarch64.whl
Size 2.2 MB
Tags CPython 3.11 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
a50a3bdf5b703f35eb738b213dafc59ebb2aa622763027056c6a163f502b3ce3
BLAKE2b-256 checksum
How to use checksums
54c59d3d5c1f4f1a9608f8418a6aecefc3d8cc1f4cae8031d357fc62051918ce
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp311-cp311-macosx_11_0_arm64.whl

Download URL voyant_api-1.0.1-cp311-cp311-macosx_11_0_arm64.whl
Size 2.0 MB
Tags CPython 3.11 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
2629c760770039e13731513efe17cef11820a4c8fe0095bdb7fadc0e9a6adef2
BLAKE2b-256 checksum
How to use checksums
767e8fcdebbe9e1ca27848b7e42007a6f27521354d28de401e1819e2d7b92973
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp310-cp310-win_amd64.whl

Download URL voyant_api-1.0.1-cp310-cp310-win_amd64.whl
Size 1.8 MB
Tags CPython 3.10 Windows x86-64
SHA-256 checksum
How to use checksums
870318773ce7eef4683b8b0226c705b6f344760ab7b5e6824f6954935b7f2b6d
BLAKE2b-256 checksum
How to use checksums
136db59f7cba45bd049de0a51cd8525c34e64f3c18f3edca4466cb2fada5e780
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp310-cp310-manylinux_2_34_x86_64.whl

Download URL voyant_api-1.0.1-cp310-cp310-manylinux_2_34_x86_64.whl
Size 2.2 MB
Tags CPython 3.10 Linux glibc 2.34+ x86-64
SHA-256 checksum
How to use checksums
cf27749f1b52a16a6d3394bc485d6a1f4dd091d889e8cc0bf3b16e21343d8d68
BLAKE2b-256 checksum
How to use checksums
578d4a29b44d061d55b12aba2a8d5c7bb843210c6765f88d64831020e4705257
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp310-cp310-manylinux_2_28_aarch64.whl

Download URL voyant_api-1.0.1-cp310-cp310-manylinux_2_28_aarch64.whl
Size 2.2 MB
Tags CPython 3.10 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
4452de73b8e8caf682581e2b88be234ddbf2f090b671c9d1d5a2779dc2670c5d
BLAKE2b-256 checksum
How to use checksums
c5d219a244a26aa39b48063d929219ca8efdac3bf3481202428bdf84a444b41f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp310-cp310-macosx_11_0_arm64.whl

Download URL voyant_api-1.0.1-cp310-cp310-macosx_11_0_arm64.whl
Size 2.0 MB
Tags CPython 3.10 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
bfcf607e70c7debfbd5fd830a7dbc48c6bd25f1ae553b2c0113a97c2b2e50ad9
BLAKE2b-256 checksum
How to use checksums
470a354f188c92be348e1dd041f349cacc08b6fc29712c98f8d2b937709b9f30
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp39-cp39-win_amd64.whl

Download URL voyant_api-1.0.1-cp39-cp39-win_amd64.whl
Size 1.9 MB
Tags CPython 3.9 Windows x86-64
SHA-256 checksum
How to use checksums
e6e174d78cb09654ada1248295d7ff448cf76dc69d34036a13a1dee5fc83d81e
BLAKE2b-256 checksum
How to use checksums
2abce3b2a59374ae55dbe9ea95fa69e45faf266c8002d117842ab1a2808ac529
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp39-cp39-manylinux_2_34_x86_64.whl

Download URL voyant_api-1.0.1-cp39-cp39-manylinux_2_34_x86_64.whl
Size 2.2 MB
Tags CPython 3.9 Linux glibc 2.34+ x86-64
SHA-256 checksum
How to use checksums
0429f0b547d289322b6a2c40f3a8046191b83c7d810bdbdbd00ae6aca3932a99
BLAKE2b-256 checksum
How to use checksums
5e61b6e307b1db3cba719cc15e61a227962cd083554820ea2c9dab549f16a7a0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp39-cp39-manylinux_2_28_aarch64.whl

Download URL voyant_api-1.0.1-cp39-cp39-manylinux_2_28_aarch64.whl
Size 2.2 MB
Tags CPython 3.9 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
073ef03cccb7e99aee9f0608264bc90391bf5fcdae5e93ba8f7704f3055cfec8
BLAKE2b-256 checksum
How to use checksums
df3f82a7e2049cbc78683762ef6a48c6c8072127142f2813865ea10728f17d6d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / voyant_api-1.0.1-cp39-cp39-macosx_11_0_arm64.whl

Download URL voyant_api-1.0.1-cp39-cp39-macosx_11_0_arm64.whl
Size 2.0 MB
Tags CPython 3.9 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
819ca9643a914042caa680655291cdfc509d17806445832f0eb930de3496b747
BLAKE2b-256 checksum
How to use checksums
6b7328e9155bf3a60d56cc122f21bf1fb5a42dbc7d729fbabdeaaeeb30ec948c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release history Release notifications | RSS feed

This release

1.0.1 This release

28 release files

1.0.0

28 release files

0.9.3

18 release files

0.8.2

18 release files

0.8.1

18 release files

0.8.0

18 release files

0.7.2

18 release files

0.7.1

18 release files

0.5.0

18 release files

0.4.4

18 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page