Skip to main content

spviz

spviz is a TensorBoard-style observer for intermediate signal-processing data products. Your application continues to own execution, scheduling, and data flow. spviz only taps values that the application already produced, records their semantic axes and lineage, and serves an interactive visualization afterward.

Explore all ten live examples

  1. Phased-array radar — beamforming, range–Doppler processing, cell averaging, and CA-CFAR.
  2. Microphone-array audio — delay-and-sum steering, spectra, noise estimation, and tone tracking.
  3. QPSK receiver — carrier correction, matched filtering, symbol error magnitude, and decisions.
  4. Seismic array — trace filtering, spectra, event-energy integration, and triggering.
  5. Multi-lead ECG — baseline removal, QRS enhancement, energy integration, and peak candidates.
  6. LFM pulse compression — 1D chirp, complex echo, matched filtering, CA-CFAR, and detections.
  7. Audio FIR equalizer — 1D waveforms, windowed-sinc coefficients, convolution, and power spectra.
  8. Rolling-bearing diagnostics — 1D vibration, resonance filtering, analytic envelope, and fault harmonics.
  9. Acoustic source localization — a 1D reference, 2D microphone capture, 3D steered time–frequency cube, 2D beam energy, and 1D direction score.
  10. OFDM receiver quality — a 1D I/Q capture, 3D resource grid, 2D EVM and error maps, and 1D subcarrier quality.

GitHub Actions regenerates that example from examples/radar.py and deploys it to Pages on every push to main. You can create the same serverless bundle yourself with spviz export-static RUN_DIR OUTPUT_DIR.

Install and run the radar example

python -m venv .venv
. .venv/bin/activate
pip install -e .
python examples/radar.py
spviz serve runs/radar-demo

Choose a different port with either --port or -p:

spviz serve runs/radar-demo --port 9000

Open http://127.0.0.1:8765. Click any product without losing the pipeline overview, permute axes, scrub or animate layers, isolate a layer, adjust the opacity of other layers, and inspect individual values. Horizontal and vertical dragging adjust the 3D stack separation within constrained inspection bounds, while double-clicking restores the home view. Two-dimensional products can switch between a heatmap and stacked 1D slices; axis order selects which dimension becomes the playable layer axis.

The viewer includes dark and light interface themes plus Spviz, Viridis, Plasma, Inferno, Magma, and Cividis color maps. The latter five use the familiar Matplotlib palette endpoints; values at or below the selected minimum remain transparent so the chosen page theme forms the visualization's low-end background.

The inspector can export the selected axis-labeled layer as PNG, the current transparent stack as PNG, an animated GIF sweep through the selected depth axis, or the complete processing chain as PNG. Exports preserve the active axis permutation, coordinates, units, color limits, log mode, transparency, and selected layer where applicable.

The pixel-density control trades fidelity for interaction speed using an explicit samples-per-displayed-axis count. Its maximum is the selected plane's largest native dimension, which requests the full plane without downsampling. The pipeline overview remains fixed at a lightweight 64 samples per axis.

The inspector aspect-ratio control offers Data proportions (the normal array width-to-height ratio), Equal axes (a square display extent), and Fit view (fill the available inspector area). The processing overview has a separate aspect control and defaults to data-proportional previews, so changing the full-chain presentation does not alter the selected product view.

Observe your existing pipeline

import numpy as np
import spviz

spviz.init("runs/my-run", name="My receiver")

# These functions belong to your application. spviz does not call them.
iq = read_receiver()
spviz.tap(iq, "Raw I/Q", axes=["channel", "pulse", "sample"], units="volts")

beamformed = beamform(iq)
spviz.tap(
    beamformed,
    "Beamformed I/Q",
    filename="beamformed_iq.npy",
    axes=["beam", "pulse", "sample"],
    scale="log",
    vmin=1e-4,
    vmax=2.0,
    operation="beamform",
    inputs=iq,
)

range_doppler = process_range_doppler(beamformed)
spviz.tap(
    range_doppler,
    "Range–Doppler",
    axes=["beam", "doppler", "range"],
    operation="range + Doppler FFT",
    inputs=beamformed,
)

spviz.close()

axes names every source dimension. Arrays with one to three dimensions use all of them by default. For higher-dimensional products, explicitly choose the three spatial dimensions while preserving the full source shape:

