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.
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.
See one instant, every way
3D point cloud, camera frame, and range profile for the same frame, locked together by one slider.
Find the pattern
Scatter, histogram, violin, parallel categories, and heatmap views over the whole log or the current frame.
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.
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.
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.
| Data | Format | Filterable | Re-read when |
|---|---|---|---|
| Table | Parquet, tidy table | YES full filter pipeline | filters or frame change |
| Cloud | HDF5, pre-decimated | no, fixed backdrop | frame changes |
| Curves | HDF5, one (N, 2) pair per frame | no | frame changes |
| Images | mp4, all-intra | no | frame changes |
| Reference pose | Parquet, one row per frame | no | frame changes |
h5read, works better than Parquet.<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.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
diskcachejob 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.jshandles panel collapse, splitter drags, theme persistence, and refitting Plotly after any layout change.worker.jsis 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.
Archived comments
Comments left on the previous version of this site.
Dear Dr. Peng,
I will like to test this software.
Kind regards,
N. Katte
Hi, Nkorni,
I haven’t had time put a detail documentation on this, but this is an open source project and you can find the source code here: https://github.com/rookiepeng/sensorview
You can also find the docker build here: https://hub.docker.com/repository/docker/rookiepeng/sensorview