Repository navigation
GeecsPanels: crosshairs and the analysis ROI — drawn by the panel, dragged to move, written through an allow-list - #1133
Conversation
…collapsible Live strip, and frames fetched only when the camera makes one - The image fills the panel; wheel zooms at the cursor, drag pans, double-click or Fit fits, 1:1 shows camera pixels (unsmoothed when magnified). The colour-mapped frame is kept apart from the view, so later overlays zoom and pan with it (toView/toImage). - Scale: linear / square root / log, in the same lookup table as the levels. - Live folds into a native disclosure whose summary keeps centroid and max. - FrameSource reuses a frame exactly while MJPG1's counter stands still and sends it as X-Frame-Counter; the page skips decoding a frame it already shows. A 1 Hz camera polled at 10 Hz is now one fetch and one draw a second. - Fixed while measuring: the reuse window was timed from the fetch's reply, so a poll at the cap's period was handed the old frame a third of the time (5.5 fps shown of 10). Now timed from the request, and the counter decides whenever it is known. The page also fetches the next frame while drawing the last. Measured: 9.5-10 fps at the 10 fps cap. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ers, a reuse limit, per-fetch frame tags, decode errors, pixel density, the 1:1 floor F1: the min_interval floor applies whatever the counter says, so N viewers cost the IOC one fetch per floor (a 30 Hz camera and 5 viewers was ~50/s). F2: a frame is never reused past max_reuse (1 s) under an unchanged counter, and each fetch gets its own tag (X-Frame-Tag) so the page redraws a refetch. ffmpegServer stores the JPEG before posting its counter, so this is a net, not a known failure. F3: a change of devicePixelRatio (window moved between screens) re-sizes. F4: a frame that fails to decode shows the error and is retried. F5: 1:1 reaches 100% on a frame smaller than the view. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…decode-error box hides only after a frame draws; two comments brought up to date Review round 2 on #1132 (both low). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…agged to move, written through an allow-list Build step 2b. The IOC stores both crosshairs (OVER1:1/2) and the analysis ROI (ROI1); the panel draws them over the colour-mapped image (overlay.js, a layer on the viewer's new hooks) and edits them: - drag a crosshair's centre, or the ROI's edges and corners; the edit is held on screen until the IOC's readback agrees - per crosshair: on/off (an unconfigured overlay becomes a visible cross with a visible colour), colour, x/y, to-centroid (converted ROI -> image pixels on the server, coords.py, binning and reversal included) - ROI x/y/width/height and Full frame Writes: POST put (allow-listed: OVER1:1/2 fields, ROI1 Min/Size — nothing a scan saves; values coerced to the PV's type), a colour route, a to-centroid route; --read-only refuses all. Fit now leaves a 16 px margin so a full-frame ROI's handles can be grabbed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…[object Object] Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… value ranges, no grabs before a frame, whole-bin reversal F1: a crosshair is drawn and hit-tested on its pixel's centre, a drag writes the pixel under the pointer (floor, as the cursor readout names it), and to-centroid rounds half up rather than half-to-even. F2: a cleared or non-numeric field writes nothing; the allow-list carries ranges (pixels 0..65535, ROI sizes >= 1, colour 0..255). F3: no hover or grab before the first frame (an invisible ROI could be collapsed). F4: coords uses NDROI's whole-bin span, so a reversed ROI whose size is not a multiple of the binning maps to the right pixel. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adversarial review (fresh-context reviewer, two rounds)The reviewer found no way around the allow-list or
Below the floor, fixed in #1134: the allow-list comment sat above the wrong definition. |
skbarber
left a comment
There was a problem hiding this comment.
Reviewed this PR in the #1130–#1135 stack, including the existing review fixes. No additional actionable findings in this PR. Validation at stack head dc8ac07: panel suite plus Core EPICS bootstrap/light-import tests, 143 passed (including JavaScript syntax checks). Targeted offline probes reproduced the findings on #1134/#1135. No hardware writes or live camera testing performed. The documented dependency on #1134 for scaled-image coordinates still applies.
Stacked PR, step 2b of the panels arc. Base:
feat/panels-viewer(#1132) ← #1131 ← #1130. The stack merges in order at the end of the arc (maintainer's call: evaluate the arc as a unit).What
The IOC stores both crosshairs (
OVER1:1/2) and the analysis ROI (ROI1): shared by every viewer and autosaved. The panel draws them over the colour-mapped image and edits them. This is the design note's §5 ruling: colour crosshairs drawn client-side, with the stream left plain greyscale.overlay.js, a layer on the viewer's new hooks (draw,grab,hover,snapshotviawindow.GeecsCameraView). It zooms and pans with the image.POST /camera/{d}/put: allow-listed (camera.WRITABLE: OVER1:1/2 fields and ROI1 Min/Size only, nothing a scan saves), with values coerced to the PV's type./crosshair/{n}/colour: r/g/b, range-checked by the model./crosshair/{n}/to-centroid: the STAT centroid converted from ROI to image pixels on the server (coords.py, binning and reversal included).--read-onlyrefuses every write and disables the controls.1013 added, 19 removed.
Tests
test_writes.pycovers:overlay.jsadded to the guard).Hardware verification (done on ADTEST_CAM1)
Through the panel's routes and real mouse events in Chrome over CDP:
cam1:AcquireTimeandHDF1:Capturerefused;Capture_RBVstayed Done.🤖 Generated with Claude Code