Commit Graph
1217 Commits
Author SHA1 Message Date
leonarski_fandClaude Opus 4.8 2f8d486b51 viewer: ROI list panel — select, add, rename, delete, per-ROI results
Add JFJochViewerROIList to the side panel: a list of the dataset's ROIs
with selection, add (box/circle/azimuthal), rename and delete, plus a
statistics readout (sum/mean/std/max/valid/masked/centre-of-mass) for the
selected ROI, taken from the analysis output for the current image. Edits
emit a full ROIDefinition, routed to the worker's SetROIDefinition.

Per-ROI statistics now live in this panel rather than the canvas labels;
the diffraction image's labels show only the ROI name, and the ad-hoc
ROIIntegrationCPU computation there is removed in favour of the analysis
pipeline. The result widget now reports std dev instead of variance.

The single-ROI scratch panel remains for now and will be retired once the
interactive canvas editing replaces it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 13:56:09 +02:00
leonarski_fandClaude Opus 4.8 4e45680e96 viewer: worker can update ROIs and recompute them without full re-analysis
The reading worker's experiment is the source of truth for ROIs. Add a
SetROIDefinition slot that updates curr_experiment.ROI(), rebuilds the
analysis ROI engine, mutates the dataset (so the canvas reflects the new
ROIs) and recomputes only the ROIs for the current image via RunROIOnly.
On image load when full re-analysis is off, ROIs are still computed via
AnalyzeROIOnly so the statistics stay current.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 13:56:09 +02:00
leonarski_fandClaude Opus 4.8 a433399106 image_analysis: surgical ROI-only entry points in MXAnalysisWithoutFPGA
Add three entry points so ROI statistics can be (re)computed without a
full re-analysis, in support of interactive ROI editing in the viewer:

- RebuildROI(): recreate the ROI engine after the ROI set changes (the
  CudaStream is now kept as a member so the GPU engine can be rebuilt).
- AnalyzeROIOnly(): decompress + preprocess + ROI, skipping azimuthal
  integration, spot finding and indexing (a new image when re-analysis
  is off).
- RunROIOnly(): rerun only the ROI integration on the already-preprocessed
  image (an interactive ROI move). A full Analyze() still computes ROIs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 13:56:09 +02:00
leonarski_fandClaude Opus 4.8 3996595606 viewer: per-ROI statistics on the diffraction image via the CPU ROI engine
When ROI labels are shown, each ROI's label now also reports its sum,
max and pixel count for the current image. Rather than reimplementing the
accumulation, this reuses the existing ROIIntegrationCPU engine (the
software counterpart of the FPGA roi_calc), built from the experiment and
cached per dataset. A small adapter folds the viewer's gap sentinel
(INT32_MIN+1) onto the engine's masked sentinel (INT32_MIN) so masked and
saturated pixels are handled correctly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 13:56:09 +02:00
leonarski_fandClaude Opus 4.8 33118ebe8b viewer: fix stray line from origin on full-ring azimuthal ROI
The full-ring annulus built the inner ring as a separate QPainterPath and
merged it with addPath, which stitched a spurious segment from (0,0) to
the ring. Build both concentric rings as subpaths of one path, each begun
with an explicit moveTo, so there is no connecting segment.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 13:56:09 +02:00
leonarski_fandClaude Opus 4.8 7d6f79a1da viewer: draw azimuthal ROI wedges, with optional fill and labels
Azimuthal ROIs now render on the diffraction image as annular sectors
(or full-ring annuli), sampled through DiffractionGeometry::ResPhiToPxl
so the outline follows the ROI footprint, including wrap-around sectors.

Add two side-panel toggles (both default off): a translucent fill for
every ROI (helpful when outline colours clash with the image colour map,
and with many ROIs) and ROI name labels (constant on-screen size). Wired
side panel -> window -> diffraction image like the existing feature
toggles.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 13:56:09 +02:00
leonarski_fandClaude Opus 4.8 35f6ffdde9 viewer: draw loaded ROIs on the diffraction image
When a file with ROI definitions is opened (read into experiment.ROI()
by the HDF5 reader), the diffraction image now overlays the configured
box and circle ROIs as distinct colour-coded outlines, alongside the
existing resolution rings and spots. This is the first step of the
ROI-map-based multi-ROI canvas: showing the ROIs loaded from a file.

Azimuthal ROIs (wedge rendering) and per-ROI statistics from the bitmap
follow in subsequent steps.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 13:56:09 +02:00
leonarski_fandClaude Opus 4.8 332fd32224 frontend: link PSI in footer, add Source code and License to References
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Failing after 3m26s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Failing after 3m29s
Build Packages / build:rpm (rocky9_nocuda) (push) Failing after 3m37s
Build Packages / build:rpm (rocky9_sls9) (push) Failing after 3m45s
Build Packages / build:rpm (ubuntu2204) (push) Failing after 3m32s
Build Packages / build:rpm (rocky9) (push) Failing after 3m37s
Build Packages / build:rpm (ubuntu2404) (push) Failing after 3m46s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 8m31s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 8m52s
Build Packages / Generate python client (push) Successful in 20s
Build Packages / Build documentation (push) Successful in 59s
Build Packages / Create release (push) Skipped
Build Packages / build:rpm (rocky8) (push) Successful in 8m44s
Build Packages / XDS test (durin plugin) (push) Successful in 6m26s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 6m32s
Build Packages / XDS test (neggia plugin) (push) Successful in 5m56s
Build Packages / DIALS test (push) Successful in 9m21s
Build Packages / Unit tests (push) Successful in 49m53s
- Footer "Paul Scherrer Institute" now links to https://www.psi.ch
- Reference drawer gains a "Source code" entry linking out to the Gitea
  repository (new nav-item href that opens in a new tab)
