Stop the extent clamp rewriting the ROI on every drag event (+ a jump detector) - #43
Merged
Conversation
… event
Adds RoiTrace, an always-on detector for an integrating ROI that moves on its
own, and fixes the first thing it found.
THE BUG. _clamp_extent compared the span against the cap with a bare `>`. A
span resting EXACTLY on the cap computes fractionally OVER it in floating
point -- 1.95 - 1.15 = 0.8000000000000003 > 0.8 -- so the clamp rewrote the
widget on nearly every pointer_move of a capped drag. Each rewrite pushes a
python-sourced geometry echo back to the renderer mid-drag, which is exactly
the feedback loop the widget-side max_extent cap exists to avoid. Now compared
with a relative tolerance; same for the 2-D rectangle, which can hit it too.
THE DETECTOR. The symptom is intermittent and the interesting state (what the
renderer sent, what the clamp did to it, what indices came out) is gone by the
time anyone looks. RoiTrace keeps a ring of the last 8 pointer events and dumps
it at WARNING when the geometry moves in a way no single pointer gesture
explains:
* the fallback clamp rewrote geometry -- with the widget-side cap this should
be unreachable during a drag, so a hit means that assumption broke;
* the ROI both MOVED and RESIZED in one event -- dragging an edge moves one
end, dragging the body moves both by the SAME amount, so both ends moving
by DIFFERENT amounts did not come from one gesture;
* every index collapsed onto one nav position while the ROI still covers more
than one -- the "span pinned at the last frame" shape.
It is always on and silent until one of those fires. Requiring an env var would
mean reproducing the bug twice: once to notice, once to capture. The rules are
deterministic -- distance is deliberately NOT one of them, because a fast mouse
move legitimately translates the ROI a long way in a single event and a
threshold there would cry wolf on every flick. SPYDE_ROI_TRACE=1 logs every
event for a deliberate reproduction session.
Measured beforehand and worth recording, since it rules out the obvious
suspects on a calibrated 0.05 s/frame movie axis: the cap is CORRECT at
construction (0.8 = 16 frames, not stale), the widget clamps the drag itself,
and the lower-edge-anchoring fallback never fires. So the remaining jumping is
not the documented _clamp_extent phantom-movement.
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.
Chasing "the ROI still jumps a bit" on a 4k in-situ movie. Adds an always-on detector for an integrating ROI that moves on its own, and fixes the first thing it found — within one test run.
The bug
_clamp_extentcompared the span against the cap with a bare>. A span resting exactly on the cap computes fractionally over it in floating point:So the clamp rewrote the widget on nearly every
pointer_moveof a capped drag. Each rewrite pushes a python-sourced geometry echo back to the renderer mid-drag — precisely the feedback loop the widget-sidemax_extentcap exists to avoid. Now compared with a relative tolerance; same for the 2-D rectangle, which can hit it too.Caught by the detector''s own ring buffer on its first run:
— before and after print identically at 4 s.f., which is the whole point.
The detector
The symptom is intermittent and the interesting state (what the renderer sent, what the clamp did to it, what indices came out) is gone by the time anyone looks.
RoiTracekeeps a ring of the last 8 pointer events and dumps it at WARNING when the geometry moves in a way no single pointer gesture explains:Design choices worth stating:
SPYDE_ROI_TRACE=1logs every event for a deliberate reproduction session.Costs a few float comparisons and a deque append per pointer event.
What this rules out
Measured first, on a calibrated 0.05 s/frame movie axis, because the documented suspect was
_clamp_extent''s lower-edge anchoring:_clamp_extentranSo the remaining jumping is not the documented phantom-movement. The detector is there to identify what it actually is.
Tests
26 new, mostly about what must not fire — pure translation, dragging either edge, a fast flick, a single-point region, the first event. Plus the epsilon regression pinned directly (
_clamp_extentmust not rewrite a span sitting exactly on the cap), and a realSessiondrag asserting silence. 367 selector/nav/region/movie tests pass.