Skip to content

v1.4.0rc1 — fast_render (Qt-native video pane)

Pre-release
Pre-release

Choose a tag to compare

@praneethnamburi praneethnamburi released this 18 May 05:42
· 47 commits to master since this release

Release candidate for the 1.4.0 line — Qt under-the-hood rewrite + opt-in Qt-native video pane. Two milestones rolled in:

  • 1.4.0a1 (branch milestone, not separately published): Qt widget swap (Phase 2/3 — buttons → QToolBar, statevariables → QLabel overlay, focus management) + cache_quick_wins (_revision counter on VideoAnnotation skipping per-frame trace recompute). 1.51× on real DUSTrack (interosseous_pn24-x, 141.6 → 93.8 ms median, 7.1 → 10.7 fps).
  • 1.4.0rc1: adds the architectural change probe 13 surveyed — fast_render=True routes the video frame to QGraphicsView + QPixmapItem and the annotation scatter to QGraphicsItemGroup, leaving matplotlib responsible only for the trace canvas. Opt-in (default False); DUSTrack 1.1.0+ defaults it on. 3.94× on real DUSTrack (36 ms median, 27.8 fps).

PyPI: https://pypi.org/project/datanavigator/1.4.0rc1/

Added

  • fast_render Tier 2 (VideoBrowser, VideoPointAnnotator): QGraphicsView + QPixmapItem for the video frame, QGraphicsItemGroup for annotation markers, mpl-shaped _QtPickAdapter so the existing pick_event / button_press_event callbacks fire unchanged. Wheel-zoom + middle-button pan/reset on the image pane. r key resets both image zoom and trace axes.
  • Layout-managed statevariables sidebar in Tier 2 (fixed 280 px, word-wrapping QLabel in the central widget's left column). Width is invariant across state changes; long annotation-layer names wrap to the next line instead of reflowing the layout. The matplotlib canvas (trace region) sits to the right of the sidebar; image pane occupies the top row.
  • VideoPointAnnotator.set_image_background_color — dispatches to mpl _ax_image.set_facecolor (Tier 1) or _QtImagePane.set_background_color (Tier 2). Lets DUSTrack's dark theme work in both tiers without subclass-awareness of which tier is active.

Changed (1.4.0a1 work folded in)

  • Qt-native buttons (QPushButton in a QToolBar attached to LeftToolBarArea) replace matplotlib widgets.Button. Soft Qt mode: mpl-axes fallback unchanged on non-Qt backends.
  • StateVariables overlay uses QLabel parented to the canvas (Tier 1) or the layout-managed sidebar (Tier 2). Original TextView mpl path retained for non-Qt backends.
  • Per-frame trace recompute cache (_revision counter on VideoAnnotation): update_frame_marker and update_display_trace now short-circuit on annotation-revision change rather than running every frame.
  • copy_to_clipboard migrated from PySide2 to qtpy (pip install datanavigator[qt] pulls PyQt6 as the default binding).

Performance

tests/qt_learning/14_benchmark_fast_render.py against real DUSTrack on the interosseous_pn24-x 36715-frame video:

segment / total 1.4.0-qt + cache 1.4.0rc1 fast_render delta
update body 11.43 11.42 ~0
process_events 82.39 24.42 -57.97
total (median) 93.80 35.97 -57.83
fps (median) 10.7 27.8 +17.1

Full breakdown + probe 14 result block in BENCHMARKING.md.

Tier 2 ergonomic cost

The image region is no longer an mpl Axes. Subclasses that did self._ax_image.plot(...) will not render (the attribute is the _QtImagePane instance). Portfolio audit confirmed no in-tree code does this; DUSTrack's _apply_dark_theme (_ax_image.set_facecolor) was the only external touch and migrated to the new shim. Constraint is forward-looking — opt out with fast_render=False for legacy subclasses that need an mpl image axis.

Tested

  • tests/test_fast_render_parity.py — sub-pixel positional parity between Tier 1 and Tier 2, pick-event regression at known marker pixels, out-of-radius miss check.
  • tests/test_pointtracking.py — full Tier 1 regression suite (41/41 pass).
  • Full suite — 170/170 (one pre-existing test_is_video cv2 failure unrelated).

See also