- Reference drawer gains a "License" entry rendering the nicely formatted
  docs/LICENSE.md inline (generalises the changelog renderer into MarkdownDoc)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 13:23:51 +02:00
leonarski_fandClaude Opus 4.8 6962a61489 frontend: render Changelog inline instead of in a Sphinx iframe
The framed Sphinx changelog reused MUI with the same colours, so it read as
a picture-in-picture. Bundle docs/CHANGELOG.md at build time (?raw) and render
it with react-markdown, themed to match the app, for a quick frame-less view.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 13:21:19 +02:00
leonarski_fandClaude Opus 4.8 cee4739221 frontend: bundle Sphinx docs locally instead of linking readthedocs
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Failing after 3m32s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Failing after 3m35s
Build Packages / build:rpm (rocky9_nocuda) (push) Failing after 3m51s
Build Packages / build:rpm (rocky9_sls9) (push) Failing after 3m56s
Build Packages / build:rpm (rocky9) (push) Failing after 4m3s
Build Packages / build:rpm (ubuntu2204) (push) Failing after 4m13s
Build Packages / build:rpm (ubuntu2404) (push) Failing after 4m13s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 9m7s
Build Packages / Generate python client (push) Successful in 22s
Build Packages / build:rpm (rocky8) (push) Successful in 9m34s
Build Packages / Create release (push) Skipped
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 9m48s
Build Packages / Build documentation (push) Successful in 49s
Build Packages / XDS test (neggia plugin) (push) Successful in 5m56s
Build Packages / XDS test (durin plugin) (push) Successful in 6m26s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 6m36s
Build Packages / DIALS test (push) Successful in 11m8s
Build Packages / Unit tests (push) Successful in 55m19s
The Documentation tab pointed at jungfraujoch.readthedocs.io, which lags
behind the installed version. Build the Sphinx docs into frontend/dist/docs
and serve them at /frontend/docs so they always match the package.

- make_doc.sh: accept an output dir (default public), absolutize it, run
  from the script dir, and allow $PYTHON override
- package.json: add "docs" script building into dist/docs
- CMakeLists: run "npm run docs" in the frontend target so CPack packs the
  docs via the existing dist/ install
- App.tsx: point the Documentation DocFrame at /frontend/docs/index.html

Also clean up the Sphinx build (911 -> 0 warnings):
- fix typo myst_heading_anchor -> myst_heading_anchors so cross-doc
  #anchor links actually resolve
- suppress myst.header/myst.xref_missing (auto-generated OpenAPI client
  docs only) and the harmless sphinx_material config.cache note
- drop a dangling "---" transition at the end of CPU_DATA_ANALYSIS.md
- add REPOSITORIES and the generated python_client model pages to toctrees

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 12:44:00 +02:00
leonarski_fandClaude Opus 4.8 eadbce51bd common: take ROIAzimuthal phi as plain floats, not optionals
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 10m48s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 11m35s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 12m2s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 12m58s
Build Packages / build:rpm (rocky8) (push) Successful in 13m0s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 13m58s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 14m29s
Build Packages / XDS test (durin plugin) (push) Successful in 7m30s
Build Packages / Generate python client (push) Successful in 39s
Build Packages / Build documentation (push) Successful in 51s
Build Packages / Create release (push) Skipped
Build Packages / build:rpm (ubuntu2404) (push) Successful in 10m11s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 10m55s
Build Packages / build:rpm (rocky9) (push) Successful in 12m15s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 9m11s
Build Packages / XDS test (neggia plugin) (push) Successful in 8m33s
Build Packages / DIALS test (push) Successful in 12m0s
Build Packages / Unit tests (push) Successful in 57m36s
The phi bounds were stored as plain floats internally but passed through
std::optional in the constructor, which obscured the intent. Take them
as float arguments defaulting to 0 instead. The convention is explicit:
phi_min == phi_max means the full ring (all angles), a sector wraps
across 0 when phi_min > phi_max, and otherwise phi_min <= phi_max. The
"both bounds or none" rule belongs at the API/file boundary
(OpenAPIConvert, reader), not in the core class, so it lives there now.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 11:03:40 +02:00
leonarski_fandClaude Opus 4.8 6b95600260 writer: link ROI results into the VDS master file
In VDS mode the per-image ROI results (max/sum/sum_sq/npixel/x/y) are
written into the data files but were not exposed in the master, so a VDS
master surfaced no ROI statistics. Add virtual datasets under
/entry/roi/<name> in LinkToData_VDS, one group per ROI, mirroring how the
spot-finding and azimuthal-integration arrays are linked. Integrated and
legacy formats are unaffected (the results are already reachable there).

