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)

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.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

voyant_api-1.0.0-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl (2.2 MB view details)

Uploaded PyPymanylinux: glibc 2.28+ ARM64

voyant_api-1.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl (2.2 MB view details)

Uploaded PyPymanylinux: glibc 2.28+ ARM64

voyant_api-1.0.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl (2.2 MB view details)

Uploaded PyPymanylinux: glibc 2.28+ ARM64

voyant_api-1.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl (2.2 MB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.28+ ARM64

voyant_api-1.0.0-cp314-cp314-win_amd64.whl (1.9 MB view details)

Uploaded CPython 3.14Windows x86-64

voyant_api-1.0.0-cp314-cp314-manylinux_2_34_x86_64.whl (2.2 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.34+ x86-64

voyant_api-1.0.0-cp314-cp314-manylinux_2_28_aarch64.whl (2.2 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.28+ ARM64

voyant_api-1.0.0-cp314-cp314-macosx_11_0_arm64.whl (2.0 MB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

voyant_api-1.0.0-cp313-cp313-win_amd64.whl (1.9 MB view details)

Uploaded CPython 3.13Windows x86-64

voyant_api-1.0.0-cp313-cp313-manylinux_2_34_x86_64.whl (2.2 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.34+ x86-64

voyant_api-1.0.0-cp313-cp313-manylinux_2_28_aarch64.whl (2.2 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.28+ ARM64

voyant_api-1.0.0-cp313-cp313-macosx_11_0_arm64.whl (2.0 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

voyant_api-1.0.0-cp312-cp312-win_amd64.whl (1.9 MB view details)

Uploaded CPython 3.12Windows x86-64

voyant_api-1.0.0-cp312-cp312-manylinux_2_34_x86_64.whl (2.2 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.34+ x86-64

voyant_api-1.0.0-cp312-cp312-manylinux_2_28_aarch64.whl (2.2 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.28+ ARM64

voyant_api-1.0.0-cp312-cp312-macosx_11_0_arm64.whl (2.0 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

voyant_api-1.0.0-cp311-cp311-win_amd64.whl (1.8 MB view details)

Uploaded CPython 3.11Windows x86-64

voyant_api-1.0.0-cp311-cp311-manylinux_2_34_x86_64.whl (2.2 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.34+ x86-64

voyant_api-1.0.0-cp311-cp311-manylinux_2_28_aarch64.whl (2.2 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ ARM64

voyant_api-1.0.0-cp311-cp311-macosx_11_0_arm64.whl (2.0 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

voyant_api-1.0.0-cp310-cp310-win_amd64.whl (1.8 MB view details)

Uploaded CPython 3.10Windows x86-64

voyant_api-1.0.0-cp310-cp310-manylinux_2_34_x86_64.whl (2.2 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.34+ x86-64

voyant_api-1.0.0-cp310-cp310-manylinux_2_28_aarch64.whl (2.2 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.28+ ARM64

voyant_api-1.0.0-cp310-cp310-macosx_11_0_arm64.whl (2.0 MB view details)

Uploaded CPython 3.10macOS 11.0+ ARM64

voyant_api-1.0.0-cp39-cp39-win_amd64.whl (1.9 MB view details)

Uploaded CPython 3.9Windows x86-64

voyant_api-1.0.0-cp39-cp39-manylinux_2_34_x86_64.whl (2.2 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.34+ x86-64

voyant_api-1.0.0-cp39-cp39-manylinux_2_28_aarch64.whl (2.2 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.28+ ARM64

voyant_api-1.0.0-cp39-cp39-macosx_11_0_arm64.whl (2.0 MB view details)

Uploaded CPython 3.9macOS 11.0+ ARM64

File details

Details for the file voyant_api-1.0.0-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for voyant_api-1.0.0-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 a93c7b556c893c96b44cb6ff8cb9bb1d91326d870aff06971fd3891a02fef9b5
MD5 d58ba653f5f1926831f3e5d8b99625d0
BLAKE2b-256 fc8770ca15757aa129570101adb5675ad41830bdfbd9fe52ef57681c2b064e15

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for voyant_api-1.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 c6a3e17af112b38760ce0d6e8e5ea455c5d6a34b311e711ca4cdac689a1b7854
MD5 c483821adad132ed387cdffbb8bb8b0c
BLAKE2b-256 d8e0644257718139afcabc14da68d9f2fd4c24cb84d9342d383516d1efca9675

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for voyant_api-1.0.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 0774e64863f27d945af416e2d0819d05e437a5018c631c3be469bcc3547b1b4d
MD5 8fb376b8126c8c6935c4ba9300c244fc
BLAKE2b-256 4d5036cfba3c8c2ec08ce9b0329635df165a99d90e2f7f09274c67b51a548a78

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for voyant_api-1.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 f01162e87cb34acbaf9d8bec8fc2716ab279020edfe04976633043979ff116f7
MD5 7161767db184dd7f79dc977f970775ec
BLAKE2b-256 c2d6dc1d4c0b5f42ab8dab61b7a72462806954dcaf59c5a4d4db6e89987543f1

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp314-cp314-win_amd64.whl.

File metadata

  • Download URL: voyant_api-1.0.0-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 1.9 MB
  • Tags: CPython 3.14, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for voyant_api-1.0.0-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 1f140d3cf7f3a5b81cb24e794df470c94ab78a8fbac99f91f2e0090c4d49f337
MD5 10d721d03be174aa64b45fe65dc39482
BLAKE2b-256 7679db832b7740c6abba943df51faf4939ec8264039cd9309466eb44135edd0c

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp314-cp314-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for voyant_api-1.0.0-cp314-cp314-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 0f0f4f0f4378a4a4d25db5c57ff13f511ef18923005524665bce34b0de3c2823
MD5 9458cc197a3b3c2142a2df703c2a749f
BLAKE2b-256 221e72193e7d8d1185b91a8baa83b83a343c0467fd9c6a8fe7ff093443066362

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp314-cp314-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for voyant_api-1.0.0-cp314-cp314-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 798a1890f54dbe2ad62439a3bd1fb807ee52f11d6ff4c5c12f4827a85c387025
MD5 97279fb181877b71d0066d116272a8b8
BLAKE2b-256 5a2c4222bd09182691acdaf5c5c52b7e1c5e83a4f04d8c457543b817944c6f16

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for voyant_api-1.0.0-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 fd10e5c6a6cebc905c27310fb91ecd9cda23e8ac4501fb3d09527a1059ea2637
MD5 fcb3ff465dd5350bf3d636ad0662db65
BLAKE2b-256 3bb2cb0b4155ecc380d1b44e1eb25b10ef007d0e45f94f1c5be22de3ad4249ee

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: voyant_api-1.0.0-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 1.9 MB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for voyant_api-1.0.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 9167a40e6719486d8afd6e92b7af0c7be453a2f47c10bae57ca211325c17416e
MD5 ace3068944e91a1e787f3a8041c6d756
BLAKE2b-256 129162ed1272413198ba865d58dc286a9412be79c69ffc8894c156778565dcf5

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp313-cp313-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for voyant_api-1.0.0-cp313-cp313-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 aec6a27fb18b9f0339d82b0fc60732f98d73c8790ee45c93116d381473c8bb76
MD5 5fd8d14f17acae21fef93e1930509df8
BLAKE2b-256 fd71b8dc57c6963fd6f9cf394c48e95a76e85a7bfe6cb202c86bf8a1daa6fe5e

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp313-cp313-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for voyant_api-1.0.0-cp313-cp313-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 dad13ba8efa6a62308ed625cdc60aa4eae4eb73bd432440e29d69dfa97955244
MD5 b6b4c3a73cd7ddc1c0e45a7e2f60146a
BLAKE2b-256 81b4b970d757c6523b18ff392c1d0deaa1bba822621ebfb6e4318219d4f21a0f

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for voyant_api-1.0.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 564621a2f280bf96e31aabbd95c3e9b7b274c4a9bf55f845ac13a8ba486d3bb1
MD5 0d74dc34f2aec2ea7dbe227cfc1ff8e3
BLAKE2b-256 74e7bef276ff674a9a841baa2f4af6db9ee0b6aaf0d925ff445818eb597a5fce

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: voyant_api-1.0.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 1.9 MB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for voyant_api-1.0.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 a0fc0227d89ff1079f79fbf994d0d77195dbc46acafbd373453d9dbe37b6c7c5
MD5 a062e3dbd0711ac6c9e9321cec861b22
BLAKE2b-256 46123fe51f7e49fdd8908e96d7a625b6ced5a1c075ff7fd2fd6e4dd1a79d3511

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp312-cp312-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for voyant_api-1.0.0-cp312-cp312-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 ef961508d578eaead602a1595c720b4a58f40288d63e4f1470922881adb370de
MD5 3ffd7ce87c2007f9f690bd76ea195196
BLAKE2b-256 c4359cf519bb4825af662a3f076be60e792ed88fb44d969bde99c148600d1f71

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp312-cp312-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for voyant_api-1.0.0-cp312-cp312-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 a8584da60e6c29ff4a3ea1b742750446da748cd19afbe2e8238fe8cfd0b175ee
MD5 146c886892f2e6ca1b0af0bdb29790a2
BLAKE2b-256 23d7d5b2e94f2eb9ca2ac5bc55e1d139b2b8f1d279ff6195a6513f0088df95c5

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for voyant_api-1.0.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 150580671e7e43831b4d352d13eb8873a39f5c31db848083344bb41646a44f06
MD5 e56e93fb738c4a6c3d56bb00c552c917
BLAKE2b-256 1a9bcebb783d4585fde9e4362332731ce3172843de49bb4e5447f53a3e23f906

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: voyant_api-1.0.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 1.8 MB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for voyant_api-1.0.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 ce652a7bc37bc4124d209e90421cdfe04eed6b6a46f021cf02ba4084f11006be
MD5 5dbf578cb1b0c92dfb1fac105a7719b4
BLAKE2b-256 3e7b2d096c16e58b858f2b5a30391ca74e931732cbf6a485cd4d1d5b73290a51

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp311-cp311-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for voyant_api-1.0.0-cp311-cp311-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 a269cede22ffeaf7f8a51ce1e818025f40789cfe9664154621c797ea5fc2c817
MD5 565600af8b722f677263e28cf2a55598
BLAKE2b-256 b5660e186bf4dc7a3cc4670c447087b664f94294c83729cbcb9549015e3054ad

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp311-cp311-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for voyant_api-1.0.0-cp311-cp311-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 672948b30daf08ed658729597aa136691f6185caf056fc1df8970914974edd63
MD5 dbf8c3e76c1ee99393be73ac7bac0bd6
BLAKE2b-256 6799f7df00a574198deb7265cb3c7a5a381d39c9537221d3203b5a6b59f6213b

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for voyant_api-1.0.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 02df4df180641079a8000240665e47227c084b885a961734abe61de42fc02caa
MD5 c13cdac15878d945f64d3ef5cae08efa
BLAKE2b-256 0ab9a20b65613d334e5a1e5ff822166da0b55f615f2514103440c79c82e387cf

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: voyant_api-1.0.0-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 1.8 MB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for voyant_api-1.0.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 e945a91b9d67fa1826b4f5872f73c388b69e4566bfaef551a0d19a1f1436804f
MD5 c2e52d6634b3bb75fd862d1ffe7af1da
BLAKE2b-256 bc346a306c7d03b495548c9539ee57019d4000085fb91d01e7df65b851e79da5

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp310-cp310-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for voyant_api-1.0.0-cp310-cp310-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 01d299307335dc59d932109733b1562227dbddc894f8773a53b92a231b2eb308
MD5 f322fe78ff992b92ac6ea0edd0ad4917
BLAKE2b-256 edfc7a10c51b1ac13d931df16a0a21b276b81eab163319a0dc822266ca664f25

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp310-cp310-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for voyant_api-1.0.0-cp310-cp310-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 f25a251b233b71ac44e031c0ad1bf9f899a5e9cd744d530f4f4b4e15148112ba
MD5 c892ef2e49c1ec7d63e99fb2aa5b3157
BLAKE2b-256 1a6afbd733a49a3b25e6cd969f7c831cf8287cdd6c1736464b4d91a2115f78bf

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for voyant_api-1.0.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c8ed11a7fd4446dd517318fea9a9c75b644b42190cc80fd187d86553f9a104e9
MD5 af1da4321c84fccce669d27830337618
BLAKE2b-256 588fcc846b7c60d20f4200570995a875ea6e44c46a8bc3c737b3510693c96f7f

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp39-cp39-win_amd64.whl.

File metadata

  • Download URL: voyant_api-1.0.0-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 1.9 MB
  • Tags: CPython 3.9, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for voyant_api-1.0.0-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 5e0951c668e86b2a3ad6b9c3feeb7c220bf78207990f8229fe4585ce3c83f9ae
MD5 cfa9e2491ce36e3beb71a38c5fd90c8f
BLAKE2b-256 2242a1a155197b42a4e8f67fc6daf6f918b190d90da5ad30b5abf46271c0d1b7

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp39-cp39-manylinux_2_34_x86_64.whl.

File metadata

File hashes

Hashes for voyant_api-1.0.0-cp39-cp39-manylinux_2_34_x86_64.whl
Algorithm Hash digest
SHA256 098c6fadab494e9f94c6bc31fd9ea08aad9ecb116f7ecac64a45d8311b993523
MD5 50851be557c4ed355938ea74931eea47
BLAKE2b-256 a4366fa0ab188b55c5aa57081bfee5b149edad3c8f5810e78951f1b079f16a33

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp39-cp39-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for voyant_api-1.0.0-cp39-cp39-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 39e480a044e8b1d806f771587b6a25d42b9fe4d86ccf752e20d69ed2b6f21fd4
MD5 9f673ee7c2d15f81fd408edc05f9618e
BLAKE2b-256 48b87a46624d199b605fd1a5d82a8319a8182de64fb47750232a70e79b055b85

See more details on using hashes here.

File details

Details for the file voyant_api-1.0.0-cp39-cp39-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for voyant_api-1.0.0-cp39-cp39-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2efad465d2e22e79118e31b4020d0a4f647227a4237db2bf23ca53148dcc7394
MD5 e0deb897fe1b59d21f93aa7335dc4082
BLAKE2b-256 dad2824d15e0741215934c70c47da4577afc823f039611eba4c29f3cfb29b111

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.0.0 This release

28 files

0.17.1

28 files

0.17.0

28 files

0.16.1

28 files

0.16.0

28 files

0.15.0

28 files

0.14.1

18 files

0.14.0

18 files

0.13.1

18 files

0.13.0

18 files

0.12.2

18 files

0.12.1

18 files

0.12.0

18 files

0.11.0

18 files

0.10.1

18 files

0.10.0

18 files

0.9.3

18 files

0.9.2

18 files

0.9.1

18 files

0.9.0

18 files

0.8.2

18 files

0.8.1

18 files

0.8.0

18 files

0.7.2

18 files

0.7.1

18 files

0.7.0

18 files

0.6.0

18 files

0.5.0

18 files

0.4.5

18 files

0.4.4

18 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