v1.4.0rc1 — fast_render (Qt-native video pane)
Pre-releaseRelease 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(_revisioncounter onVideoAnnotationskipping 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=Trueroutes the video frame toQGraphicsView+QPixmapItemand the annotation scatter toQGraphicsItemGroup, leaving matplotlib responsible only for the trace canvas. Opt-in (defaultFalse); 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_renderTier 2 (VideoBrowser,VideoPointAnnotator):QGraphicsView+QPixmapItemfor the video frame,QGraphicsItemGroupfor annotation markers, mpl-shaped_QtPickAdapterso the existingpick_event/button_press_eventcallbacks fire unchanged. Wheel-zoom + middle-button pan/reset on the image pane.rkey resets both image zoom and trace axes.- Layout-managed statevariables sidebar in Tier 2 (fixed 280 px, word-wrapping
QLabelin 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 (
QPushButtonin aQToolBarattached toLeftToolBarArea) replace matplotlibwidgets.Button. Soft Qt mode: mpl-axes fallback unchanged on non-Qt backends. StateVariablesoverlay usesQLabelparented to the canvas (Tier 1) or the layout-managed sidebar (Tier 2). OriginalTextViewmpl path retained for non-Qt backends.- Per-frame trace recompute cache (
_revisioncounter onVideoAnnotation):update_frame_markerandupdate_display_tracenow short-circuit on annotation-revision change rather than running every frame. copy_to_clipboardmigrated 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_videocv2 failure unrelated).