Extended the reader round-trip test to write real ROI results and check
they read back from the master for both VDS and integrated formats.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 10:38:24 +02:00
leonarski_fandClaude Opus 4.8 c6e7f8aa15 writer/reader: move ROI definitions to /entry/roi_defs and read them back
Relocate the ROI definitions and the roi_map bitmap from /entry/roi to a
separate /entry/roi_defs group in the master file. /entry/roi keeps its
original meaning (per-image ROI results only), so an older reader that
iterates /entry/roi is not disturbed by the bitmap/definition entries
(which would otherwise make it try to read /entry/roi/roi_map/max and
fail to open the file at all). Back-compatibility for already-deployed
viewers is the reason for the split.

JFJochHDF5Reader now reads the logical definitions into experiment.ROI()
and the roi_map bitmask (+ a name->bit index) into the dataset, for all
file formats (the master always carries them). Reading both lets a later
viewer either re-derive ROIs with the current geometry (logical) or show
the exact written footprint (bitmap).

Added a write/read round-trip test over VDS and integrated formats.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 10:35:18 +02:00
leonarski_fandClaude Opus 4.8 2bd276ae1b preview: draw azimuthal ROIs
AddROI now renders azimuthal ROIs in addition to box and circle ROIs:
inner/outer arcs at the Q (d) bounds and, for a sector, the two radial
edges at the phi bounds. The per-pixel phi comes from the same
DiffractionGeometry::Phi_rad used to assign ROIs, so the overlay matches
the ROI footprint exactly (including wrap-around sectors). Full-ring
azimuthal ROIs draw as two concentric arcs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 09:44:57 +02:00
leonarski_fandClaude Opus 4.8 03814b1425 writer: save ROI bitmap and definitions in the master file
Persist regions of interest so an acquisition's ROI layout can be
recovered from the master (_master.h5 / _process.h5):

- /entry/roi/roi_map: uint16 per-pixel bitmask (bit i == ROI i).
- /entry/roi/<name>: logical definition (type + geometry params, incl.
  azimuthal phi sector) plus bit_index tying it to the bitmap plane.

The bitmap rides along in the StartMessage (CBOR, mirroring az_int_map)
and is filled both online (JFJochReceiver::SendStartMessage) and offline
(jfjoch_process). Definitions come from the already-transmitted rois.
Both are dataset-wide metadata, so they are written by the NXmx master
writer (new NXmx::ROI), not the per-image data-file plugin.

Documented the /entry/roi layout in docs/HDF5.md and the master-vs-data
writer convention in CLAUDE.md; added a CBOR roi_map round-trip test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 09:41:26 +02:00
leonarski_fandClaude Opus 4.8 1d04656dc8 api: serialize azimuthal ROI phi sector over OpenAPI and CBOR
Expose the optional phi_min_deg / phi_max_deg azimuthal-sector bounds
added to ROIAzimuthal through the wire formats. Both are optional, so
older clients and streams (Q-only ROIs) remain valid.

- jfjoch_api.yaml: optional phi_min_deg / phi_max_deg on roi_azimuthal;
  regenerated the cpp-pistache server model and the TS frontend client.
- OpenAPIConvert: map phi both directions (set only when present).
- CBOR start message: emit phi_min/phi_max only for a sector; on decode,
  absent phi means a full ring.
- Documented the new optional CBOR fields; extended the CBOR round-trip
  test with a sector and a full-ring azimuthal ROI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 09:28:25 +02:00
leonarski_fandClaude Opus 4.8 9e57219b31 common: add azimuthal-angle (phi) sectors to ROIAzimuthal
ROIAzimuthal can now be restricted to an azimuthal-angle sector in
addition to its Q/d range, enabling STXM-style directional ROIs. phi
bounds are optional (both-or-neither); absent means a full 360 ring, so
existing Q-only azimuthal ROIs are unchanged.

- ROIElement::CheckROI gains a phi_deg argument; box/circle ignore it.
- MarkROI gains an optional phi_map; ROIMap builds it from Phi_rad
  alongside the resolution map only when azimuthal ROIs are present.
- phi bounds are normalized to [0,360) and wrap-around sectors are
  supported (phi_min > phi_max).
- ROIConfigAzim carries phi_min/phi_max (kept trivially copyable for the
  union; phi_min == phi_max means full ring).

No phi crosses the wire yet (CBOR/API wiring follows separately).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 09:21:39 +02:00
leonarski_fandClaude Opus 4.8 88f97fc197 docs: add CLAUDE.md with build/test/architecture, code-style and portability guidance
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 08:11:07 +02:00
leonarski_fandClaude Opus 4.8 a76aac65b7 frontend: add missing React keys in DetectorSelection and ROI
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 11m16s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 11m41s
Build Packages / build:rpm (rocky8) (push) Successful in 12m47s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 13m17s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 13m27s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 13m32s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 13m52s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 10m35s
Build Packages / XDS test (neggia plugin) (push) Successful in 8m15s
Build Packages / XDS test (durin plugin) (push) Successful in 8m58s
Build Packages / Generate python client (push) Successful in 14s
Build Packages / Create release (push) Skipped
Build Packages / build:rpm (ubuntu2404) (push) Successful in 9m58s
Build Packages / Build documentation (push) Successful in 40s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 9m30s
Build Packages / build:rpm (rocky9) (push) Successful in 12m11s
Build Packages / DIALS test (push) Successful in 12m4s
Build Packages / Unit tests (push) Successful in 56m3s
DetectorSelection rendered the info-table rows and the detector-select
menu items without keys; ROI's grid action cells likewise. Add stable
keys to silence the warnings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 08:01:03 +02:00
leonarski_fandClaude Opus 4.8 4f9452736a frontend: drawer-based navigation shell
Replace the stack of toggle-revealed sections with a left navigation
drawer (collapsible, expanded by default) clipped under a persistent
status bar. Dashboard (plots + measurement statistics + spot-finding)
is the default view; every other panel is its own drawer entry, so one
thing shows at a time.

