Key the label projection cache on the viewport, not the canvas size - #8
Merged
Conversation
_screen_y_projection caches the world->screen-y mapping the channel-label overlay places its text with, but keyed that cache on the canvas widget's size while the mapping is computed from the subplot's viewport rect. The two usually move together, so the widget size stood in for the viewport -- until something reshaped the viewport without resizing the canvas, at which point nothing was left to evict the entry. The camera terms could not cover for it either: a sweep's camera height follows n_visible alone, so it does not move on a resize. The labels then kept a projection built for the previous geometry and sat stretched or compressed against their traces indefinitely, until an unrelated change to n_visible or the scroll position happened to change the key. Nudging the viewport by 40px with the canvas size held fixed put them 36px out and left them there. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Channel labels could end up stretched or compressed against their traces after a window resize, and stay that way.
The bug
ChannelPlotWidget._screen_y_projectioncaches the world→screen-y mapping thatChannelLabelOverlayplaces its text with. The mapping is computed fromsubplot.viewport.rect, but the cache was keyed onself._fpl_widget.size()— the canvas widget. The widget size was only ever standing in for the viewport.The two normally move together, so this held up in the common case. It breaks whenever something reshapes the viewport without resizing the canvas: there is then nothing left in the key to evict the entry. The camera terms cannot cover for it either —
SweepWidget._apply_auto_scalederivescamera.heightfromn_visiblealone, so it does not move on a resize.The overlay then keeps a projection built for the previous geometry indefinitely, until an unrelated change to
n_visibleor the scroll position happens to change the key.The fix
Key on
viewport.rect— the thingmap_world_to_screenactually reads.getattr-guarded, consistent with the camera terms alongside it.Nudging the viewport 40px with the canvas size held fixed, before and after:
Verification
Ground truth came from comparing where the overlay paints against where traces actually land in the wgpu framebuffer, rather than re-deriving the same arithmetic. Across canvas heights 306–1366 px,
QT_SCALE_FACTOR1 / 1.25 / 1.5 / 2, and liveshowFullScreen/showMaximized/showNormal/ resize cycles driven through the Qt event loop: glyph-to-trace offset is a constant −0.5 px and mapping error is 0.00 px.tests/test_overlays.py::test_projection_follows_the_viewport_not_the_canvas_sizepins it. The stub deliberately carries a fixed-size_fpl_widget, so reverting the fix fails on the stale projection value rather than on anAttributeError— confirmed by stashing the fix and re-running. Full suite: 128 passed.Not addressed here
A separate, cosmetic issue turned up while chasing this and is left alone:
MIN_LABEL_FONT_PX = 8pinsfm.height()at 10 px while the row span tracks canvas height, so once the span drops below ~10 px,step(overlays.py:163) goes to 2 or 3 and the chips grow to 1–2 rows tall.At step 1 each label sits cleanly on its own trace. At step 2–3 the chips merge into a near-solid column straddling neighbours, and which channels get labeled changes on every resize. That is aligned-but-ambiguous rather than misaligned — a leader tick from chip to trace, or suppressing labels that cannot fit their row, would be the fix.
🤖 Generated with Claude Code