spviz.tap(
    data,
    "Range–Doppler history",
    axes=["frame", "beam", "doppler", "range"],
    view_axes=["beam", "doppler", "range"],
    coordinates={
        "frame": timestamps,
        "beam": {"values": look_angles, "units": "deg"},
        "doppler": {"values": velocities, "units": "m/s"},
        "range": {"values": ranges, "units": "m"},
    },
)

Coordinates may be numeric, categorical, or temporal. They are stored as separate NumPy arrays and loaded only when needed. The inspector presents permutations using axis names—not anonymous dimension numbers—and displays coordinate ranges, physical layer values, units, and coordinates for selected cells. Non-view dimensions remain part of the captured product and are indexed at zero by the current viewer.

tap() returns the exact object it receives, so it can also be inserted inline without changing the chain:

beamformed = spviz.tap(beamform(iq), "Beamformed", inputs=iq)

filename= controls the .npy filename inside the run's arrays/ directory. It is intentionally a filename rather than an arbitrary path, keeping runs self-contained and portable. When omitted, spviz derives a safe filename from the display name and adds a suffix for repeated names.

scale= sets the product's default visualization scale to "linear" (the default) or "log". It initializes the inspector and is also honored by the full-chain overview. Users can still toggle the selected product interactively.

overview_aspect= optionally overrides only that product's top processing-graph preview with "data", "equal", or "fit". It does not change the product inspector. Without an override, the shared overview aspect control applies.

vmin= and vmax= set a product's initial absolute display range. Values at or below vmin are fully transparent and then fade smoothly into the selected color map; this lets background/noise disappear into either the dark or light theme without discarding the underlying captured data. The viewer's range controls remain adjustable.

For code where wrapping a function is convenient, optional instrumentation observes its return value while leaving invocation and scheduling with the original application:

spviz.init("runs/my-run")

@spviz.instrument(name="Filtered I/Q", axes=["channel", "sample"])
def filter_bank(iq):
    return existing_filter_implementation(iq)

Observed runs are portable directories containing manifest.json and standard NumPy .npy files. The browser requests a resolution-limited visualization volume once, then changes layers locally for responsive interaction without loading the full source array.

Current scope

  • NumPy arrays with arbitrary dimensionality
  • Directed product lineage and operation labels
  • Local, dependency-light HTTP server
  • Transparent stacked-slice volume rendering
  • Axis permutation, layer playback/isolation, opacity, and value inspection
  • Deterministic synthetic phased-array radar example with clutter, receiver mismatch, thermal noise, windowed FFTs, an explicit cell-average noise estimate, and binary CA-CFAR detections

This is an initial foundation. Live streaming, framework adapters, timeline comparison, GPU-side capture, and richer plots are intentionally left for later versions.

Download files

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

Source Distribution

spviz-0.1.0.tar.gz (35.1 kB view details)

Uploaded Source

Built Distribution

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

spviz-0.1.0-py3-none-any.whl (31.9 kB view details)

Uploaded Python 3

File details

Details for the file spviz-0.1.0.tar.gz.

File metadata

  • Download URL: spviz-0.1.0.tar.gz
  • Upload date:
  • Size: 35.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.14

File hashes

Hashes for spviz-0.1.0.tar.gz
Algorithm Hash digest
SHA256 185b238cb18f6cc99c285772c96764203b9c9140fb2935c13b1459ac3c41d77c
MD5 a2cffe452bb63f2f16db54456c582116
BLAKE2b-256 6158bffdb3120a103a03db9e6210bb6ef444d7f8860ca92830600ae371c5ec4c

See more details on using hashes here.

File details

Details for the file spviz-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: spviz-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 31.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.14

File hashes

Hashes for spviz-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a5e2cb7501cbf0052315ff42835a75ddfa25807eb4f63d0e28d4acf4e3b94332
MD5 8d55c9212cfa710c8fb1e886740a31e0
BLAKE2b-256 d07cb168f1fab3d854a2735dbcf2cdf181596fac461cd83121cbc38cd2db02e2

See more details on using hashes here.

Release history Release notifications | RSS feed

0.2.1

2 files

0.2.0

2 files

This release

0.1.0 This release

2 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