- Group entries under Acquisition / Expert / Reference subheaders;
  ROI folded into On-the-fly processing.
- Pale-indigo drawer with a lime accent on the selected entry.
- Gray out JUNGFRAU calibration / FPGA status when their data is empty.
- API reference and documentation open in-app via iframe.
- Fixed footer pinned to the page bottom.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 07:57:57 +02:00
leonarski_fandClaude Opus 4.8 9fc971c1d2 frontend: add zod plugin to hey-api openapi-ts
Generate Zod schemas alongside the typed client (src/client/zod.gen.ts),
picking up the OpenAPI field defaults. Enables runtime validation and
default-filling for form payloads.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 07:24:52 +02:00
leonarski_fandClaude Opus 4.8 5d8e33d52c frontend: orange Upload button when panel is dirty
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 11m26s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 12m45s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 14m0s
Build Packages / build:rpm (rocky8) (push) Successful in 14m3s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 14m16s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 14m46s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 15m46s
Build Packages / XDS test (durin plugin) (push) Successful in 8m3s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 9m51s
Build Packages / Generate python client (push) Successful in 22s
Build Packages / Create release (push) Skipped
Build Packages / build:rpm (rocky9) (push) Successful in 11m30s
Build Packages / Build documentation (push) Successful in 41s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 8m49s
Build Packages / XDS test (neggia plugin) (push) Successful in 7m53s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 9m54s
Build Packages / DIALS test (push) Successful in 11m46s
Build Packages / Unit tests (push) Successful in 59m17s
Match the unsaved-changes dot: the Upload button uses the warning color
while the panel has unedited changes, primary otherwise.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 22:14:10 +02:00
leonarski_fandClaude Opus 4.8 59da040e30 frontend: shared SettingsPanel + typed upload with error display
Generalize the expert-panel boilerplate (container + title + widgets +
upload button) and surface real upload errors via hey-api.

- SettingsPanel: consistent padded Paper + Typography title (one place to
  size it) + optional Upload button + result snackbar; PanelTitle and
  UploadSnackbarView exported for panels with bespoke layouts (DetectorSettings
  grid, ROI)
- useUpload(mutation): wraps a generated hey-api mutation, shows the server's
  error message on failure (errorMessage handles 400 string / 500 error_message)
- "unsaved changes" dot on panel titles, derived from the existing
  last-downloaded snapshot (dirty = !isEqual(value, lastDownloaded))
- fix PixelMask: TIFF upload was swallowing errors; now shows them
- config panels (FileWriter, ImageFormat, Detector, AzInt, DarkMask, Indexing,
  Instrument, ZeroMQ, ROI, DetectorSelection) upload through the typed SDK
  instead of ButtonWithSnackbar's raw fetch; status/display panels share the
  same shell for consistent spacing
- ButtonWithSnackbar now only powers bodyless action buttons (pedestal/cancel/
  initialize, start/trigger, deactivate)

Build (tsc + vite) passes; dev server transforms all modules.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 22:04:55 +02:00
leonarski_f c000b872bb jfjoch_viewer: Fix status_bar, it looks nicer now 2026-06-18 21:59:10 +02:00
leonarski_fandClaude Opus 4.8 237de5a0fc frontend: convert to function components + TanStack Query
Replace all class components with function components and move server-state
polling to @tanstack/react-query.

- add @tanstack/react-query; generate query helpers via the hey-api
  @tanstack/react-query plugin (src/client/@tanstack)
- QueryClientProvider + one-time client.setConfig({ baseUrl: '' }) in index.tsx
- App polls statistics with useQuery(getStatisticsOptions, refetchInterval),
  DataProcessingPlot uses getPreviewPlotOptions; manual setInterval polling gone
- memo() on presentational children; with TanStack structural sharing this
  re-renders a child only when its own statistics slice changes
- PreviewImage stays imperative (binary JPEG -> object URL) using useEffect +
  a ref for the object-URL lifecycle
- fix AzIntSettings correction checkboxes that mutated state in place (relied on
  the poll re-render); they now use setState
- drop dead code uncovered during the port (unused upload/deactivate handlers
  and imports in ImageFormatSettings, DetectorSettings, ROI)

Build (tsc + vite) passes; dev server transforms all entry modules.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 21:32:36 +02:00
leonarski_f 7ed424a4ca JFJochReceiverFPGA: Fix typo 2026-06-18 20:48:19 +02:00
leonarski_fandClaude Opus 4.8 ceb7d31eac frontend: generate OpenAPI client with @hey-api/openapi-ts
Replace the unmaintained openapi-typescript-codegen generator with
@hey-api/openapi-ts.

