Commit Graph
5 Commits
Author SHA1 Message Date
leonarski_fandClaude Opus 5 30252722e4 Viewer: the magnifier re-opens on the current cursor position
centerAt returns early while the window is hidden, and nothing replays the last
position when it comes back, so re-opening the magnifier showed whatever region
the cursor was over when it was closed - with current pixels, which makes it
look like a live view of the wrong place. Remember the position while hidden and
apply it on show.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 11:22:27 +02:00
leonarski_fandClaude Opus 5 7a893bb1e7 Viewer: per-pixel counts in the magnifier, read from the int32 image
Users expect a magnifier to tell them the counts, which the follower view could
not do: it has the rendered pixels but not the numbers behind them.

Take them from the detector's int32 buffer directly, the same source the main
view colours from, so no float copy of the image is needed - the magnifier
still holds nothing full-size of its own, only a shared_ptr to the frame and
one to the reader image.

The labels are painted in drawForeground() rather than as scene items. The main
view creates up to 5000 QGraphicsSimpleTextItems per overlay rebuild for this;
here they are just drawn, so there is no item churn and no scene invalidation.
Text is laid out in viewport pixels so it stays a constant readable size, and
black/white is chosen from the luminance of the rendered pixel underneath, as
the main view does.

Threshold is the same 30x as the main view, so the default 12x magnification
shows no labels until the user wheels in; a cap keeps pathological window sizes
from drawing thousands of them.

Verified in the GUI at 32x: counts drawn per pixel with white text over the
dark centre of a Bragg peak and black elsewhere, and "Gap" across a module gap.
Main image panel still pixel-identical to the pre-series baseline.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 21:18:20 +02:00
leonarski_fandClaude Opus 5 d2ce65f857 Viewer: magnifier displays the frame the main view already rendered
The magnifier and the main view are two views of the same image at different
position and zoom, but the magnifier ran the whole pipeline again on its own
copy: it wrapped the same int32 buffer in a SimpleImage, converted it to float,
coloured every pixel and kept its own full-size QImage. That is a second
conversion and two extra full-detector buffers (20 MB at 2.8 Mpx, 138 MB at
18 Mpx) to feed a 320x320 window.

Separate producing a frame from displaying one:

- JFJochImage keeps the rendered frame in a shared_ptr<QImage> (the pointer is
  stable for the widget's lifetime; only the contents change, so the existing
  buffer reuse is unaffected), publishes it via Frame() and announces new
  pixels with frameRendered().
- JFJochImageItem holds that shared_ptr instead of a reference to a member of
  its owner, which also removes a lifetime coupling.
- JFJochFollowerImage is a small read-only view of such a frame with its own
  zoom and centre. It shows only the image: overlays, ROI tools and per-pixel
  labels belong to the view that owns the data.
- The magnifier becomes one of those, fed from frameRendered().

Consequences beyond the saving: the magnifier now agrees with the main view on
colour map, contrast and HDR mode, which it never did -- it was wired to
neither, so it always drew with its own defaults. And the visibility guard
added in 6d1af4921 is gone: there is no longer any per-frame work to skip, so
nothing needs guarding. That guard was a workaround for this design.

Stepping 30 frames with the magnifier open: 5550 -> 4810 ms CPU, which is what
it costs with the magnifier closed (4770 ms) -- it is now free either way.

Verified: main image panel and a drag-pan stay pixel-identical to the
pre-refactor binary (AE=0); the magnifier follows the cursor, updates on a new
frame, and now tracks a colour-map change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 21:11:42 +02:00
leonarski_fandClaude Opus 5 68f5f1f32d Viewer: do not render the magnifier close-up while it is closed
centerAt() checked isVisible(), but imageLoaded() did not, so every frame built
a SimpleImage over the whole detector image and ran it through the full
JFJochSimpleImage path -- convert to float, colour every pixel, redraw -- to
feed a 320x320 window that is closed by default and stays closed most of the
time.

Remember the frame instead and do the work in showEvent(). Holding the
shared_ptr also keeps alive the buffer that the SimpleImage's CompressedImage
points into, which it did not own.

Stepping 30 frames with the magnifier closed: 5545 -> 4770 ms CPU (-14%), on a
2.8 Mpx detector; the saving is per-pixel, so it grows with detector size. With
the magnifier open the cost is unchanged (5500 ms), which is what was being
paid unconditionally before.

Verified in the GUI: opening the magnifier still populates it, and it still
refreshes when the frame changes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 20:45:11 +02:00
leonarski_f 75e401f0e5 v1.0.0-rc.153 (#63)
Build Packages / Unit tests (push) Successful in 1h31m59s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 8m43s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 10m5s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 9m27s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 8m56s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 9m24s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 10m27s
Build Packages / build:rpm (rocky8) (push) Successful in 9m20s
Build Packages / build:rpm (rocky9) (push) Successful in 10m50s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 9m54s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 8m38s
Build Packages / DIALS test (push) Successful in 12m13s
Build Packages / XDS test (durin plugin) (push) Successful in 7m8s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 7m8s
Build Packages / XDS test (neggia plugin) (push) Successful in 7m50s
Build Packages / Generate python client (push) Successful in 16s
Build Packages / Build documentation (push) Successful in 50s
Build Packages / Create release (push) Skipped
This is an UNSTABLE release. It includes many experimental features, as well as many AI generated fixes. We recommend using rc.152 for production use.

* jfjoch_broker: Add EXPERIMENTAL pixelrefine mode for image processing
* jfjoch_broker: Allow to load user mask from 8-bit and 16-bit TIFF files
* jfjoch_broker: Add ROI calculation in non-FPGA workflow
* jfjoch_broker: Fixes to TCP image pusher
* jfjoch_broker: Remove NUMA bindings
* jfjoch_broker: Improvements to indexing
* jfjoch_broker: For PSI EIGER, trimming energies are taken from the detector configuration (now compulsory) instead of hardcoded values
* jfjoch_writer: Save ROI definitions and the per-pixel ROI bitmap in the master file; azimuthal ROIs support phi (angular) sectors
* jfjoch_viewer: Major redesign with dockable panels and saved layouts, plus on-canvas creation/move/resize of box, circle and azimuthal ROIs
* jfjoch_viewer: Run jfjoch_process reprocessing jobs from inside the GUI and overlay per-run results

Reviewed-on: #63
2026-06-23 20:29:49 +02:00