Project log

SensorView

Updated October 4, 2026
SensorView logo

SensorView is a workbench for exploring multi-sensor logs. Open a drive, scrub to any frame, and see the radar point cloud, the camera image, and the 1D curves for that instant side by side, filtered down to the data that matters and backed by six linked statistical views.

01 · Filter

Cut the table down

Range sliders and multi-selects are generated for every column. One filtered table feeds every view, so a single drag moves them all.

02 · Inspect

See one instant, every way

3D point cloud, camera frame, and range profile for the same frame, locked together by one slider.

03 · Analyze

Find the pattern

Scatter, histogram, violin, parallel categories, and heatmap views over the whole log or the current frame.

SensorView workbench in the dark theme, replaying a nuScenes scene

A nuScenes scene: radar detections over a decimated lidar backdrop with the ego vehicle overlaid, the camera frame and range profile for the same instant in the inspector, and two statistical views in the dock.

1frame slider drives it all
6linked statistical views
5data streams, one frame id
0server trips to seek video

The Workbench

Everything on one screen

The layout is sized to the window instead of flowing down a page. Only panel interiors scroll, so every view of the current frame is at most one click away. The rail, inspector, and dock each have a splitter on their inner edge, and whatever space they give up goes to the canvas.

Select a region to jump to its description. Collapsing, dragging, and theme switching all run in the browser, without a round trip to the server.

TOPTop bar

The dataset breadcrumb doubles as the file picker. It also holds the controls to combine logs, switch theme, and export.

RAILFilter rail

Filters are generated from the manifest: a range slider for each numerical column and a multi-select for each categorical one. Points can be clicked or lassoed to mark them hidden, then filtered out by that label.

3DCanvas

An interactive 3D scatter with color mapping. A decay slider fades earlier frames in behind the current one, and overlay mode draws every frame at once. View settings float over the plot because they change only a few times per session.

INSPInspector

Shows the camera stream and the curve plot for the current frame. Each section can be minimized on its own. When a log has neither a camera nor a curve file, the inspector hides and the canvas takes its width.

TIMETransport

The frame slider is the only clock. The video never plays by itself; it seeks to whichever frame the rest of the app shows, and playback goes through the same path. Two thin lines on the top edge show server and browser buffering progress.

DOCKAnalysis dock

Two slots side by side, each showing one of six views:

  • 2D Scatter A / B: separate x/y/color mappings, with lasso and box select tied to the hidden label
  • Histogram: density or probability, optionally split by a category
  • Violin: distributions by category
  • Parallel Categories: how categorical columns relate
  • Heatmap: 2D density

Only the views placed in a slot are computed, and a collapsed dock computes nothing.

Combine logsLoad more logs from the top bar and compare them in one view.
Pre-fetched framesA WebWorker fills IndexedDB ahead of the slider, so scrubbing doesn't wait for the server.
Dark and light themesThe app and the Plotly templates switch together, and the choice is remembered.
ExportThe current plot as PNG or HTML, all frames as an HTML video, or the filtered data as Parquet.
Session isolationEach browser session gets its own cache namespace.
Native dialogsThe desktop window uses the OS file browser and save dialogs, so exports go where you choose.

Data Architecture

Each data type in the format that fits it

Each kind of sensor data is stored in the format that suits its shape, and everything is joined by a single frame id.

DataFormatFilterableRe-read when
TableParquet, tidy tableYES full filter pipelinefilters or frame change
CloudHDF5, pre-decimatedno, fixed backdropframe changes
CurvesHDF5, one (N, 2) pair per framenoframe changes
Imagesmp4, all-intranoframe changes
Reference poseParquet, one row per framenoframe changes
Only the table is queried, so it stays columnar. Parquet gives compression plus projection and predicate pushdown, and MATLAB reads and writes it natively.
Clouds and curves are display-only. They are blobs indexed by frame, so a chunked HDF5 dataset per frame, also readable from MATLAB with h5read, works better than Parquet.
Video is seeked in the browser with a native <video> element. All-intra encoding allows seeking to any frame. A container the browser can't play, such as a vendor .avi, is transcoded once and cached.
Pose is stored per frame, not per detection. Repeating six columns on each of a log's 300k rows to record one vehicle's position would waste space, and table columns can't represent orientation.

The display-only data never depends on filter state, so dragging a filter slider re-renders only the table. The cloud, curves, pose, and video are not re-read. SensorView reads these files but never writes them. The full contract, with filenames, HDF5 paths, dtypes, manifest keys, an example converter, and a validation checklist, is in DATA_FORMAT.md.

Get Started

From download to first frame

Get the app

Download the latest release for Windows or Linux, or run it from source:

git clone https://github.com/rookiepeng/sensorview.git
cd sensorview
pip install -r requirements.txt
python main.py

Prepare a case

Create a folder per case under ./data, or point the open dialog at any other directory.

Add an info.json manifest. The minimal manifest is a good starting point.

Add <stem>.parquet plus any extra files you have for it. Missing ones are simply not shown.

Or try nuScenes

data/NuScenes ships with the repo: five logs from the nuScenes v1.0-mini split, with a lidar backdrop, six curve sources, two camera streams, and a per-frame ego pose.

build_nuscenes_case.py rebuilds the case from the original archive. The data is under nuScenes' CC BY-NC-SA terms, not GPL-3.0.

Desktop window

python main.py starts Waitress on 127.0.0.1:8521 and opens it in a native pywebview window: WebView2 on Windows, WKWebView on macOS, and WebKitGTK or Qt on Linux. Closing the window stops the process. If no webview backend is available, the app opens in the default browser.

For hot reload during development, set DEBUG = True in main.py.

Shared server

server/dash_app.py exposes a ready-to-serve app that any WSGI server can host, without the desktop window:

from waitress import serve
from server.dash_app import app
serve(app.server, listen="*:8000")

Under the Hood

Flask · Dash · Plotly

Server

  • REST endpoints serve buffered frames (/api/data), the decimated backdrop (/api/cloud), and each log's video, transcoding it if needed (/api/camera).
  • Background callbacks pre-compute 3D frames through a diskcache job manager, and a newer request cancels an older one that's still running.
  • A disk cache (diskcache FanoutCache) holds session and frame data, keyed by session id.

Browser

  • workbench.js handles panel collapse, splitter drags, theme persistence, and refitting Plotly after any layout change.
  • worker.js is a WebWorker that pulls frames from the REST API into IndexedDB ahead of the slider.
  • Clientside callbacks swap figures from the local buffer and keep a bounded cache of cloud backdrops, so going back to a frame is free.
main.pyThe only entry point. Nothing starts a server on import.
server/Builds the app, the HTTP routes, the clientside callbacks, and the desktop shell.
layouts/One module for each region of the workbench.
view_callbacks/One module for each view's server-side callbacks.
viz/Turns data into Plotly figures and runs the per-frame pipeline.
frame_sources/Resolves a session's manifest, logs, and per-frame data files.
dataio/Reads Parquet, HDF5, mp4, and the manifest that describes them.
utils/Session cache, JSON persistence, table loading, and filtering.
dashplotlydash-bootstrap-componentspolarspandaspyarrowh5pynumpydiskcacheorjsonkaleidoimageio-ffmpegwaitresspywebview
GPL-3.0 · contributions welcome Issues · Pull requests · Releases

Archived comments

Comments left on the previous version of this site.

Nkorni Katte

Dear Dr. Peng,
I will like to test this software.
Kind regards,

N. Katte