- openapi-ts.config.ts generates src/client from ../broker/jfjoch_api.yaml
  (client-fetch + typescript + sdk plugins; enums as const objects via
  mode: 'javascript', type names preserved)
- npm "openapi" script now runs openapi-ts; drop openapi-typescript-codegen
- migrate all imports from src/openapi to src/client
- DefaultService.foo() -> standalone foo({ body|query, throwOnError })
- OpenAPI.BASE='' -> client.setConfig({ baseUrl: '' }); ButtonWithSnackbar
  uses the relative path directly
- adapt hey-api's inlined enums: broker_status.state/message_severity and
  bit_depth_image/eiger_bit_depth become string/number literal unions;
  file_writer_format NXMX_* -> N_XMX_*
- remove generated src/openapi

Build (tsc + vite) passes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 20:30:15 +02:00
leonarski_f eb9b463263 VERSION: 1.0.0-rc.153 2026-06-18 19:26:15 +02:00
leonarski_f b71da6238e Clean-up unused tools 2026-06-18 18:54:31 +02:00
leonarski_f d14b8e9e18 Merge upstream 2026-06-18 18:52:22 +02:00
leonarski_fandClaude Opus 4.8 a7c77f1f08 internal generator: compare raw image width to RAW_MODULE_COLS
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 9m15s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 11m36s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 11m47s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 12m49s
Build Packages / build:rpm (rocky8) (push) Successful in 13m32s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 13m36s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 14m15s
Build Packages / build:rpm (rocky9) (push) Successful in 11m25s
Build Packages / Generate python client (push) Successful in 32s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 10m0s
Build Packages / Create release (push) Skipped
Build Packages / Build documentation (push) Successful in 39s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 10m32s
Build Packages / XDS test (neggia plugin) (push) Successful in 8m7s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 8m53s
Build Packages / XDS test (durin plugin) (push) Successful in 8m57s
Build Packages / DIALS test (push) Successful in 11m53s
Build Packages / Unit tests (push) Successful in 57m24s
The raw stacked-module layout check compared the image width (cols) against
RAW_MODULE_SIZE (the per-module pixel count, 524288) instead of
RAW_MODULE_COLS (1024), so a raw-geometry TIFF could never be accepted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 16:09:05 +02:00
leonarski_fandClaude Opus 4.8 0f5271f14c mask: accept any-bit-depth TIFF for user mask upload
PUT /config/user_mask.tiff only accepted 32-bit unsigned TIFF, so masks
exported by tools like PyFAI (8-bit) failed. Route the upload through the
universal ReadTIFF reader and let PixelMask take a CompressedImage directly:
it validates the 2D shape against the detector's converted/raw layouts,
binarizes any 8/16/32-bit integer image (non-zero == masked), and rejects
float/multi-channel images.

Also dedupe the TIFF readers: ReadTIFFFromString16 is now a thin wrapper over
ReadTIFF, and the now-unused ReadTIFFFromString32 is removed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 16:05:04 +02:00
leonarski_fandClaude Opus 4.8 57ae145555 writer: drop unused <sys/stat.h> include from HDF5DataFile
Nothing in HDF5DataFile.cpp uses sys/stat.h (no stat/mkdir/S_* etc.); it relies
on <filesystem>. Removing the dead POSIX include also avoids a needless
non-portable header for the eventual MSVC build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 15:02:39 +02:00
leonarski_fandClaude Opus 4.8 bee35f7a25 frame_serialize: write CBOR length big-endian without bswap intrinsic
AppendImage wrote the CBOR byte-string length (major type 2, 8-byte length,
which is defined big-endian) via __builtin_bswap64 under #ifdef LITTLE_ENDIAN.
That is broken two ways off GCC/Clang+glibc: __builtin_bswap64 is not available
on MSVC, and LITTLE_ENDIAN is not defined there, so the #else path skipped the
swap and emitted a little-endian length on a little-endian host -> corrupt
frames.

Write the 8 length bytes most-significant-first directly. This is big-endian by
construction on any host, needs no byte-swap intrinsic and no endianness macro,
and is byte-for-byte identical to the previous output on little-endian hosts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 15:02:39 +02:00
leonarski_fandClaude Opus 4.8 5d9e1be814 portability: replace M_PI / std::numbers::pi with a host+device-safe PI
M_PI is a POSIX <math.h> extension that MSVC does not define without
_USE_MATH_DEFINES. std::numbers::pi (introduced in the viewer guard commit) is
C++20, but CUDA here is compiled as C++17 (CMAKE_CUDA_STANDARD 17) and several
common/ headers are pulled into .cu device translation units, so std::numbers is
not available there.

Add common/JFJochMath.h with a dependency-free `constexpr double PI` that works
in host code (including MSVC), in CUDA device code, and under C++17/20, and use
it everywhere:
- common/ and image_analysis/ (incl. CUDA .cu): 78 M_PI occurrences, 22 files
- broker/OpenAPIConvert.cpp
- viewer/: the 5 files that used std::numbers::pi now use PI, for one consistent
  convention across the codebase

Verified to build: JFJochImageAnalysis (incl. CUDA), jfjoch_viewer, JFJochBroker.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 14:54:01 +02:00
leonarski_f d0a1175c65 Clean-up of OpenAPI code 2026-06-18 14:29:53 +02:00
leonarski_fandClaude Opus 4.8 1558dddbb8 indexing: make the resolved-algorithm invariant explicit in the pool
IndexerThreadPool dispatches on DiffractionExperiment::GetIndexingAlgorithm(),
which already resolves Auto to a concrete algorithm (FFTW/FFT/FFBIDX) or None;
the pool has no policy to resolve Auto itself. The worker handled a stray Auto
with a dead branch and silently produced no result when the resolved algorithm
had no matching indexer built.

- Document on GetIndexingAlgorithm() that it never returns Auto.
- Throw a clear internal error at the pool boundary if Auto ever arrives.
- In the worker, replace the dead Auto branch with a loud failure for any
  resolved algorithm that has no matching indexer (e.g. a GPU algorithm on a
  host without a GPU), instead of returning no result silently.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 14:25:30 +02:00
leonarski_fandClaude Opus 4.8 01a97d61fe common: spell the azimuthal d-spacing unit d_A consistently
PlotAzintUnit used D_A while MultiLinePlotUnits used d_A for the same
d-spacing-in-angstrom unit. Align PlotAzintUnit to the lowercase crystallographic
convention already used by MultiLinePlotUnits. Generated Plot_unit_x::D_A is
left as-is (controlled by the OpenAPI generator's C++ enum casing).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 14:25:30 +02:00
leonarski_fandClaude Opus 4.8 52f349b9f1 frame_serialize: use reentrant gmtime in CBOR date decoding
gmtime() returns a pointer to a shared static buffer, so concurrent
deserialization of CborUnixTime_tTag values was a data race. Decode into a local
struct tm via gmtime_r (gmtime_s on Windows) instead.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 14:25:30 +02:00
leonarski_fandClaude Opus 4.8 086129f767 receiver: count only images the pusher accepted
images_sent was incremented right after image_pusher.SendImage(*loc), but the
ZeroCopyReturnValue overload was void and, for the TCP pusher, asynchronous: it
silently drops the image (releases the slot and returns) when there is no live
connection or the 2 s enqueue deadline expires. So images_sent over-counted on a
broken/slow writer connection and disagreed with the ACK-based GetImagesWritten().

Make SendImage(ZeroCopyReturnValue&) return whether the image was accepted
(enqueued/handed off) and only increment images_sent on success. The slot is
still released on the drop path. The authoritative delivered count remains
GetImagesWritten() (total_data_acked_ok for TCP). File/ZMQ pushers return true on
accept, preserving their previous always-counted behaviour.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 14:24:48 +02:00
leonarski_fandClaude Opus 4.8 e1622c3750 plots: expose compression_ratio over the REST/UI plot path
The receiver already computes and stores the compression ratio per image
(JFJochReceiverPlots Add/GetPlots/GetPlotRaw all handle PlotType::CompressionRatio),
but the type was unreachable from the API: it was missing from ConvertPlotType,
the OpenAPI plot_type enum, and the TS client, so requesting it returned 500 and
no UI menu entry existed.

Wire it through all layers:
- broker: add the compression_ratio -> PlotType::CompressionRatio case in
  ConvertPlotType.
- spec: add compression_ratio to the plot_type parameter enum.
- frontend: add COMPRESSION_RATIO to the generated plot_type enum (matches what
  regeneration would produce), a "Compression ratio" menu entry, and a Y-axis
  label.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 13:52:41 +02:00
leonarski_fandClaude Opus 4.8 ec1308f4a9 viewer: guard Linux-only constructs for Windows/MSVC builds
Step toward building jfjoch_viewer on Windows/MSVC. No change to the Linux
build: D-Bus stays on by default and the XCB plugin is still used.

- CMake: make Qt6::DBus optional via JFJOCH_VIEWER_DBUS (ON on Linux, OFF on
  Windows/macOS where Qt6::DBus does not exist); compile/link/install the dbus/
  adaptor + service file only when enabled. Select the platform integration
  plugin per-OS (QXcb on Linux, QWindows on Windows, QCocoa on macOS) instead
  of hard-coding QXcbIntegrationPlugin.
- JFJochViewerWindow: wrap the adaptor include and D-Bus registration in
  #ifdef JFJOCH_VIEWER_DBUS.
- JFJochImageReadingWorker: the POSIX open()/fstat()/NFS-errno preflight is now
  #ifndef _WIN32, with a portable QFileInfo fallback elsewhere; POSIX-only
  headers are guarded too.
- Replace the POSIX M_PI/M_PI_2 extension with C++20 std::numbers::pi across the
  viewer (not defined by MSVC without _USE_MATH_DEFINES).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 13:50:49 +02:00
leonarski_fandClaude Opus 4.8 b29b870ef2 broker/gen: gitignore generated cpp-pistache-server output
Only gen/model/ is compiled (into JFJochAPI) and tracked; the REST server is
hand-written on cpp-httplib, so the generated Pistache server stubs (api/,
impl/, main-api-server.cpp, CMakeLists.txt, README.md, .openapi-generator*) are
regeneration debris that was previously left untracked and tended to carry a
newer spec version than the committed models. Ignore it so it can't be
committed by accident.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 13:45:04 +02:00
leonarski_fandClaude Opus 4.8 56ddfaef96 viewer: live detector status bar + dataset-follow sync mode
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 11m38s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 11m49s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 11m55s
Build Packages / build:rpm (rocky8) (push) Successful in 12m55s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 13m4s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 13m16s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 14m12s
Build Packages / XDS test (durin plugin) (push) Successful in 8m5s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 8m1s
Build Packages / Generate python client (push) Successful in 19s
Build Packages / Create release (push) Skipped
Build Packages / build:rpm (ubuntu2404) (push) Successful in 9m55s
Build Packages / Build documentation (push) Successful in 45s
Build Packages / XDS test (neggia plugin) (push) Successful in 7m58s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 10m56s
Build Packages / build:rpm (rocky9) (push) Successful in 11m58s
Build Packages / DIALS test (push) Successful in 11m59s
Build Packages / Unit tests (push) Successful in 55m33s
Add a status-bar cluster, shown when connected over HTTP, that surfaces
the broker state and live acquisition info:
- broker state box (QProgressBar) with progress drawn as the bar fill,
  polled ~1 Hz on its own timer independent of image sync
- Live/Disconnected connection badge (host:port in tooltip)
- "+N new" badge and effective live-rate (Hz) readout
All widgets are fixed-width and only blanked in place, so the bar never
reflows when things appear/disappear.

Add a third autoload mode (HTTPSyncDataset): manually selecting an image
while following live now freezes the displayed image but keeps the dataset,
plots and image count updating. Surfaced via a tri-state HTTP Sync button
(off / live / data-only).

Also fix GetBrokerStatus() dropping the message field and a couple of
copy-pasted exception strings in JFJochHttpReader.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-18 08:13:07 +02:00
leonarski_fandClaude Opus 4.8 188cbb659d tests: add GPU/CPU equivalence test for ROI integration
Build Packages / Unit tests (push) Successful in 55m23s
Build Packages / DIALS test (push) Successful in 11m2s
Build Packages / XDS test (durin plugin) (push) Successful in 6m22s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 6m27s
Build Packages / XDS test (neggia plugin) (push) Successful in 5m50s
Build Packages / Generate python client (push) Successful in 12s
Build Packages / Build documentation (push) Successful in 41s
Build Packages / Create release (push) Skipped
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 9m44s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 11m48s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 11m56s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 13m7s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 13m8s
Build Packages / build:rpm (rocky8) (push) Successful in 13m8s
Build Packages / build:rpm (rocky9) (push) Successful in 14m10s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 14m31s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 9m1s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 8m56s
Runs ROIIntegrationGPU and ROIIntegrationCPU on identical input and asserts
every per-ROI field (sum, sum_square, max, pixels, weighted centre, masked
count) matches bit-for-bit. Uses overlapping ROI boxes (multi-bit masks),
negative pixel values (signed weighted-sum path), and an injected saturated
and masked pixel per ROI to cover the "max only" and "fully excluded" branches.

Guarded by JFJOCH_USE_CUDA and skips with a warning when no CUDA GPU is present,
mirroring ImageSpotFinderGPUTest.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 22:28:42 +02:00
leonarski_fandClaude Opus 4.8 c0a4801bc4 TCPStreamPusher: fix zero-copy buffer reuse and make send/END timeouts progress-based
Build Packages / Unit tests (push) Successful in 1h10m55s
Build Packages / DIALS test (push) Successful in 12m20s
Build Packages / XDS test (durin plugin) (push) Successful in 7m16s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 7m15s
Build Packages / XDS test (neggia plugin) (push) Successful in 6m7s
Build Packages / Generate python client (push) Successful in 25s
Build Packages / Build documentation (push) Successful in 47s
Build Packages / Create release (push) Skipped
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 9m21s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 10m31s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 11m38s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 12m26s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 11m22s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 12m43s
Build Packages / build:rpm (rocky8) (push) Successful in 9m47s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 8m37s
Build Packages / build:rpm (rocky9) (push) Successful in 10m5s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 7m27s
Three robustness fixes for the writer-facing TCP stream, addressing the
spurious "wrong number of images" / connection failures seen under load.

1. Never MSG_ZEROCOPY a transient buffer. The synchronous SendImage path
   passes a caller-owned buffer with z == nullptr and reuses it for the next
   frame immediately. With MSG_ZEROCOPY the kernel still references that buffer
   after send() returns, so the peer could receive corrupted frames and drop
   the connection mid-stream, truncating the run. Zero-copy is now gated on a
   ZeroCopyReturnValue that keeps the buffer alive until completion.

2. Make the SendAll watchdog measure lack of progress, not total wall-clock.
   The previous absolute deadline tore down a healthy but back-pressured
   connection (slow/starved writer) after a fixed window; the watchdog now
   resets on every byte actually sent, so only a genuinely stuck socket is
   closed. Dead peers are still caught by OS keepalive and POLLHUP/POLLERR.

3. Make the END-ack wait progress-based (WaitForEndAck). The writer may still
   be draining a backlog of DATA frames when END is sent; each DATA ACK is
   progress, so the timeout only arms once the writer falls silent rather than
   firing while images are legitimately still being drained.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 22:02:09 +02:00
leonarski_fandClaude Opus 4.8 58910274bf image_analysis: compute ROI statistics in the non-FPGA path
MXAnalysisWithoutFPGA never filled DataMessage.roi, so ROI integrals were
only available on the FPGA path. Add a software ROI engine that mirrors the
FPGA roi_calc kernel: per-ROI sum, sum of squares, good-pixel count, max and
intensity-weighted centre of mass, with each pixel carrying a 16-bit mask so
it can contribute to any subset of up to 16 ROIs.

New image_analysis/roi/ library (JFJochROIIntegration), structured like azint:
a base that precomputes the per-pixel mask and names, a templated CPU engine
(generic over pixel type for a future 16-bit path), and a GPU kernel using
per-block shared-memory atomics for the STXM case (half-detector ROIs).

Masked pixels are excluded entirely; saturated pixels are excluded from the
sums but still count towards the max, matching roi_calc exactly. The engine is
only constructed when at least one ROI is defined. Downstream CBOR/HDF5 already
consume message.roi, so no further changes are needed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 21:15:54 +02:00
leonarski_f c49bd2ac3b v1.0.0-rc.152 (#62)
Build Packages / XDS test (neggia plugin) (push) Successful in 6m2s
Build Packages / Unit tests (push) Successful in 1h37m1s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 12m4s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 13m30s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 12m52s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 11m53s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 12m38s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 13m30s
Build Packages / build:rpm (rocky8) (push) Successful in 10m47s
Build Packages / build:rpm (rocky9) (push) Successful in 11m48s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 10m40s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 9m44s
Build Packages / DIALS test (push) Successful in 12m59s
Build Packages / XDS test (durin plugin) (push) Successful in 8m33s
Build Packages / Generate python client (push) Successful in 16s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 6m24s
Build Packages / Build documentation (push) Successful in 57s
Build Packages / Create release (push) Skipped
* jfjoch_broker: Fix bounds for azimuthal integration for Q spacing (allow Q of 1e-5)
* jfjoch_viewer: Adjust Q bounds for azimuthal integration
* jfjoch_azint: Add tool to do quick azimuthal integration

Reviewed-on: #62
1.0.0-rc.152
2026-06-17 20:36:24 +02:00
leonarski_fandClaude Opus 4.8 cc925b2668 Remove NUMAHWPolicy and the libnuma dependency
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 8m30s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 10m13s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 9m45s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 11m13s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 9m51s
Build Packages / build:rpm (rocky8) (push) Successful in 8m29s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 9m31s
Build Packages / build:rpm (rocky9) (push) Successful in 9m42s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 8m47s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 8m23s
Build Packages / Generate python client (push) Successful in 19s
Build Packages / Build documentation (push) Successful in 38s
Build Packages / Create release (push) Skipped
Build Packages / XDS test (durin plugin) (push) Successful in 6m18s
Build Packages / XDS test (neggia plugin) (push) Successful in 6m4s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 6m35s
Build Packages / DIALS test (push) Successful in 10m39s
Build Packages / Unit tests (push) Successful in 1h24m58s
NUMA CPU/memory pinning is no longer worthwhile: the FPGA DMA buffers are
placed device-local by the kernel (dma_alloc_coherent), the big RAM ring
buffer is random-access (first-touch handles placement), and GPU work is
already spread across all visible devices. So drop the pinning entirely
and with it libnuma.

- Delete NUMAHWPolicy; the only concern worth keeping - GPU selection -
  is done directly via pin_gpu() (round-robin over visible GPUs) in the
  indexer pool and the Lite analysis threads. CPU-only threads
  (FPGA acquire/pedestal/summation/frame-transform) no longer bind
  anything.
- Drop get_gpu_numa_node() (sysfs lookup) - only SelectGPUAndItsNUMA
  used it.
- numa_policy broker setting is deprecated and ignored (kept in the API
  for backward compatibility; warns once on startup).
- Remove NUMA_LIBRARY / numa.h / numaif.h detection from CMake.
- Docs: drop the NUMA dependency, remove the numa_policy config example,
  and document running multiple brokers on disjoint GPUs via
  CUDA_VISIBLE_DEVICES.
- Remove NUMA_GPU_REVIEW.md (the planning note; this work is now done).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 20:25:36 +02:00
leonarski_fandClaude Opus 4.8 17732ea774 docs: refresh NUMA_GPU_REVIEW to match implemented state
Several items in the note had landed or were inaccurate. Update it to:
- mark DONE: G2 pin_gpu, ImageBuffer first-touch, acquisition_device
  de-NUMA, CUDAWrapper sysfs node lookup;
- add the previously-missing FPGA DMA buffer section - placement is a
  kernel concern (dma_alloc_coherent, device-local), not the userspace
  mbind, which was only the simulator;
- record that libnuma is now down to a single file (NUMAHWPolicy.cpp);
- note that dependency removal (G3) and pinning behaviour (G4) are
  separable axes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-17 19:22:00 +02:00