Compare commits

..
115 Commits
Author SHA1 Message Date
leonarski_fandClaude Opus 4.8 a79f05134b rugnux: also write merged reflections as SHELX HKLF-4 (.hkl)
Build Packages / Unit tests (push) Successful in 1h19m28s
Build Packages / build:windows:cuda (push) Successful in 13m16s
Build Packages / build:viewer-tgz:cpu (push) Successful in 6m54s
Build Packages / build:viewer-tgz:cuda (push) Successful in 7m28s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 9m13s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 9m53s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 9m36s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 8m55s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 10m18s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 11m23s
Build Packages / build:rpm (rocky8) (push) Successful in 10m55s
Build Packages / build:rpm (rocky9) (push) Successful in 11m37s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 10m38s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 10m37s
Build Packages / DIALS test (push) Successful in 11m59s
Build Packages / XDS test (durin plugin) (push) Successful in 7m25s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 8m0s
Build Packages / XDS test (neggia plugin) (push) Successful in 7m16s
Build Packages / Generate python client (push) Successful in 25s
Build Packages / Build documentation (push) Successful in 56s
Build Packages / Create release (push) Skipped
Build Packages / Unit tests (pull_request) Successful in 1h2m9s
Build Packages / build:windows:nocuda (pull_request) Successful in 11m23s
Build Packages / build:viewer-tgz:cpu (pull_request) Successful in 6m33s
Build Packages / build:viewer-tgz:cuda (pull_request) Successful in 7m26s
Build Packages / build:rpm (rocky8_nocuda) (pull_request) Successful in 9m29s
Build Packages / build:rpm (rocky9_nocuda) (pull_request) Successful in 9m40s
Build Packages / build:rpm (ubuntu2204_nocuda) (pull_request) Successful in 8m58s
Build Packages / build:rpm (ubuntu2404_nocuda) (pull_request) Successful in 8m35s
Build Packages / build:rpm (rocky8_sls9) (pull_request) Successful in 9m47s
Build Packages / build:rpm (rocky9_sls9) (pull_request) Successful in 10m32s
Build Packages / build:rpm (rocky8) (pull_request) Successful in 9m44s
Build Packages / build:rpm (rocky9) (pull_request) Successful in 11m1s
Build Packages / build:rpm (ubuntu2204) (pull_request) Successful in 10m11s
Build Packages / build:rpm (ubuntu2404) (pull_request) Successful in 9m49s
Build Packages / DIALS test (pull_request) Successful in 11m41s
Build Packages / XDS test (durin plugin) (pull_request) Successful in 7m25s
Build Packages / XDS test (JFJoch plugin) (pull_request) Successful in 7m2s
Build Packages / XDS test (neggia plugin) (pull_request) Successful in 6m25s
Build Packages / Generate python client (pull_request) Successful in 19s
Build Packages / Build documentation (pull_request) Successful in 52s
Build Packages / Create release (pull_request) Skipped
Build Packages / build:windows:nocuda (push) Successful in 10m34s
Build Packages / build:windows:cuda (pull_request) Successful in 18m35s
WriteReflections now emits a third format alongside the MTZ and mmCIF: a
SHELX HKLF-4 text file (<prefix>.hkl), the direct input for SHELXC / ANODE /
SHELXD. Fixed FORMAT(3I4,2F8.2), one record per reflection as h k l I sig(I),
ending with the 0 0 0 terminator.

Two things make it a valid substructure-solution input:
- Bijvoet mates are written separately (I(+) at +hkl, I(-) at -hkl) so the
  anomalous differences survive; a reflection with no anomalous split is
  written once as its mean.
- Intensities are put on a common scale so the largest value fits the fixed
  F8.2 field (negative weak intensities would otherwise overflow it). I and
  sigma share the scale, so the anomalous signal is untouched; the absolute
  scale is irrelevant to SHELXC/ANODE, which use only ratios.

The MTZ writer's Bijvoet row-building is factored into a shared BuildMergedRows
helper so the MTZ and HKL outputs agree (MTZ output is byte-equivalent to
before). docs/RUGNUX.md updated to describe the three reflection formats.

Validated end-to-end on lysozyme: SHELXC reads the .hkl and reports real
anomalous signal (<d"/sig> 1.6 at low res), and ANODE locates the Met/Cys S
and a chloride at 6.5-9 sigma from the unmodified file.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 07:56:55 +02:00
leonarski_fandClaude Opus 4.8 55efd42045 tests: seed spindle-parallel beam at truth in XtalOptimizer_rotation
Build Packages / build:windows:nocuda (pull_request) Successful in 14m36s
Build Packages / build:windows:cuda (pull_request) Successful in 17m13s
Build Packages / build:viewer-tgz:cpu (pull_request) Successful in 6m44s
Build Packages / build:viewer-tgz:cuda (pull_request) Successful in 7m45s
Build Packages / build:rpm (rocky8_nocuda) (pull_request) Successful in 10m52s
Build Packages / build:rpm (rocky9_nocuda) (pull_request) Successful in 11m5s
Build Packages / build:rpm (ubuntu2204_nocuda) (pull_request) Successful in 10m5s
Build Packages / build:rpm (ubuntu2404_nocuda) (pull_request) Successful in 10m26s
Build Packages / build:rpm (rocky8_sls9) (pull_request) Successful in 10m43s
Build Packages / build:rpm (rocky9_sls9) (pull_request) Successful in 11m32s
Build Packages / build:rpm (rocky8) (pull_request) Successful in 11m19s
Build Packages / build:rpm (ubuntu2204) (pull_request) Successful in 12m8s
Build Packages / build:rpm (ubuntu2404) (pull_request) Successful in 11m50s
Build Packages / build:rpm (rocky9) (pull_request) Successful in 12m43s
Build Packages / Generate python client (pull_request) Successful in 19s
Build Packages / Create release (pull_request) Skipped
Build Packages / Build documentation (pull_request) Successful in 1m16s
Build Packages / XDS test (durin plugin) (pull_request) Successful in 8m9s
Build Packages / XDS test (JFJoch plugin) (pull_request) Successful in 7m41s
Build Packages / DIALS test (pull_request) Successful in 13m35s
Build Packages / XDS test (neggia plugin) (pull_request) Successful in 6m57s
Build Packages / Unit tests (push) Successful in 1h45m16s
Build Packages / build:windows:nocuda (push) Successful in 11m15s
Build Packages / build:viewer-tgz:cpu (push) Successful in 7m23s
Build Packages / build:viewer-tgz:cuda (push) Successful in 8m19s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 13m58s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 14m20s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 14m12s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 13m31s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 13m50s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 13m14s
Build Packages / build:rpm (rocky8) (push) Successful in 11m51s
Build Packages / build:rpm (rocky9) (push) Successful in 13m39s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 13m38s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 13m10s
Build Packages / DIALS test (push) Successful in 13m47s
Build Packages / XDS test (durin plugin) (push) Successful in 7m16s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 9m6s
Build Packages / Create release (push) Skipped
Build Packages / XDS test (neggia plugin) (push) Successful in 8m41s
Build Packages / Generate python client (push) Successful in 30s
Build Packages / Build documentation (push) Successful in 1m10s
Build Packages / build:windows:cuda (push) Successful in 12m40s
Build Packages / Unit tests (pull_request) Successful in 1h40m48s
The gauge-weak beam-centre prior (c140b3567) deliberately restrains the
spindle-parallel beam component toward the header instead of refining it
freely. The rotation test seeded that exact component (beam-X, axis along X)
off-truth, so the intended restraint slightly biased the co-refined distance
and cell-c through the distance-cell degeneracy, pushing both just past the
tight thresholds.

Seed beam-X at its true value (the gauge direction is meant to be trusted to
the header); keep beam-Y perturbed to still exercise beam-centre recovery in
the well-constrained direction. Distance/cell now recover within the original
thresholds. Source (the intended prior) untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 07:08:44 +02:00
leonarski_fandClaude Opus 4.8 074aca55e8 rugnux: supercell-collapse guard forces pass-1's full indexer result
Build Packages / build:windows:nocuda (push) Successful in 16m37s
Build Packages / build:windows:cuda (push) Successful in 18m19s
Build Packages / build:viewer-tgz:cpu (push) Successful in 7m30s
Build Packages / build:viewer-tgz:cuda (push) Successful in 7m32s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 9m26s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 9m59s
Build Packages / build:windows:nocuda (pull_request) Successful in 15m46s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 13m5s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 11m56s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 10m53s
Build Packages / build:windows:cuda (pull_request) Successful in 18m14s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 11m50s
Build Packages / build:rpm (rocky8) (push) Successful in 9m49s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 10m19s
Build Packages / build:rpm (rocky9) (push) Successful in 11m46s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 12m53s
Build Packages / Generate python client (push) Successful in 12s
Build Packages / XDS test (durin plugin) (push) Successful in 7m38s
Build Packages / Create release (push) Skipped
Build Packages / Build documentation (push) Successful in 44s
Build Packages / DIALS test (push) Successful in 11m39s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 8m21s
Build Packages / XDS test (neggia plugin) (push) Successful in 8m47s
Build Packages / build:viewer-tgz:cpu (pull_request) Successful in 6m38s
Build Packages / build:viewer-tgz:cuda (pull_request) Successful in 7m10s
Build Packages / build:rpm (rocky8_nocuda) (pull_request) Successful in 10m45s
Build Packages / build:rpm (ubuntu2404_nocuda) (pull_request) Successful in 9m30s
Build Packages / build:rpm (ubuntu2204_nocuda) (pull_request) Successful in 10m4s
Build Packages / build:rpm (rocky9_nocuda) (pull_request) Successful in 12m36s
Build Packages / build:rpm (rocky8_sls9) (pull_request) Successful in 10m32s
Build Packages / build:rpm (rocky8) (pull_request) Successful in 10m46s
Build Packages / build:rpm (rocky9_sls9) (pull_request) Successful in 13m29s
Build Packages / build:rpm (ubuntu2204) (pull_request) Successful in 11m8s
Build Packages / build:rpm (rocky9) (pull_request) Successful in 12m54s
Build Packages / Generate python client (pull_request) Successful in 19s
Build Packages / Build documentation (pull_request) Successful in 57s
Build Packages / Create release (pull_request) Skipped
Build Packages / build:rpm (ubuntu2404) (pull_request) Successful in 11m30s
Build Packages / XDS test (durin plugin) (pull_request) Successful in 7m11s
Build Packages / XDS test (JFJoch plugin) (pull_request) Successful in 7m11s
Build Packages / XDS test (neggia plugin) (pull_request) Successful in 7m3s
Build Packages / DIALS test (pull_request) Successful in 10m17s
Build Packages / Unit tests (push) Failing after 1h18m31s
Build Packages / Unit tests (pull_request) Failing after 1h0m57s
The two-pass supercell-collapse guard re-ran the second pass with only pass-1's
LATTICE forced (RotationIndexer::ForceLattice), which drops pass-1's refined
per-frame orientation, rotation axis and search metadata (ForceLattice sets a
stub search result and leaves updated_geom_/axis_ unset) - so the re-run
integrated markedly worse than de-novo at the same geometry (measured ~3.3
lower ISa / ~1.5% higher R-meas on the affected dataset).

Capture pass-1's full RotationIndexerResult and force THAT (ForceResult) in the
re-run instead. The second pass then integrates at the refined geometry with
pass-1's refined orientation on the correct cell, matching (slightly beating)
de-novo pass-1 quality - a genuine refined-geometry two-pass result, not a
fallback to the header-geometry pass. Isolation confirmed the geometry move
itself and the mosaicity override were not the cause; the lattice-only force
was. The guard still fires only when the second-pass cell is markedly larger
than pass-1 (a spurious supercell), so all other datasets are untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 00:14:09 +02:00
leonarski_fandClaude Opus 4.8 e6cb627c6f rugnux: two-pass supercell-collapse guard + post-refine fixes
Build Packages / build:viewer-tgz:cpu (push) Successful in 7m54s
Build Packages / build:viewer-tgz:cuda (push) Successful in 8m44s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 13m53s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 14m0s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 14m16s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 14m23s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 14m38s
Build Packages / build:windows:nocuda (push) Successful in 15m45s
Build Packages / build:windows:nocuda (pull_request) Failing after 58s
Build Packages / build:windows:cuda (push) Successful in 18m39s
Build Packages / build:rpm (rocky8) (push) Successful in 11m12s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 12m50s
Build Packages / XDS test (durin plugin) (push) Successful in 10m5s
Build Packages / Generate python client (push) Successful in 39s
Build Packages / Build documentation (push) Successful in 1m5s
Build Packages / Create release (push) Skipped
Build Packages / build:rpm (ubuntu2404) (push) Successful in 13m44s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 14m18s
Build Packages / build:rpm (rocky9) (push) Successful in 14m44s
Build Packages / DIALS test (push) Successful in 14m37s
Build Packages / XDS test (neggia plugin) (push) Successful in 9m17s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 10m2s
Build Packages / build:windows:cuda (pull_request) Successful in 13m7s
Build Packages / build:viewer-tgz:cpu (pull_request) Successful in 7m23s
Build Packages / build:viewer-tgz:cuda (pull_request) Successful in 7m57s
Build Packages / build:rpm (rocky8_nocuda) (pull_request) Successful in 10m44s
Build Packages / build:rpm (ubuntu2404_nocuda) (pull_request) Successful in 11m39s
Build Packages / build:rpm (rocky9_nocuda) (pull_request) Successful in 12m41s
Build Packages / build:rpm (ubuntu2204_nocuda) (pull_request) Successful in 11m50s
Build Packages / build:rpm (rocky8_sls9) (pull_request) Successful in 11m6s
Build Packages / build:rpm (rocky9_sls9) (pull_request) Successful in 13m23s
Build Packages / build:rpm (rocky8) (pull_request) Successful in 11m4s
Build Packages / build:rpm (ubuntu2204) (pull_request) Successful in 11m59s
Build Packages / build:rpm (ubuntu2404) (pull_request) Successful in 12m11s
Build Packages / Generate python client (pull_request) Successful in 16s
Build Packages / build:rpm (rocky9) (pull_request) Successful in 12m45s
Build Packages / Create release (pull_request) Skipped
Build Packages / Build documentation (pull_request) Successful in 1m20s
Build Packages / XDS test (durin plugin) (pull_request) Successful in 8m5s
Build Packages / XDS test (JFJoch plugin) (pull_request) Successful in 9m28s
Build Packages / DIALS test (pull_request) Successful in 15m13s
Build Packages / XDS test (neggia plugin) (pull_request) Successful in 8m54s
Build Packages / Unit tests (push) Failing after 1h36m51s
Build Packages / Unit tests (pull_request) Failing after 1h32m3s
- Guard the two-pass second pass against a bistable de-novo lattice search
  collapsing onto a spurious supercell after the small post-refine geometry
  move: when pass 2's cell volume balloons past 1.5x pass 1, re-run pass 2 with
  pass-1's correct lattice forced (still integrating at the refined geometry).
  A genuine de-novo demotion to a smaller primitive (pass2 <= pass1) is left
  untouched.
- Keep an empty output prefix empty in the "compute stats, persist nothing"
  mode so the two-pass first pass does not write stray _01_* files.
- Fix the stale ProcessConfig doc-comment to describe the actual output
  (canonical unsuffixed _* second pass, header-geometry _01_* first pass) and
  the --rotation-no-postrefine default-on flag, not the removed _02_*.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 23:14:41 +02:00
leonarski_fandClaude Opus 4.8 812ea94a86 rugnux: code-review fixes across the offline path
- frontend: drop the CBF/TIFF file-format menu items; the broker now rejects
  those formats, so offering them in the picker was a dead, error-producing
  choice (the enum values remain only for back-compat decode).
- RugnuxCommandLine: emit --background-trim (when it differs from the 0.10
  default) and --stills-modulation, so the viewer "copy command line" matches
  what the settings dock actually configured.
- ReindexAmbiguity: multiply the reference-CC intensity by rlp rather than
  dividing by it, matching image_scale_corr everywhere else; drop the now
  unused SafeInv helper.
- rugnux_cli: parse --refine-geometry with the hardened bounded parser instead
  of atoi (reject trailing garbage; bound N so refine_frames*50 can't overflow).
- LoadFCalcFromMtz: drop the generic "first type-F column" catch-all so a
  reference MTZ carrying only map coefficients (FWT/FC_ALL) can't silently seed
  CCref from the wrong quantity.
- WriteReflections: consolidate the duplicated MTZ Friedel/anomalous branches
  into one shared row list + column/row emission (behaviour-preserving).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 23:14:25 +02:00
leonarski_fandClaude Opus 4.8 99617c549a docs: rc.160 changelog + CPU_DATA_ANALYSIS/RUGNUX updates
Document the newest rc.160 work: rotation geometry post-refinement (now
default-on), the opt-in per-batch relative-B, the always-on radiation-damage
report, net-absence space-group centering ranking, and software/geometry
provenance in the merged mmCIF. Add a §7.5 for the two-pass post-refinement.
Drop the removed .hkl output from RUGNUX.md and add the new CLI options
(--rotation-no-postrefine, --relative-b, --refine-geometry, --background-trim,
--stills-modulation, --still-partiality, --spot-low-resolution,
--min-pix-per-spot, -S symbol, -r flex).

Add a plain-lysozyme (HEWL) carve-out to the no-sample-identity rule: the
field's universal standard specimen and its reference cell are allowed, while
named user datasets and every other sample stay forbidden.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 23:14:09 +02:00
leonarski_fandClaude Opus 4.8 fcafc61be6 rugnux: two-pass refined pass takes the canonical (unsuffixed) output name
In the rotation two-pass geometry post-refine, the second (refined-geometry)
pass is the result users want, so give it the plain <prefix>_* name and keep
the first (header-geometry) pass as <prefix>_01_*. Previously the refined pass
was <prefix>_02_*, leaving no plain <prefix>_* output; a downstream consumer
that expects the canonical name now finds the refined result there.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 22:21:07 +02:00
leonarski_fandClaude Opus 4.8 09e4c1116e rugnux/viewer: rotation geometry post-refine on by default
The two-pass rotation geometry post-refine (post-refine detector distance /
beam / cell / rotation axis from the whole sweep, then re-integrate; writes
both passes, _01 header geometry and _02 refined) is robust across the test
battery, so make it the default.

- rugnux CLI: replace the opt-in --rotation-post-refine with an opt-out
  --rotation-no-postrefine; a rotation full-analysis run now post-refines
  unless disabled.
- jfjoch_viewer: add a "Post-refine geometry (rotation, two-pass)" checkbox
  to the analyze-dataset dialog, default on for rotation datasets (a no-op
  for stills), mirroring the existing stills "Refine geometry" toggle; it
  sets ProcessConfig::rotation_postrefine_geometry, which the viewer already
  feeds to the same Rugnux::Run the CLI uses.
- The "Copy command" line renders --rotation-no-postrefine when the box is
  cleared on a rotation dataset.

The ProcessConfig struct default stays off, so the online broker path is
unchanged; only the two user-facing entry points (CLI, viewer) default it on.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 22:14:53 +02:00
leonarski_fandClaude Opus 4.8 6e277668b6 rugnux: header line for the per-image _image.dat scaling table
The offline per-image scaling table had bare numeric columns. Prefix it with
a '#' comment header (image_number scale_G bfactor_Ang2 mosaicity_deg
wedge_deg cc_to_merge cc_n) so it is self-describing; numpy.loadtxt / gnuplot
skip the comment line, so existing consumers are unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 22:08:18 +02:00
leonarski_fandClaude Opus 4.8 c5cfdcef7e rugnux: per-batch relative-B correction + radiation-damage B monitor
Rotation scaling modelled dose-dependent scattering power with a single
global relative-B decay slope only (RefineDecay); per-frame refinement was
scale-only. Add a per-batch relative Debye-Waller B, both as an opt-in
correction and as an always-on measurement.

- FitRelativeBCurve / SolveCurvatureSmoothedB: per rotation-range batch, fit
  the s^2 slope of ln(Iref/Iobs) that the resolution-flat per-frame G leaves,
  regularised by a second-difference (curvature) penalty so a genuine smooth
  relative-B is kept while resolution-correlated noise (which an unconstrained
  per-batch fit would chase into an oscillating curve) is suppressed.

- Correction (--relative-b[=deg], default off): applied after RefineDecay,
  gated by a physical peak-to-peak floor and cross-validated by ASU-group
  parity (a per-batch parameter owns whole frames, so it is scored on held-out
  equivalents, not held-out frames). On a battery re-scaling identical stored
  reflections it is a no-op on well-behaved data and a small gain on
  radiation-damaged rotation data; never a regression.

- Radiation-damage monitor (always on for rotation, report-only): measure the
  relative-B change from the pristine low-dose start of the run to its end
  (a whole-run-mean reference inverts on damaged data) plus the per-batch
  curve, and report them on the command line (in the radiation-damage report
  and the merge statistics) and in the mmCIF (_reflns.jfjoch_radiation_damage_
  relative_B and a per-batch loop). A large magnitude flags radiation damage,
  complementing the existing per-image CC / mosaicity read.

- --scale now reproduces the de-novo rotation merge (it previously omitted
  scale-fulls and smooth-G, silently using a weaker model), and honours
  --relative-b, so an offline re-scale matches the full pipeline.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 22:08:09 +02:00
leonarski_fandClaude Opus 4.8 e97a610091 rugnux: reindex the de-novo primitive cell to the group's conventional setting (two-pass)
When the two-pass second pass indexes de novo and the pseudo-symmetry guard
keeps a triclinic (primitive) cell - a huge oblique cell whose constrained
centred refine is ill-posed - the reflections are left in the primitive frame
while the reused merge space group expects its conventional setting, so the
merge folds the wrong equivalents (a centred group's half-set CC1/2 collapses).
Reindex the integrated reflections into the group's conventional setting first,
using the same exact-integer primitive->conventional change of basis the
space-group search applies to a demoted result, gated on LatticeSearch
recovering the group's own metric (crystal system + centring).

Fires only for a demoted-triclinic indexing under a higher-symmetry reused
group; every other dataset is bit-identical. Closes the last centred-space-group
case where the second pass's merge was frame-mismatched (CC1/2 72 -> 98).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 20:03:47 +02:00
leonarski_fandClaude Opus 4.8 290c30b9be rugnux: post-refine commits detector/cell geometry only for a small (< 1 %) move
The rotation geometry post-refine committed the detector distance and cell
scale on any cross-validated improvement within a loose 3 % / 2 % bound. On a
multi-lattice crystal the second lattice's spots bias every cross-validation
fold the same way, so the "it improved" test cannot catch it and a spurious
distance<->cell pair (their radial degeneracy) is committed far off the true
geometry, losing reflections in the re-integration.

Tighten the commit bound to < 1 % (a calibrated header needs < ~0.6 %). The
move SIZE discriminates a genuine header correction from the multi-lattice
failure far better than the fit residual, which genuinely marginal (noisy or
ice-ring) data shares with the multi-lattice case - so a real ~0.3 % correction
is kept while the ~1.7 % multi-lattice one is rejected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 19:41:12 +02:00
leonarski_fandClaude Opus 4.8 0ebf90a1ad rugnux: two-pass second pass re-indexes de novo, reuses the group for the merge only
The two-pass second pass reused pass-1's space group for both the indexer and
the merge. Reusing it in the INDEXER disables the de-novo pseudo-symmetry
safeguards, so build_sr adopts a wrong cell: a metrically pseudo-centred
crystal doubles into a super-cell (every real reflection plus phantom
half-integer ones - so the merge keeps CC1/2 but halves <I/sigma>), and a huge
oblique cell's constrained monoclinic refine is ill-posed, diverges, and the
re-indexing collapses.

Decouple the two: the second pass now indexes DE NOVO (the group is cleared
before it, safeguards on) so it recovers the true cell, and pass-1's group is
reinstated for the MERGE ONLY, just before RotationScaleMerge, so the symmetry
stays fixed exactly as a user-fixed group would - no re-search, no flip. A
reindex-derived group is still left to re-search.

Neutral for genuine-symmetry data (its de-novo cell already matches the
group); it recovers the pseudo-symmetric cases that previously collapsed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 19:41:12 +02:00
leonarski_fandClaude Opus 4.8 1089b75906 rugnux: two-pass writes both passes (_01 header geometry, _02 refined)
The two-pass geometry post-refinement previously wrote only the second
(refined-geometry) pass. Write both instead, so the header-geometry and
post-refined results can be compared directly and the better one kept:

  <prefix>_01_*  first pass, at the header geometry (the plain single-pass
                 baseline)
  <prefix>_02_*  second pass, at the post-refined geometry

Each is a complete standalone result - its own merged reflections
(.mtz/.cif), per-image _process.h5 (with --write-process-h5), ice-ring
flags and mmCIF detector geometry, all consistent with the geometry that
pass actually used.

Mechanics: the pre-pass now stores the post-refined detector geometry
instead of applying it mid-pass (so the first pass finishes and writes at
the header geometry), and no longer returns early - it continues through the
full write. Run() then applies the stored geometry, lets the second pass
re-search a reindex-derived space group, and routes the two passes to the
_01 / _02 prefixes. The second pass's result is unchanged from before.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 17:46:20 +02:00
leonarski_fandClaude Opus 4.8 c140b3567d rugnux: restrain the gauge-weak beam centre toward the header in geometry refinement
Single-axis rotation has a gauge degeneracy: rotating the whole experiment
about the spindle leaves every spot position unchanged, so the beam-centre
component parallel to the spindle is a null / under-determined direction.
Refining it freely lets it wander a few pixels and absorb centroid
systematics into a wrong beam that the co-refined orientation keeps
position-consistent.

Add a soft header prior on that one component in the shared XtalOptimizer:
residual = w*(beam[parallel] - header), with w set so the restraint behaves
like a sigma_px-pixel prior competing with the positional residuals. The
gauge direction has ~zero data sensitivity, so the prior pins it near the
LaB6-monitored header, while a real, well-supported drift can still overcome
it (the beam does drift). One restraint covers all three refinement sites at
once: the noisy accumulated-spot primary, the per-frame filter, and
post-refine.

Validated against independent XDS processing: neutral on well-determined
data (the gauge direction has no effect there), and a real low-resolution
accuracy gain where the free refinement had otherwise wandered off the
header - the merged intensities move back into agreement with XDS while the
internal CC1/2, which is blind to this, barely changes. No space-group
determinations change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 17:31:45 +02:00
leonarski_fandClaude Opus 4.8 c9ed9c3776 rugnux: two-pass reuses pass-1 space group; floor the fed mosaicity
The second pass re-searching the space group at the slightly changed geometry
could flip a borderline determination (cubic <-> orthorhombic) and mix the two
passes, collapsing the multiplicity. Fix it: the pre-pass now continues through
the space-group search, so the determined group is already fixed on experiment_
and the second pass reuses it instead of re-searching. The lattice is NOT forced
- the second pass re-indexes at the refined geometry so the cell stays
self-consistent with it (forcing the pre-pass lattice would pin the nominal cell
and undo the refinement). A reindex-derived group (the centred-lattice test) is
in a conventional setting the indexer's primitive frame does not share, so it is
cleared for the second pass to re-search (else its indexing fails outright).

Also floor the mosaicity fed to the second pass's prediction at each frame's own
estimate (max), so a too-narrow smoothed value can never make prediction drop
reflections.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 13:04:04 +02:00
leonarski_fandClaude Opus 4.8 1b91823eed rugnux: --rotation-post-refine two-pass geometry post-refinement (opt-in)
A first pass integrates and post-refines the detector geometry from the observed
diffraction, applies it to experiment_, and a second pass re-indexes and
re-integrates with it - only the second pass is written, so the _process.h5 / mtz
(and the ice-ring flags, which move with the geometry) reflect the refined values.
Default off; enable with --rotation-post-refine.

PostRefineRotationGeometry refines in two SEPARATE cross-validated steps (a joint
fit of everything is fragile - the same lesson as integration, where refining the
profile width and the scale jointly fails but separately works):
  * Step A: cell scale + rotation axis from the observed rocking centroids phi_obs
    (a distance-independent excitation residual, so it pins the absolute cell scale
    that the positional residual leaves degenerate with distance).
  * Step B: detector distance + beam centre from the observed spot positions, with
    the cell fixed at step A.
Each step commits only if it lowers a held-out (deterministic split-half) residual,
else that part of the geometry is left at nominal.

Rugnux::Run wraps RunPipeline(write_output, geometry_prepass); the pre-pass runs
the first scale/merge so RotationScaleMerge fits a frame-order-smoothed mosaicity,
which is captured and fed to the second pass's Bragg prediction (via
IndexAndRefine::SetPredictionMosaicityOverride) rather than re-derived per image.
observed_x/y were plumbed through the profile integrator earlier for the positional
residual. rugnux_vs_xds.py gains --extra-args to sweep the option over the battery.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 12:19:33 +02:00
leonarski_fandClaude Opus 4.8 f396385e11 rugnux: record the detector distance and beam centre in the merged mmCIF
Add _diffrn_detector.jfjoch_{distance_mm,beam_center_x_pxl,beam_center_y_pxl} to
the merged mmCIF header, as feedback of the geometry the data was actually
reduced with. When geometry refinement ran (the rotation two-pass or the stills
global refinement, which update experiment_ before the written pass) these are
the refined values; otherwise they are the nominal header geometry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 12:19:16 +02:00
leonarski_fandClaude Opus 4.8 9bfecaadf5 beam_stop: add ShadowFinder detection class (unwired)
Add image_analysis/beam_stop/ShadowFinder.{h,cpp} and SHADOW_FINDER.md: a
self-contained beam-stop shadow detector that accumulates images via AddImage()
and returns a mask from GetMask(), mirroring the shape of DarkMaskAnalysis.

It detects the beam-stop shadow (central disk + holder arm) as an azimuthal
anomaly: an iterated radial-median background baseline, a ratio threshold, a
connectivity-to-beam-centre anchor with module-gap bridging, a central low-res
disk guard capped just inside the innermost reflection, and a reflection guard
that never masks a pixel that recorded real signal.

Not yet wired: not added to image_analysis/CMakeLists.txt and no PixelMask /
Rugnux / viewer changes. SHADOW_FINDER.md documents the algorithm and the
deferred offline (Rugnux bit 9 + viewer user-mask) integration plan.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 12:05:05 +02:00
leonarski_fandClaude Opus 4.8 1911875e1c integration: carry the box-sum observed centroid through the profile path
Pass A (the box-sum) always computes an intensity-weighted centroid (the
observed spot position), but it was only emitted in BoxSum mode. Rotation
integration runs the profile path, so observed_x/y were left NAN there and no
positional (detector<->reciprocal) residual was possible downstream.

Emit the Pass-A centroid in the profile path too (CPU) and copy d_obs_x/d_obs_y
back in all modes (GPU) - Pass A fills them regardless of integrator mode.
observed_x/y are consumed only by the diagnostic HDF5 reflection table and the
viewer read-back; nothing in scaling/merge reads them, so merged output is
unchanged - the _process.h5 observed_x/y columns simply go from NAN to the real
centroid. This makes the observed position available to post-refinement.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 10:23:17 +02:00
leonarski_fandClaude Opus 4.8 7ceffde5a4 rugnux: rank space groups by net absences, not gross (fix C222 over-centering)
Build Packages / Unit tests (pull_request) Successful in 1h1m38s
Build Packages / build:windows:nocuda (pull_request) Successful in 15m24s
Build Packages / build:windows:cuda (pull_request) Successful in 17m21s
Build Packages / build:viewer-tgz:cpu (pull_request) Successful in 8m51s
Build Packages / build:viewer-tgz:cuda (pull_request) Successful in 8m21s
Build Packages / build:rpm (ubuntu2404_nocuda) (pull_request) Successful in 10m28s
Build Packages / build:rpm (rocky8) (pull_request) Successful in 12m54s
Build Packages / build:rpm (rocky9) (pull_request) Successful in 13m33s
Build Packages / build:rpm (ubuntu2204) (pull_request) Successful in 13m8s
Build Packages / build:rpm (ubuntu2404) (pull_request) Successful in 11m45s
Build Packages / DIALS test (pull_request) Successful in 14m34s
Build Packages / XDS test (durin plugin) (pull_request) Successful in 7m39s
Build Packages / XDS test (JFJoch plugin) (pull_request) Successful in 7m48s
Build Packages / XDS test (neggia plugin) (pull_request) Successful in 5m56s
Build Packages / Generate python client (pull_request) Successful in 12s
Build Packages / Build documentation (pull_request) Successful in 52s
Build Packages / Create release (pull_request) Skipped
Build Packages / build:rpm (ubuntu2204_nocuda) (pull_request) Successful in 16m25s
Build Packages / build:rpm (rocky9_nocuda) (pull_request) Successful in 16m38s
Build Packages / build:rpm (rocky8_nocuda) (pull_request) Successful in 16m52s
Build Packages / build:rpm (rocky8_sls9) (pull_request) Successful in 16m46s
Build Packages / build:rpm (rocky9_sls9) (pull_request) Successful in 17m40s
Build Packages / Unit tests (push) Successful in 1h11m44s
Build Packages / build:windows:nocuda (push) Successful in 10m57s
Build Packages / build:viewer-tgz:cpu (push) Successful in 6m47s
Build Packages / build:viewer-tgz:cuda (push) Successful in 8m11s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 11m5s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 11m8s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 16m3s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 9m13s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 16m31s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 12m22s
Build Packages / build:rpm (rocky8) (push) Successful in 12m4s
Build Packages / build:rpm (rocky9) (push) Successful in 15m43s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 15m39s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 14m28s
Build Packages / DIALS test (push) Successful in 15m19s
Build Packages / XDS test (durin plugin) (push) Successful in 8m42s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 8m41s
Build Packages / XDS test (neggia plugin) (push) Successful in 8m19s
Build Packages / Generate python client (push) Successful in 17s
Build Packages / Build documentation (push) Successful in 1m4s
Build Packages / Create release (push) Skipped
Build Packages / build:windows:cuda (push) Successful in 12m46s
Stage B of SearchSpaceGroup chose the largest centering that explained the most
absences and was self-consistent, ranking candidates by the gross observed-absent
count. A false super-centering over-claims: on a C222 crystal, F222 predicts every
C absence (all genuinely weak) PLUS a block of C-present reflections it wrongly calls
absent. Its absent class is then bimodal - many true zeros diluting a strong block -
so its mean <I/sigma>abs (and the violation-rate arm) slip under the centering
strength gate, which cannot see the over-claim in isolation. With the gross-count
ranking F222 then beat the true C222, and the strength gate is scale-invariant here,
so real C-centered data trips it identically (the rotation battery just has no
C-centered crystal on this path; the synthetic unit test does).

Rank instead by the absences GENUINELY explained, absent_observed - absent_violations,
then by fewer violations, then lower space-group number. C222 and F222 net to the same
count (F222's genuine absences ARE C222's), so the fewer-violations tie-break keeps the
honest, less-centred C222. Symmetric: on a real F222 crystal F explains strictly more
weak absences and still wins. Also tighten the "indistinguishable alternatives" grouping
to require the same absent AND violation counts, so a super-centering is never reported
as an equal alternative. No tuned threshold is changed; the ranking is a no-op for any
0-violation winner.

Fixes the SearchSpaceGroup C222 synthetic-space-group test. Rotation battery (32
crystals, de-novo) is space-group-identical to before.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 22:35:12 +02:00
leonarski_fandClaude Opus 4.8 742a1c1b94 rugnux: identify the producing software in the merged mmCIF and MTZ
Build Packages / build:windows:nocuda (pull_request) Successful in 15m47s
Build Packages / build:windows:cuda (pull_request) Successful in 17m52s
Build Packages / build:viewer-tgz:cpu (pull_request) Successful in 8m17s
Build Packages / build:viewer-tgz:cuda (pull_request) Successful in 6m44s
Build Packages / build:rpm (rocky8_nocuda) (pull_request) Successful in 9m25s
Build Packages / build:rpm (rocky9_nocuda) (pull_request) Successful in 10m11s
Build Packages / build:rpm (ubuntu2204_nocuda) (pull_request) Successful in 9m33s
Build Packages / build:rpm (ubuntu2404_nocuda) (pull_request) Successful in 9m19s
Build Packages / build:rpm (rocky8_sls9) (pull_request) Successful in 10m1s
Build Packages / build:rpm (rocky9_sls9) (pull_request) Successful in 11m27s
Build Packages / build:rpm (rocky8) (pull_request) Successful in 10m15s
Build Packages / build:rpm (ubuntu2204) (pull_request) Successful in 10m33s
Build Packages / DIALS test (pull_request) Successful in 10m33s
Build Packages / XDS test (durin plugin) (pull_request) Successful in 7m24s
Build Packages / XDS test (JFJoch plugin) (pull_request) Successful in 7m47s
Build Packages / XDS test (neggia plugin) (pull_request) Successful in 7m10s
Build Packages / Generate python client (pull_request) Successful in 24s
Build Packages / Build documentation (pull_request) Successful in 1m4s
Build Packages / Create release (pull_request) Skipped
Build Packages / build:viewer-tgz:cpu (push) Successful in 6m51s
Build Packages / build:viewer-tgz:cuda (push) Successful in 7m43s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 12m17s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 12m54s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 12m28s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 11m57s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 10m58s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 10m48s
Build Packages / DIALS test (push) Successful in 13m12s
Build Packages / XDS test (durin plugin) (push) Successful in 9m10s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 8m40s
Build Packages / XDS test (neggia plugin) (push) Successful in 8m25s
Build Packages / Generate python client (push) Successful in 16s
Build Packages / Build documentation (push) Successful in 1m7s
Build Packages / Create release (push) Skipped
Build Packages / build:windows:nocuda (push) Failing after 2m35s
Build Packages / build:windows:cuda (push) Successful in 18m20s
Build Packages / build:rpm (ubuntu2404) (pull_request) Successful in 13m16s
Build Packages / build:rpm (rocky9) (pull_request) Successful in 15m14s
Build Packages / build:rpm (rocky8) (push) Successful in 12m6s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 11m47s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 12m13s
Build Packages / build:rpm (rocky9) (push) Successful in 12m32s
Build Packages / Unit tests (pull_request) Failing after 59m4s
Build Packages / Unit tests (push) Failing after 51m23s
mmCIF: set _software.name to 'Rugnux' (was 'Jungfraujoch') and correct
_software.classification to the CIF-dictionary value 'data reduction'.
MTZ: add the producing software to the header via the title and a HISTORY
record ("From Rugnux <version>, data reduction"), the CCP4 provenance channel,
which was previously empty.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 21:29:47 +02:00
leonarski_fandClaude Opus 4.8 e209069ccd docs: compress the rc.160 changelog entries to one-line summaries
The rc.160 entries were multi-sentence explanations; rewrite each as a short
statement of what changed (feature / flag / behaviour), roughly under 200
characters, matching a normal changelog.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 21:02:34 +02:00
leonarski_fandClaude Opus 4.8 3a23c79ea4 docs: document the asymptotic ISa reporting and the azint Q-field precision
CHANGELOG: describe reporting ISa at its asymptotic definition (read from the
strong equivalents, relaxed threshold on weak/damaged data) and the frontend
azimuthal-integration Q fields gaining 5-decimal precision.
CPU_DATA_ANALYSIS: update the error-model section - ISa is the counting-
subtracted strong-reflection asymptote (and drives the systematic floor), not
1/b of the whole-range fit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 20:58:38 +02:00
leonarski_fandClaude Opus 4.8 59e260876a rugnux: recover the asymptotic ISa on weak / radiation-damaged data
Build Packages / build:viewer-tgz:cpu (push) Successful in 7m2s
Build Packages / build:viewer-tgz:cuda (push) Successful in 7m47s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 13m54s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 14m13s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 13m44s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 13m17s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 14m14s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 13m28s
Build Packages / build:rpm (rocky8) (push) Successful in 12m14s
Build Packages / build:rpm (rocky9) (push) Successful in 13m16s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 13m20s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 12m28s
Build Packages / DIALS test (push) Successful in 13m47s
Build Packages / XDS test (durin plugin) (push) Successful in 8m18s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 8m54s
Build Packages / XDS test (neggia plugin) (push) Successful in 8m11s
Build Packages / Generate python client (push) Successful in 35s
Build Packages / Build documentation (push) Successful in 1m6s
Build Packages / Create release (push) Skipped
Build Packages / build:windows:nocuda (push) Successful in 15m47s
Build Packages / build:windows:cuda (push) Failing after 3m45s
Build Packages / Unit tests (push) Failing after 49m43s
The asymptote was read only from groups with I/sigma > 20 and required at
least 100 of them, so weak or radiation-damaged data (few strong reflections)
fell back to the higher whole-range b and reported an over-conservative ISa.
Relax the I/sigma threshold in a second tier (>= 50 groups above I/sigma 10)
when the tight one is unmet; the per-group counting-subtracted estimate is
stable down to that threshold. Data with many strong groups is unchanged (it
keeps the tight-threshold asymptote); weak / damaged data now reports the
asymptote its own reflections support instead of falling back.

Battery (32 crystals): no space-group, R_meas or CC1/2 change; strong sets
unchanged; e.g. a room-temperature radiation-damage series recovers ISa 5.4 ->
11.2 (its data already exceeds the reference on CC1/2 and R_meas).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 20:54:03 +02:00
leonarski_fandClaude Opus 4.8 88359a57ee rugnux: report ISa at its asymptotic definition (strong-reflection limit)
ISa is the I->infinity limit of the signal-to-noise (Diederichs, Acta Cryst.
D66 (2010), 733-740), i.e. the reproducibility of the strongest reflections.
The reported value was taken as 1/b of the whole-intensity-range error-model
fit, whose systematic term b is raised by a mild excess of scatter at
intermediate intensity, so it understated that limit.

Read the asymptote directly instead: for each well-measured reflection group the
counting-subtracted fractional scatter of its symmetry mates estimates the
systematic term, and the robust median over strong groups is the asymptote. It
falls back to the whole-range b when too few strong groups exist (weak or
low-multiplicity data). The reported ISa and the merged-sigma systematic floor
use this value, so merged I/sigma approaches ISa.

The (a, b) fit and the per-observation error model are unchanged, so the merge
weights, anomalous statistics and chi^2 are untouched, and CC1/2 and R_meas
(which do not depend on sigma) are bit-identical. Battery (32 crystals): no
space-group or indexing change, R_meas and CC1/2 unchanged, ISa rises to the
true asymptote of the data.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 20:54:03 +02:00
leonarski_fandClaude Opus 4.8 174b9585c5 docs: document SigAno and the low-energy centering fix
CHANGELOG (rc.160): add the centering rate-gate recovery on weak/low-energy data
and the SigAno anomalous signal-to-noise statistic.

CPU_DATA_ANALYSIS: describe SigAno in the merging-statistics section - its
definition, the standard PDBx mmCIF items, and why a half-set anomalous CC is not
used (complementary halves drive it negative on weak shells) - and note the
floor-independent centering-acceptance test in the space-group-determination notes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 20:54:03 +02:00
leonarski_fandClaude Opus 4.8 7fe12773de rugnux: report anomalous signal-to-noise SigAno (stats table + mmCIF)
Compute SigAno = <|I(+)-I(-)|>/<sigma(I(+)-I(-))> per report shell and overall
from the full-multiplicity I(+)/I(-) Bijvoet split, store it on
MergeStatisticsShell, and surface it in the console merge-statistics table (new
SigAno column) and the mmCIF via the standard wwPDB PDBx items
_reflns.pdbx_absDiff_over_sigma_anomalous (overall) and
_reflns_shell.pdbx_absDiff_over_sigma_anomalous (per shell) - the dictionary's
home for this quantity, so no jfjoch_ local item is needed (unlike ISa).

SigAno approaches ~0.8 for pure noise and rises above 1 with real anomalous
signal. A half-set anomalous CC is deliberately not used: its two half estimates
are complementary partitions of one observation pool (dI0 + dI1 = 2*dI_full), so
differencing the two Bijvoet hands cancels the large common intensity that keeps
CC1/2 non-negative and, once the anomalous SNR per half drops below 1, drives the
correlation towards -1 rather than 0 - misrepresenting a weak-but-real signal.

Emitted only when an anomalous split was made (has_anom guard), so a non-anomalous
merge keeps its stats block and shell-loop columns byte-for-byte. Export-neutral:
the I(+)/I(-)/IMEAN accumulation is unchanged. On low-energy S-SAD test data SigAno
tracks XDS (13 keV null ~0.89, 6 keV ~1.44, 5 keV ~1.5-1.7) and never goes
spuriously negative.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 20:54:03 +02:00
leonarski_fandClaude Opus 4.8 1b5eb80ba4 rugnux: recover I-centering on weak / low-energy data (centering rate gate)
The de-novo centering gate promoted to a centred lattice only when the mean
signed <I/sigma> of the centering-absent class was <= 0.5x that of the present
class. Weak / low-energy data carry a positive intensity floor (background /
profile leakage) that lifts <I/sigma> of the genuinely-extinct class to ~1.5-2.3
instead of ~0; when the present class is itself weak that additive floor inflates
the ratio past the bound and the true centering is missed. An I-centred cubic
crystal recorded at 5 and 13 keV sat at ratio ~0.57 and stayed primitive P2_1 3,
while the same crystal form at 6 keV (stronger data) correctly merged as I23 - an
energy-dependent space group for one physical crystal.

Add a second, floor-independent acceptance path OR'd with the mean-ratio: the
centering-absent class's strong-reflection rate (violations / absent) versus the
present class's own strong rate. A false centering (absent as strong as present)
fails both arms; a true weak centering passes the rate arm. Battery SG sweep vs
XDS: the low-energy datasets now adopt I23, and no crystal is newly over-centred.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 20:54:03 +02:00
leonarski_fandClaude Opus 4.8 32c7f9f59f rugnux: don't veto genuine high symmetry on excellent data (b-veto floor)
The de-novo space-group search's systematic-b veto - which keeps a merohedral
twin in its true lower symmetry - is a RATIO test: reject a point-group promotion
whose merge error-model b balloons past 2x the parent subgroup's. That ratio is
meaningless when the parent b is near zero, on excellent data where symmetry
equivalents already agree almost perfectly. A genuine tetragonal 422 whose 222
parent sits at b=0.008 and 422 at b=0.049 (both tiny, ISa ~20) reads as a 6x
balloon and is wrongly demoted to 222.

Floor the parent b (min_systematic_b_for_veto = 0.05) before forming the ratio,
so the veto only judges a promotion once its b is a non-negligible fraction of I.
A real merohedral twin drives b to ~0.19 regardless of how clean the parent is,
so it is still caught (the insulin R3 + ~20% twin veto still fires, b=0.19 >
0.15). A P41212 58/58/150 crystal at 16 keV goes P212121 -> P41212; full
26-crystal rotation battery: only that crystal changes (its space group now
matches XDS, SG match 22->23/26), every other space group bit-identical.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 20:54:03 +02:00
leonarski_fandClaude Opus 4.8 afae1dec2f rugnux: index long finely-spaced axes (de-novo two-pass long-axis rescue)
De-novo two-pass rotation indexing collapsed on a crystal with a long, finely
spaced axis (a ~150 A c-axis at 16 keV): the unconstrained FFT either collapsed
the long axis to a short sub-multiple or let a denser supercell over-fit the
accumulated cloud - a small global-orientation error throws the many high-order
reflections off along the fine axis, so the true cell scores worst on the raw
cloud, and propagating that inaccurate global orientation to each frame fails.

Add a long-axis rescue that only runs when the standard pass indexes few
validation frames (<50%), so well-indexing crystals are untouched and keep the
fast path: re-run the first pass at a COARSE resolution (low-order reflections
only, where the fine axis stays robust) to recover the true metric, take the
recovered cell with the longest axis directly, then RE-INDEX at full resolution
with that cell as a reference (the -C path) - the reference-cell filter drops the
collapsed/supercell candidates and refines an accurate global lattice.

The scheme feed/index/validate loop is factored into a pick_best() lambda shared
by the standard and constrained passes (the standard pass is behaviour-preserved).
A P41212 58/58/150 test crystal goes 15% -> 99.89% indexed. Full 25-crystal
rotation battery: every other crystal's space group and cell BIT-IDENTICAL, and
the rescue fires only on the failing crystal.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 20:54:03 +02:00
leonarski_fandClaude Opus 4.8 799e1e15ec frontend: configurable decimal precision, 5 places for azint Q fields
Build Packages / build:viewer-tgz:cpu (push) Successful in 7m45s
Build Packages / build:viewer-tgz:cuda (push) Successful in 8m26s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 12m26s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 13m46s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 13m49s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 14m1s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 14m6s
Build Packages / build:windows:nocuda (push) Successful in 16m37s
Build Packages / build:windows:cuda (push) Successful in 18m27s
Build Packages / build:rpm (rocky8) (push) Successful in 12m13s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 13m21s
Build Packages / XDS test (durin plugin) (push) Successful in 8m22s
Build Packages / Generate python client (push) Successful in 29s
Build Packages / Build documentation (push) Successful in 1m5s
Build Packages / Create release (push) Skipped
Build Packages / build:rpm (rocky9) (push) Successful in 12m41s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 12m24s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 13m1s
Build Packages / DIALS test (push) Successful in 14m15s
Build Packages / XDS test (neggia plugin) (push) Successful in 7m30s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 8m20s
Build Packages / Unit tests (push) Failing after 58m14s
NumberTextField quantized every float input to 3 decimals, so the finest
q_spacing reachable through the UI was 0.001 - capping the azimuthal-integration
q-bin count around 200 regardless of the CPU/FPGA backend. Add an optional
`decimals` prop (default 3, unchanged elsewhere) and set it to 5 on the Q
spacing / Low Q / High Q fields, matching the q_spacing minimum of 1e-5.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 19:28:21 +02:00
leonarski_fandClaude Opus 4.8 65bc40e7c7 merge: deltaCChalf uses the deterministic HalfForImage split, not an RNG
Build Packages / build:viewer-tgz:cpu (push) Successful in 7m54s
Build Packages / build:viewer-tgz:cuda (push) Successful in 8m37s
Build Packages / build:windows:cuda (push) Failing after 9m13s
Build Packages / build:windows:nocuda (push) Successful in 10m57s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 13m8s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 14m0s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 13m56s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 14m6s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 14m6s
Build Packages / build:rpm (rocky8) (push) Successful in 11m48s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 12m43s
Build Packages / XDS test (durin plugin) (push) Successful in 7m58s
Build Packages / Generate python client (push) Successful in 31s
Build Packages / Build documentation (push) Successful in 58s
Build Packages / Create release (push) Skipped
Build Packages / build:rpm (rocky9) (push) Successful in 12m19s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 13m27s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 13m30s
Build Packages / DIALS test (push) Successful in 14m23s
Build Packages / XDS test (neggia plugin) (push) Successful in 7m58s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 8m43s
Build Packages / Unit tests (push) Failing after 1h0m21s
MergeOnTheFly::DeltaCChalfReject assigned its CC1/2 half-sets from a seeded
std::mt19937 drawn in image (call) order, whereas the actual merge, the
rotation merge, the GPU path and the R-free flags all split with the
deterministic HalfForImage(image_id) splitmix64 hash. So the deltaCChalf was
measured on a different half-partition than the reported CC1/2, and was
order-dependent (a reordered outcomes vector gave different halves).

Use HalfForImage(i) - i is the image's stable index, the same image_id AddImage
merges with - so deltaCChalf now reflects the exact CC1/2 split the statistics
report, order-independently.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 13:19:51 +02:00
leonarski_fandClaude Opus 4.8 0c33139983 rugnux: radiation-damage report for rotation (per-image CC vs dose)
Summarise the per-image scale the rotation merge already fits - the CC-to-merge
and mosaicity binned by frame (= dose) across the sweep - and flag a falling
per-image CC (or rising mosaicity) as the radiation-damage / crystal-decay
signature. A data-quality-vs-dose read complementary to the fitted decay
correction; the full per-image table is still written to <prefix>_scaling.txt.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 11:57:51 +02:00
leonarski_fandClaude Opus 4.8 b647cf454c rugnux: write I(+)/I(-) and F(+)/F(-) by default (rotation)
A rotation merge now keeps each acentric reflection's Bijvoet split - the
inverse-variance I(+)/I(-) from the same scaled fulls - even when the merge is
Friedel-averaged (the default, no -A). IMEAN stays the primary intensity and is
bit-identical to before; the split is purely additive and scaled
non-anomalously, so a weak anomalous signal is preserved in the output without
having to reprocess with -A. French-Wilson now also fills F(+)/F(-) from the two
hands (one pass, shared Wilson prior).

Writers: the default (Friedel-merged) MTZ and mmCIF now carry IMEAN plus
I(+)/I(-) and F/F(+)/F(-) whenever a reflection has an anomalous split (the
stills path, which computes none, keeps the previous columns). A missing mate or
a centric is emitted as the CCP4 missing-value flag (NaN).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 11:52:31 +02:00
leonarski_fandClaude Opus 4.8 b945444372 rugnux_vs_xds.py: find the current rugnux binary (build*/rugnux/rugnux)
The rugnux CLI target builds to build*/rugnux/rugnux; the old build*/tools/
rugnux paths are stale leftovers from a previous layout that cmake no longer
updates, so the harness could silently run weeks-old code. Pick the most
recently built binary among the candidates instead of a fixed order.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 10:46:09 +02:00
leonarski_fandClaude Opus 4.8 67a18357b5 rugnux: fix de-novo space-group centering and weak-data high symmetry
De-novo space-group search:
- Determine lattice centering from the strength of the systematically-absent
  class (its mean I/sigma vs the present class) instead of a per-reflection
  violation count. The count gate was brittle on noisy / obverse-reverse-
  twinned data, where enough genuinely-absent reflections cross I/sigma>3 to
  trip the 10% bound although the class is several-fold weaker, and wrongly
  kept a genuine R-centered lattice primitive. False centerings, whose absent
  class is as strong as the present one, stay rejected. Screws keep the count
  test (too few axial reflections to average).
- Recover a genuine high-symmetry point group when the merged error model is
  badly miscalibrated (weak, low-resolution data whose sigmas are far too
  small). The fixed-sigma chi^2 ratio then grows with point-group order for
  real symmetry too and wrongly rejects it (a true cubic group reached a
  chi^2 ratio ~14); the self-normalising systematic-b test stays valid, so
  once chi2_ref shows the ratio is untrustworthy the promotion is confirmed
  on the b-test alone. The balloon veto still rejects a twin. This is the gap
  left when the earlier log10(chi2_ref) widening was removed for the b-veto.

Also print the adopted space group and unit cell as a clean one-line summary
at the end of the run (de-novo or user-fixed -S), not only in the mmCIF.

Full rotation-test battery: exactly the two intended crystals change (both to
the correct answer, with lower R-meas and higher ISa), every other crystal
unchanged; space-group match 21->22/25.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 10:46:09 +02:00
leonarski_fandClaude Opus 4.8 d1f6b382a6 docs: rc.160 changelog (trim + scrub) and CPU_DATA_ANALYSIS updates
CHANGELOG: add the Wilson B, decay-CV and space-group b-veto entries; shorten
the verbose modulation / stills-modulation / trimmed-background entries and
remove the dataset identities from them.

CPU_DATA_ANALYSIS: the correction surfaces are now three (add modulation),
on by default, cross-validated on the sigma-independent metric; the background
trimmed mean applies to monochromatic stills as well as rotation (broadband
keeps the sigma-clip); document the dataset-wide Wilson B, the still-partiality
model, and the twin b-veto in the space-group search.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 09:25:39 +02:00
leonarski_fandClaude Opus 4.8 7d1fb8db77 bragg integration: clarify that the trimmed background applies to stills too
The background trimmed mean is gated on the beam (monochromatic vs broadband),
not on the acquisition mode: a monochromatic still (zero bandwidth) already
gets the trim by default, only broadband (non-zero bandwidth: pink-beam / DMM)
data keep the high-side sigma-clip. The comments, the settings doc and the
--background-trim help wrongly implied the trim was rotation-only / that stills
keep the sigma-clip. Wording only; no behaviour change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 09:23:13 +02:00
leonarski_fandClaude Opus 4.8 7a9d25850c rugnux: veto a b-ballooning merohedral-twin over-promotion (space-group search)
The systematic-b test (a genuine symmetry step barely moves the merge error
model's b; a merohedral twin, forcing non-equivalent reflections together,
balloons it) was only ever a RESCUE - it could promote a chi^2-borderline
genuine step but never demote a chi^2-passing one. So a partial twin whose
within-orbit scatter looks self-consistent (merged chi^2 below the ratio
bound) slipped through on chi^2 alone and was over-promoted to the holohedral
group, ballooning b and collapsing the merged ISa.

Make the same test a VETO: a chi^2-passing high-symmetry promotion whose b,
relative to the largest confirmed subgroup, exceeds max_systematic_b_veto is
kept in its true lower symmetry. Calibrated on the rotation-test battery,
where the largest genuine step (a P422 tetragonal) sits at b-ratio ~1.8 and a
merohedral R3->R32 twin at ~2.6 - an empty gap - so 2.0 catches the twin while
never demoting a genuine high-symmetry merge.

Battery space-group match 20->21/25 (an R3 case previously merged as R32 is
now correct), every other crystal unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 09:23:13 +02:00
leonarski_fandClaude Opus 4.8 e9a913f84b scale_merge: remove sample identities from SearchSpaceGroup comments
The point-group self-consistency comments named specific datasets when
illustrating the chi^2-ratio / systematic-b calibration. Describe the
crystallographic situation instead (a merohedral R3->R32 twin, a genuine
cubic step, a tetragonal P41212 case), per the repository's no-sample-names
rule. Comment-only; no behaviour change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 08:58:17 +02:00
leonarski_fandClaude Opus 4.8 3bfce24faa rugnux: score the decay cross-validation on the sigma-independent metric
RefineDecay's cross-validation still scored the held-out equivalents on a
studentized chi^2, while the absorption/modulation surfaces were switched to a
sigma-independent Rmeas-like agreement (sum|Is-Iref|/sum|Iref|) precisely
because a correction can "pass" a studentized gate by reshaping sigma without
tightening the intensities. The decay slope scales sigma up on late /
high-angle frames, so it is exposed to the same loophole. Score it the same
way.

On the rotation battery this rejects a spurious slope on a mis-indexed
monoclinic (P2_1) case: the studentized gate had accepted a physically absurd
-74 A^2 "decay" that cross-validated yet collapsed the error model (ISa
7.1 -> 1.1) and CC1/2 (to ~2%); the fractional gate scores it a -50% held-out
loss and skips it. A small genuine ~3 A^2 decay on another crystal now
cross-validates and engages, with CC1/2 unchanged. Every other crystal is
unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 08:58:17 +02:00
leonarski_fandClaude Opus 4.8 8bd0977833 rugnux_vs_xds.py: drop the removed --scaling-output flag
rugnux always writes both MTZ and CIF now (the --scaling-output option was
removed), so passing it made every crystal in the battery fail against the
current binary.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 08:58:17 +02:00
leonarski_fandClaude Opus 4.8 85cf826d2e rugnux: dataset Wilson B-factor estimate + robust per-image Wilson B
Add a dataset-wide isotropic Wilson B-factor estimate, the analogue of XDS's
"WILSON LINE ... B=" which we did not export. CalcGlobalWilsonB fits ln<I> vs
1/d^2 over the merged reflections (B = -2*slope), skipping the low-resolution
non-linear region (d > 4 A) and shells past the signal limit (<I/sigma> < 1)
so the estimate is insensitive to how far the merged data were carried. It is
diagnostic only - not fed back into scaling - and is written to the mmCIF
(_reflns.B_iso_Wilson_estimate), the printed merge statistics, and the log.

Also harden the per-image Wilson B (CalcWilsonBFactor): accept the fit only
when it is well-correlated and physically plausible (0 < B < 200 A^2), else
leave b_factor unset. A bad frame (an indexing glitch, too few reflections)
otherwise produced a wildly steep Wilson line and a B of several hundred A^2
that polluted the per-image plot; NaN is preferable to garbage.

Diagnostic-only: the merged intensities and every merge statistic are
byte-identical (verified baseline vs modified on the rotation battery).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 08:58:17 +02:00
leonarski_fandClaude Opus 4.8 3b168a1a46 viewer: expose detector-plane modulation and background trim in the settings dock
Two new controls in the interactive settings dock:

- Scaling section: a "Detector-plane modulation (stills)" checkbox that toggles
  the stills flat-field modulation surface (ScalingSettings::StillsModulation),
  alongside the existing decay/absorption "Correction surfaces" checkbox
  (rotation modulation is fitted there). Off by default.

- Bragg integration section: a "Background trim" checkbox + fraction that sets
  the symmetric trimmed-mean background fraction
  (BraggIntegrationSettings::BackgroundTrimFraction; 0 = plain ring mean).
  Defaults on at 0.10, matching the integrator default, so the viewer requests
  trimming for every dataset (the integration engine still applies its own
  per-mode gating).

Viewer-only change; compiles against the current settings API.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-17 07:48:10 +02:00
leonarski_fandClaude Opus 4.8 74d7589abe stills: optional detector-plane modulation (flat-field) correction
The stills scaling/merging path (ScaleOnTheFly + MergeOnTheFly) had no
correction surfaces, whereas rotation fits decay/absorption/modulation inside
RotationScaleMerge. Serial stills hammer the same detector regions shot after
shot, so a detector-plane (flat-field) systematic is at least as well
determined there as in rotation - it just had no home.

Add MergeOnTheFly::RefineModulation: a 16x16 multiplicative surface over the
predicted detector position, fit against the merged reference and folded into
each reflection's image_scale_corr before the error model and the merge. It
mirrors RotationScaleMerge::ApplyCellSurface - alternating per-cell fit with a
den-weighted geometric-mean gauge (never drifts the overall scale) and
Tikhonov pull to 1 - and is cross-validated the same way: fit the surface on
even images, score the held-out odd equivalents by a sigma-independent
R-meas-like agreement (a fractional metric a sigma-reshaping surface cannot
game), and apply the full-data surface only if the held-out gain clears a
margin. A no-op when the systematic is absent or the data too sparse (< 8 obs
per cell), so it is safe to leave off by default and opt in.

Wired through ScalingSettings::StillsModulation and rugnux --stills-modulation
(default off), in both the full-analysis and --scale paths. On a 17 MP
JUNGFRAU serial set the surface cross-validates with a large held-out gain,
confirming a real detector-plane systematic; whether it improves the merged
data quality is under evaluation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 20:45:44 +02:00
leonarski_fandClaude Opus 4.8 c3e877d5ec bragg integration: trimmed-mean background, on by default for rotation
Build Packages / build:windows:nocuda (push) Failing after 1m40s
Build Packages / build:windows:cuda (push) Failing after 1m39s
Build Packages / build:viewer-tgz:cpu (push) Successful in 7m50s
Build Packages / build:viewer-tgz:cuda (push) Successful in 8m45s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 13m12s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 13m43s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 13m54s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 14m3s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 14m3s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 12m50s
Build Packages / build:rpm (rocky8) (push) Successful in 12m1s
Build Packages / XDS test (durin plugin) (push) Successful in 8m9s
Build Packages / Generate python client (push) Successful in 34s
Build Packages / Build documentation (push) Successful in 1m3s
Build Packages / Create release (push) Skipped
Build Packages / build:rpm (rocky9) (push) Successful in 12m31s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 12m58s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 13m19s
Build Packages / DIALS test (push) Successful in 14m25s
Build Packages / XDS test (neggia plugin) (push) Successful in 7m45s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 8m22s
Build Packages / Unit tests (push) Successful in 58m49s
The local Bragg background is the mean over the r2..r3 ring. That mean reads
high because the contaminants that survive the signal-disk mask - neighbour-
spot wings, tails, zingers - are one-sided (positive), so it over-subtracts.
Since a weak intensity is a small difference of large numbers (I = S - nS*b),
a per-pixel background bias is fractionally largest at the resolution edge,
exactly where it hurts most.

Replace the ring mean with a symmetric trimmed mean (sort the ring, drop the
lowest and highest fraction f, average the rest), controlled by a new
BraggIntegrationSettings field and the rugnux `--background-trim <f>` option
(default f=0.10; 0 restores the plain mean). Default on for monochromatic
(rotation) data; broadband (stills) keep their tuned high-side sigma-clip, so
the base engine forces the trim to 0 there. Implemented in both the CPU engine
and the GPU kernel (shared-memory bitonic sort per block, flat-mean fallback
above BKG_TRIM_MAX ring pixels); the two agree.

25-crystal rotation battery (fixed SG/cell): <I/sigma> improved on every
crystal (median +50%), ISa on 20/22, resolution-edge R_meas fell several-fold
(e.g. lyso_ref 1.0 A 108%->43%). Last-shell CC1/2 is rescued where the plain
mean had collapsed to noise (Thau_9 at ~2.0 A 3.8%->64%, ~0.5 A of resolution
regained; cytC_10 0.2%->10%) at a small cost (1-3%) in already-clean shells -
it flattens the CC1/2 fall-off rather than shifting it. Stills unchanged.
Documented in CPU_DATA_ANALYSIS.md section 9.2.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 18:32:57 +02:00
leonarski_fandClaude Opus 4.8 118f0833dc common: remove dead Reflection.completeness field
Reflection.completeness (spot-footprint fraction) was only ever set to its
1.0f default and never read anywhere - not in scaling/merge, CBOR, HDF5, or
the viewer. The box-sum integrator already rejects any partial-footprint
reflection outright (n_inner_valid == n_inner), so the intended "down-weight
clipped spots" role is already covered more strictly. Removed to reduce
confusion.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 18:32:40 +02:00
leonarski_fandClaude Opus 4.8 818ec8fcbf rugnux: add detector-plane modulation (flat-field) correction surface
Rotation scaling gained a third cross-validated correction surface alongside
decay and absorption: a smooth multiplicative factor over the predicted detector
position (px, py) where each full lands. It absorbs detector-response and
geometric flat-field systematics that vary across the detector plane and inflate
R-meas; symmetry-equivalents of one reflection land at different detector
positions as the crystal rotates, over-determining the surface. Because it lives
in the detector frame (not the rotation), the same correction concept applies to
stills.

The surface fit/cross-validate/apply machinery shared with the absorption surface
is factored into ApplyCellSurface; RefineAbsorption and the new RefineModulation
just build their per-full cell assignment (goniometer-frame vs detector-frame)
and call it. The cross-validation now scores a sigma-INDEPENDENT, R-meas-like
fractional agreement of the held-out equivalents rather than a studentized chi^2,
so a surface can no longer pass CV by reshaping sigma without tightening the
intensities - this removes an over-fit regression on mis-indexed data and hardens
the absorption surface too.

On the /data/rotation_test rotation battery (A/B, modulation off vs on): 17 of 22
processed crystals improve R-meas, 0 regress, e.g. lysoC 23.2->16.3%, lyso_2
47.4->28.5%, EcwtAL500 53.2->27.6%, EP_cs_01-17 CC1/2 60->93%; CC1/2 held or
improved everywhere and the anomalous S signal preserved/improved (lyso_ref
SD_MET 4.37->4.46, lysoC 3.07->3.25). On by default with the other surfaces.

Also: --dump-observations now writes the per-full centroid frame and predicted
px/py columns, so the dumped combined fulls are a complete unmerged export.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 13:24:10 +02:00
leonarski_fandClaude Opus 4.8 eae7ea90dc rugnux: always write both MTZ and CIF; drop --scaling-output
The merged reflections were written in one of mtz/cif/txt selected by
--scaling-output. Write both an MTZ and an mmCIF unconditionally instead - each
has its uses downstream (MTZ for the CCP4/phenix tools, mmCIF for deposition) -
and remove the format selector, the plain-text .hkl writer, and the now-unused
IntensityFormat enum / ScalingSettings::FileFormat plumbing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 10:45:08 +02:00
leonarski_fandClaude Opus 4.8 ce12d69751 rugnux: write standard CCP4 anomalous MTZ (IMEAN + I(+)/I(-))
In anomalous mode the merge keeps the two Friedel mates as separate rows,
which WriteMtzReflections emitted verbatim - two IMEAN rows per Bijvoet pair
that downstream tools had to re-collapse. Pair the mates into one row per
reflection with the standard CCP4 anomalous layout: IMEAN + I(+)/I(-) and the
matching F/F(+)/F(-) amplitudes. A single HKLKeyGenerator(merge_friedel=false)
yields both the shared ASU group key and which mate a row is (.plus); IMEAN/F
are the inverse-variance Friedel mean, centrics/unpaired keep one hand with the
other missing. aimless/mtz2sca/ANODE now read the file directly. The
non-anomalous MTZ path is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-16 10:37:56 +02:00
leonarski_fandClaude Opus 4.8 ce15900471 changelog: add the 1.0.0-rc.160 section
Build Packages / build:viewer-tgz:cpu (push) Successful in 7m50s
Build Packages / build:viewer-tgz:cuda (push) Successful in 9m25s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 12m18s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 12m12s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 12m24s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 12m32s
Build Packages / build:windows:nocuda (push) Successful in 16m14s
Build Packages / build:windows:cuda (push) Successful in 17m46s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 11m38s
Build Packages / build:rpm (ubuntu2404) (push) Failing after 6m54s
Build Packages / build:rpm (ubuntu2204) (push) Failing after 7m9s
Build Packages / build:rpm (rocky8) (push) Failing after 7m19s
Build Packages / build:rpm (rocky9_sls9) (push) Failing after 10m17s
Build Packages / build:rpm (rocky9) (push) Failing after 7m25s
Build Packages / Generate python client (push) Successful in 17s
Build Packages / Create release (push) Skipped
Build Packages / Build documentation (push) Successful in 48s
Build Packages / XDS test (neggia plugin) (push) Successful in 6m57s
Build Packages / XDS test (durin plugin) (push) Successful in 7m34s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 7m30s
Build Packages / DIALS test (push) Successful in 10m14s
Build Packages / Unit tests (push) Successful in 56m43s
VERSION was bumped to rc.160 but the new items sat under the rc.159
heading, which released (origin/main) does not contain. Add a proper
rc.160 section, move the three misfiled items (supercell fix, -S symbol,
FFTW-on-GPU error) into it, and document the rest of the branch (stills
geometry refinement, -r flex, stills partiality, r=6 box default,
single-pass self-referenced scaling, reference-MTZ-never-a-scale-anchor,
E^2 second-lattice cap, --scale on _process.h5 fix, new spot options,
CBF/TIFF writer removal, negative total_flux, viewer, packaging).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 22:20:14 +02:00
leonarski_fandClaude Opus 4.8 0e4f91b219 rugnux: validate offline spot-finding settings and bound numeric options
The offline rugnux path never ran CheckDataProcessingSettings (only the
online broker/receiver paths did), so the new --min-pix-per-spot and
--spot-low-resolution knobs were unbounded: --min-pix-per-spot 0 silently
disabled the per-spot filter, and a low-resolution limit finer than the
high-resolution limit made spot finding reject every pixel with no
diagnostic.

Add a parse_number_arg<T> helper (integral or floating, with optional
inclusive bounds) that rejects non-numeric input, trailing garbage, and
out-of-range values, replacing the raw atoi/atof in the spot-finding
options; parse_double_arg/parse_float_arg become thin wrappers over it.
After assembling the settings, validate them with the same
CheckDataProcessingSettings the online receivers use, which also enforces
the cross-field low>=high-resolution constraint.

Also scrubs a residual sample-name comment (the r=6 box-default note) in
this file.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 22:19:59 +02:00
leonarski_fandClaude Opus 4.8 8fea7f195a docs: stop advertising the removed CBF/TIFF writers
The CBF/TIFF writer removal left two docs describing them as available
output: JFJOCH_WRITER.md's "Other formats" section and an aside in
HDF5.md. A user following them would issue a now-rejected request. State
that only NXmx HDF5 is written and that the CBF/TIFF enum values are
retained for wire back-compatibility but rejected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 22:19:46 +02:00
leonarski_fandClaude Opus 4.8 d393ec814c Remove residual sample identities missed by the earlier scrub
The rc.160 sample-identity cleanup left protein names, internal dataset
codes, and a measured cell angle in several source comments and one test.
Most sensitive: a measured monoclinic beta tied to an internal code in
Rugnux.cpp and IndexAndRefine.cpp. Rewrite each to describe the
crystallographic situation only (space group / metric relation), keeping
the technical reasoning intact. Comment- and string-only; no behaviour
change. (rugnux_cli.cpp's remaining name is scrubbed in the following
commit, alongside its other change to that file.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 22:18:32 +02:00
leonarski_f 68272a96e1 VERSION: 1.0.0-rc.160 2026-07-15 21:41:51 +02:00
leonarski_fandClaude Opus 4.8 b450140816 rugnux: warn when the cell/space group has an indexing ambiguity
Build Packages / build:viewer-tgz:cpu (push) Successful in 6m38s
Build Packages / build:viewer-tgz:cuda (push) Successful in 8m2s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 13m26s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 13m59s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 13m58s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 14m20s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 14m25s
Build Packages / build:windows:nocuda (push) Successful in 16m39s
Build Packages / build:windows:cuda (push) Successful in 18m37s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 12m50s
Build Packages / build:rpm (rocky8) (push) Successful in 12m18s
Build Packages / XDS test (durin plugin) (push) Successful in 7m45s
Build Packages / Generate python client (push) Successful in 28s
Build Packages / Build documentation (push) Successful in 1m7s
Build Packages / Create release (push) Skipped
Build Packages / build:rpm (rocky9) (push) Successful in 12m46s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 12m28s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 12m52s
Build Packages / DIALS test (push) Successful in 13m40s
Build Packages / XDS test (neggia plugin) (push) Successful in 7m45s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 8m53s
Build Packages / Unit tests (push) Successful in 1h13m13s
At the twinning-analysis print, detect alternative-indexing (twin-law) operators
for the final cell + space group via ReindexAmbiguityOperators(). When any exist
and no reference was supplied, emit a Warning (also written into the merge stats)
that serial-stills crystals are indexed in a random hand and the ambiguity can
only be broken against a reference (-z / --model). For an obvious merohedral case
(P3/P4/P6...) users expect this, but a PSEUDO-merohedral metric is easy to miss --
e.g. NmHR / 7O8F, where C2 beta=131.8 is pseudo-F-orthorhombic and gemmi reports
the reindex operator h-l,-k,-l. Advisory only; no change to processing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 20:38:31 +02:00
leonarski_fandClaude Opus 4.8 3e3545770f indexing: check candidate angles against the reference cell in Refine()
When a reference cell is supplied, PostIndexingRefinement::Refine() vetted
candidates on sorted edge lengths only; a cell with the right edges but a wrong
angle (a pseudo-symmetric near-metric, e.g. a monoclinic beta refined to the
wrong value) passed. Add a sorted-angle check against the reference, folding
each angle to its acute complement min(x,180-x) so the obtuse/acute setting
choice is irrelevant (tolerance 10 deg).

Reference-cell path only (no effect de novo, where reference_unit_cell is null):
the /data/rotation_test battery is byte-identical (22/25), and NmHR with the
correct C2 cell is unchanged (9.1%, beta~131.7). A latent guard against
wrong-angle cells slipping through on -C / reference-MTZ runs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 19:47:29 +02:00
leonarski_fandClaude Opus 4.8 0f07b7a499 rotation: widen candidate-refine angle bound to [30,150] deg
RotationIndexer's per-candidate XtalOptimizer relied on the struct-default
monoclinic angle bound [60,120], the same latent clamp fixed for the stills
path: a rotation crystal with beta>120 (or <60) would have its cell clamped to
the boundary. Set [30,150] explicitly, matching the indexers.

No change on the /data/rotation_test battery (22/25 SG match, byte-identical) --
no battery crystal has beta outside [60,120]; this is a latent-correctness fix
for future high-beta monoclinic rotation data.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 19:47:17 +02:00
leonarski_fandClaude Opus 4.8 643bda3dd3 stills: widen per-frame cell-refine angle bound to [30,150] deg
The stills per-frame XtalOptimizer in IndexAndRefine used the struct-default
monoclinic angle bound [60,120] deg, which clamps a beta outside that window
(e.g. NmHR / 7O8F, C2 beta=131.78) to the boundary and corrupts the per-frame
cell. Both indexers already use [30,150] (FFBIDXIndexer, FFT settings); this
aligns the per-frame refine with them. Rotation path is unaffected
(refine_unit_cell is false there).

Verified on NmHR serial stills: FFBIDX with the correct C2 cell went from
0.01% to 9.10% indexed, recovering the true mC cell (beta~131.7) instead of a
clamped beta=120; 60k-image merge reaches 2.61 A at 99.8% completeness.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 19:13:41 +02:00
leonarski_fandClaude Opus 4.8 7b2cfb20f8 changelog: document the supercell fix, -S symbol, and FFTW-on-GPU error
Also scrub two sample names from existing rc.159 entries.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 17:19:43 +02:00
leonarski_fandClaude Opus 4.8 d8e909a393 indexing: clear error when the requested indexer is unavailable on this host
IndexerThreadPool built its per-worker indexers from the raw requested algorithm
but dispatched the RESOLVED one. Rotation indexing always resolves to the GPU FFT
indexer when a GPU is present, so requesting FFTW (the CPU indexer) on a GPU node
created only the CPU indexer and then failed at dispatch with an opaque "no
indexer available for the resolved indexing algorithm" deep inside a worker.

Validate servability at the pool entry (in the caller's context) and throw an
actionable message instead: FFTW is not available on a GPU node (use FFT/Auto, or
a CPU-only node); FFT/FFBIDX require a GPU. Stills FFTW on a GPU node, which the
algorithm resolution still honours, keeps working.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 17:19:43 +02:00
leonarski_fandClaude Opus 4.8 abbee2d4dc Remove sample identities from the repository; document the rule
Datasets may be confidential; sample names and measured unit cells committed to
the repo can leak outside the group working on them. Scrub existing occurrences
and add a "No sample identities in the repository" section to CLAUDE.md
(forbidden: sample/dataset names, internal codes, measured cells tied to a
sample; fine: space group / lattice / twinning descriptors).

- Comments: replace internal dataset codes and protein names with the
  crystallographic situation they illustrate (centred vs pseudo-symmetric,
  holohedral, cubic, F-cubic/hexagonal, ...).
- Docs: same, in the analysis/writer/stream references and example configs.
- Tests: rename sample-named identifiers, TEST_CASE names, file prefixes and
  asserted labels to neutral crystallographic names (e.g. tetragonal_uc);
  behaviour unchanged. Reduce the CrystFEL reference PDB to a bare CRYST1 cell
  file (cell.pdb) and rename the reference data file.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 17:19:43 +02:00
leonarski_fandClaude Opus 4.8 0f3ccda779 rugnux: fix de-novo rotation indexing adopting a spurious axis-multiple supercell
Two-pass rotation indexing scored each first-pass scheme by how many
validation frames it indexes, but a spurious axis multiple (2x/3x...)
indexes every frame its true sub-cell does, so the count saturates - both
schemes reach the same frame total - and the tie fell to whichever scheme
ran first. When that first scheme's full-rotation FFT resolves a true
axis only as a 2x/3x harmonic of its length (the fundamental can sit far
below the harmonic in the full-360 cloud), it commits a multiplied cell
and the dataset collapses to P1, even though the other scheme already
found the true cell.

Add an integer-supercell cross-scheme tie-break: when two schemes tie on
frames but their cell volumes differ by a near-integer factor >=2, the
larger is the spurious supercell and the smaller true cell is adopted,
independent of scheme order. The near-integer test distinguishes a real
axis multiplication from a centering coincidence (a rhombohedral H cell
vs its C2 sub-cell is 1.5x and is left alone).

Validated de-novo across the rotation regression battery: the affected
dataset now indexes its correct space group, the override triggers only
where an axis was multiplied, and every other dataset is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 16:51:57 +02:00
leonarski_fandClaude Opus 4.8 bd094e585f rugnux: accept a space-group symbol for -S, not just a number
-S now takes either a number ("92") or a Hermann-Mauguin symbol
("P43212"), resolved via gemmi find_spacegroup_by_name. Previously a
non-numeric argument was atoi'd to 0 and tripped the early space-group
validation, aborting the run.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 15:23:31 +02:00
leonarski_fandClaude Opus 4.8 ebe7e7ec5e jfjoch_viewer: retry deferred initial fit on resize (grid-scan zoom)
fitToViewShorterSideOnce() skips the initial fit-to-view while the viewport has
no real size yet (before the widget is laid out/shown) and relies on a retry
that was never wired: resizeEvent only reset the scene rect, and there is no
showEvent. When the first Redraw() lands before layout settles the view stays
at 1:1, so a small grid-scan plot renders tiny ("zoomed out, not taking the
full picture"); the layout-timing race is why it happened only sometimes.

resizeEvent now retries fitToViewShorterSideOnce() while the initial fit is
still pending (guarded by !initial_fit_done_, so a later user resize never
overrides a manual zoom). It lives in the shared base class, so all image views
get the same robustness.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 11:28:09 +02:00
leonarski_fandClaude Opus 4.8 5d1ddccee8 viewer: expose stills processing settings; rename geom refinement multi -> flex
Wire the recently-added stills knobs into jfjoch_viewer - they were reachable
only from the rugnux CLI, and the viewer had silently diverged from the CLI once
--refine-geometry became default-on for stills-with-cell.

- Stills geometry-refinement two-pass (--refine-geometry): a checkbox + frame
  count in the reprocessing-job dialog, offered (and defaulted on, matching the
  CLI) only for a stills-with-cell run; wired into ProcessConfig and the
  "Copy command" generator (joined =N, or =off to reproduce opting out of the
  CLI default-on).
- Stills partiality (--still-partiality) checkbox in Bragg integration and the
  partiality-uncertainty merge term (--partiality-uncertainty) in Scaling, both
  mirrored in the command-line generator.

Rename the "best per-image refinement" mode from "multi" to "flex" everywhere:
GeomRefinementAlgorithmEnum::Flex, CLI -r flex (with "multi" kept as a hidden
back-compat alias), OpenAPI enum "Flex" + regenerated C++/TS clients, viewer
combo, frontend dropdown, and the stored HDF5 string. "multi" collides with
CrystFEL's multi-lattice sense; "flex" = let the pipeline decide. The API now
carries a dedicated Flex value instead of masquerading as BeamCenter.

Also fix a pre-existing bug in Convert(IndexingSettings): OrientationOnly was
missing from the outbound switch and serialized as an invalid API value.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 11:28:09 +02:00
leonarski_fandClaude Opus 4.8 4bdf9309dd writer: remove CBF and TIFF writers; only HDF5 is written
Delete CBFWriter and the TIFF write path from jfjoch_writer so the writer
only produces the NXmx HDF5 formats. Drop CBF/TIFF from the internal
FileWriterFormat enum and reject them in FileWriterSettings.

The CBF/TIFF values are kept (marked deprecated) in the file_writer_format
OpenAPI enum for back compatibility: incoming requests using them are now
rejected in OpenAPIConvert with a clear "no longer supported" error, and a
stale CBF/TIFF value on the CBOR wire decodes to unset rather than a removed
enumerator.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 10:11:39 +02:00
leonarski_fandClaude Opus 4.8 135765e5b5 rugnux: default --refine-geometry on for stills-with-cell; accept F/FP reference columns
Build Packages / build:viewer-tgz:cpu (push) Successful in 7m42s
Build Packages / build:viewer-tgz:cuda (push) Successful in 8m55s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 13m22s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 13m55s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 14m6s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 14m15s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 14m9s
Build Packages / build:windows:nocuda (push) Successful in 15m48s
Build Packages / build:windows:cuda (push) Successful in 17m53s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 13m7s
Build Packages / build:rpm (rocky8) (push) Successful in 12m1s
Build Packages / XDS test (durin plugin) (push) Successful in 8m6s
Build Packages / Generate python client (push) Successful in 37s
Build Packages / Build documentation (push) Successful in 1m6s
Build Packages / Create release (push) Skipped
Build Packages / build:rpm (ubuntu2404) (push) Successful in 12m42s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 13m3s
Build Packages / build:rpm (rocky9) (push) Successful in 13m38s
Build Packages / DIALS test (push) Successful in 14m6s
Build Packages / XDS test (neggia plugin) (push) Successful in 8m2s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 8m39s
Build Packages / Unit tests (push) Successful in 1h0m55s
Two stills usability fixes.

1. --refine-geometry now defaults ON for stills whenever a reference cell is
   available (-C or a reference MTZ) - exactly the case where the geometry
   bundle-adjust can act (it anchors on a known cell) and where it lifts weak/
   sparse-stills indexing (OCP +42%, KR2 +108% indexed in the target study). It
   stays a no-op for rotation (own two-pass) and de-novo stills (no cell yet), so
   auto-enabling it only where it does something avoids spurious "skipping"
   warnings. --refine-geometry=off opts out; explicit --refine-geometry[=N] forces it.

2. The reference-MTZ auto column selection now falls back to a plain amplitude
   column (FP / FOBS / F / FC, squared to an intensity) after F-model and the
   intensity (J) columns. A deposition that carries only structure-factor
   amplitudes (e.g. KR2's 8cl8, whose only usable column is FP) now seeds CCref
   without needing an explicit --reference-column FP.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-15 07:27:25 +02:00
leonarski_fandClaude Opus 4.8 768a926e0c rugnux: reject 2nd-lattice overlaps in the space-group search (E^2 cap)
On a two-lattice crystal a second lattice deposits intensity on one reciprocal
position but not its symmetry mate, so a contaminated reflection is a one-sided
resolution-normalised-E outlier that poisons the operator I(h)/I(Rh) correlation
in SearchSpaceGroup Stage A. On EP_cs_02-424 under -A this dropped the monoclinic
2-fold CC to 0.326 (below the 0.5 gate) -> the crystal was under-called P1 instead
of P2_1. The existing --reject-outliers cannot see it: it rejects WITHIN a P1 orbit,
but the poison is a BETWEEN-orbit effect (inflates orbit h, not its mate Rh).

Add SearchSpaceGroupOptions::max_e_squared_for_cc (default 9.0, i.e. E>3): after the
resolution-normalised Esq[] is computed, drop the extreme-E tail from the correlation
pairs only (the absence stage keeps the full range - that is where the screw signal
lives). Clean Wilson-distributed data almost never reaches E^2=9 (P ~ 0.01-0.3%), so
it is self-targeting - it trims the overlap tail without touching genuine reflections.

EP_cs_02-424 -A: 2-fold CC 0.326 -> 0.64 -> P2_1 (= XDS). Full 24-crystal rotation
battery (pre/post): only EP_cs_02-424 changed (P1 -> P2_1, SG match 20 -> 21/24); all
23 others bit-identical, including the marginal cubic Ins_I_3 (still I23, carried by
the systematic-b rescue). A Friedel-merge-the-search alternative was tried and rejected
(net-negative: did not fix EP424 and regressed Ins_I_3 -> I222).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 23:22:38 +02:00
leonarski_fandClaude Opus 4.8 4c050b576c rugnux: de-double spurious rotation supercell in candidate selection
The two-pass rotation indexer could keep a doubled-axis supercell over its own
primitive sub-cell: when the supercell won candidate (ci) order and the primitive
cleared the indexed-fraction hysteresis by less than the 0.05 "prefer-earlier"
margin, the supercell survived. On pding4_003 full data this gave P222 on a
65.6x131.3x173 cell instead of P422 on 65.6x65.6x173 - the orthorhombic metric
forecloses the 4-fold before the symmetry search ever runs. The FFT peak-finding
is correct (the primitive cell is among the candidates, just out-ranked).

Add a sub-cell override to the selection loop: adopt a later candidate that is a
genuinely smaller cell (> ROT_SUBCELL_VOLUME_RATIO=1.5x smaller volume; a doubling
is 2x) indexing at least as many spots (within ROT_SUBCELL_FRAC_SLACK=0.02). That
is the signature of a spurious doubling - the primitive always indexes >= its
integer multiple, whereas a real superstructure's larger cell indexes MORE (kept
by the existing clearly-more branch) and twins share the cell volume (untouched).

Full 24-crystal rotation battery (pre-fix vs post-fix): pding4_003 P222->P422
(cell halves to 65.6x65.6x173, R_meas 6.6% CC1/2 99.9% ISa 11.9), pding4_001
holds P422, all 22 other crystals bit-identical in space group.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 21:53:08 +02:00
leonarski_fandClaude Opus 4.8 4c5da20eda rugnux: add --partiality-uncertainty stills merge term (partiality-model error)
A stills reflection recorded at partiality p carries a systematic intensity error ~(dp/p) that is
proportional to <I> and grows as p falls; plain counting sigma misses it, so strong low-p partials
are over-trusted in the merge. Add sigma^2 += (c*<I>*(1-p))^2 in MergeOnTheFly::CorrectedSigma - the
stills-partiality analog of the existing rotation --capture-uncertainty term ((1-captured_fraction)*I
in RotationScaleMerge). Inert when partiality==1 (no --still-partiality), and gated on a real
systematic (error_model_b > 1, i.e. ISa < 1) so it fires on strong/medium stills but auto-skips weak
counting-limited data where it would only over-concentrate the merge and hurt. Opt-in via
--partiality-uncertainty <c> (default 0; ~2.5 recommended with --still-partiality).

Prototyped (Python replica of the merge): lyso8 CC1/2 +1.7, CCref +4.8, R-free -0.023; LOV CCref +2;
harmful on weak OCP (hence the b>1 gate). Full in-binary validation across all serial targets pending.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 19:52:46 +02:00
leonarski_fandClaude Opus 4.8 2f5ed411e2 rugnux: --refine-geometry stills two-pass (global bundle adjustment + re-index)
Weak/jet serial stills are often geometry-limited: a few-px beam error or a mm-scale detector
distance error (unreachable per-image) fails many frames, but is well-determined jointly from the
strong frames. Mirror the rotation two-pass: an index-only first pass over a spread sample collects
each indexed frame's spots + assigned HKL + orientation; the strongest ~N (default 200) feed one
Ceres bundle adjustment; the refined geometry is applied and the main pass re-indexes + integrates
+ merges every frame from scratch.

GeometryRefiner (reusing the extracted XtalResidual - the RecipToDetector geometry residual pulled
out of XtalOptimizer, behaviour-preserving): one problem with SHARED beam(2)/distance(1)/cell-length(3)
blocks + a PER-FRAME orientation(3) block, robust Cauchy loss, a cell-length regularizer anchoring the
known cell to break the low-resolution distance<->cell-scale degeneracy, DENSE_SCHUR eliminating the
per-frame orientations, and a 3-round HKL-reassignment / tolerance-tightening loop. Tilt is not refined
(gauge-coupled, zero gain). Opt-in via --refine-geometry[=N]; stills only (rotation untouched).

Validated: KR2 7.58% -> 21.85% (matches CrystFEL's 21.5%; a real ~1.4mm distance error + ~3px beam),
OCP 2.92% -> 4.19% (~3px beam). OFF runs are bit-identical to baseline (XtalResidual extraction
non-regressing; rotation lyso_ref de-novo ISa 17.3 unchanged).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 18:17:58 +02:00
leonarski_fandClaude Opus 4.8 49963ab855 rugnux: move indexing-ambiguity resolution out of ScaleOnTheFly
Indexing-ambiguity detection/resolution is no longer part of scaling: it
is a dedicated per-image step for stills (or a post-full-merge step for
rotation). Pull the stills per-image resolver out of ScaleOnTheFly into a
new ReindexAmbiguityResolver in ReindexAmbiguity.{h,cpp}, alongside the
existing rotation free functions (ChooseReindex / ReferenceIntensityCC).

Both workflows now share the operator generation and the best-op
selection (new file-local PickBestReindex helper); ChooseReindex is
rewired onto it. ScaleOnTheFly is now purely a scaling engine (no
ambiguity_ops, no resolve_ambiguity flag, no ResolveIndexingAmbiguity).

Pure refactor: behaviour is unchanged. IndexAndRefine now holds a
ReindexAmbiguityResolver and calls Resolve() at the same call site.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 15:35:40 +02:00
leonarski_fandClaude Opus 4.8 3f6462b30f rugnux: rotation indexing always uses FFT/FFTW, never FFBIDX
The rotation two-pass accumulates a dense multi-frame reciprocal-space cloud (all first-pass
frames de-rotated into one common frame) and needs a GLOBAL lattice finder - a 3D FFT whose
peaks are the basis vectors. ffbidx is a single-still, known-cell ORIENTATION finder: it assumes
the spots lie on one Ewald shell (one crystal, one orientation) and maximizes a near-integer-hkl
count for a fixed cell. On the volume-filling rotation cloud that objective has no dominant global
maximum, so ffbidx's coarse orientation scan locks onto an orientation valid for only a local wedge
(~18%) -> garbage merge.

GetIndexingAlgorithm resolved Auto->FFBIDX whenever a cell was known, even for rotation - and a
reference MTZ (-z) or -C silently supplies the cell. So a routine rotation run with a reference for
CCref/R-free flipped the indexer to the one solver that cannot handle its input (lyso_ref: ISa 17.8
with FFT -> 0.5 with FFBIDX, no warning). Force rotation to FFT (GPU) / FFTW (CPU) regardless of the
requested algorithm or a known cell.

Validated: lyso_ref -R with -z reference MTZ now indexes via FFT -> ISa 17.8 (was 0.5), 15975 refl.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 15:18:58 +02:00
leonarski_fandClaude Opus 4.8 95af137146 rugnux: the external reference MTZ is never a scale anchor (stills + rotation)
An external reference MTZ is a poor per-image scale reference: it is a different crystal/dataset,
so scaling against it injects cross-dataset systematics rather than removing per-image scale error
(measured: reference-scaled R-free 0.410 vs self-scaled 0.388 on OCP; 0.378 vs 0.350 on LOV). Its
real value is fixing the cell/space group, breaking the merohedral indexing ambiguity, reporting
CCref and providing the R-free test set - none of which need it to be a scale anchor.

Make that consistent across both workflows:
- Stills: the per-image pass (ScaleImage) now uses the reference ONLY to break the indexing ambiguity
  (once, for good), not to fit G. Scaling self-references at the post-measurement merge for every run,
  whether or not a reference is given (Rugnux + rugnux_cli --scale).
- Rotation: ScaleImage no longer scales against the reference either (it was dead code - RotationScaleMerge
  recomputes the per-frame scale, so the reference never actually moved the result). Rotation resolves
  the ambiguity globally (ChooseReindex / ReferenceIntensityCC) and self-scales in RotationScaleMerge.
- A reference-as-scale mode, if ever wanted, would be a dedicated later step, not this per-image pass.

Validated: OCP CCref 56.5%->64.6%, R-free 0.400->0.393 (honest 2.36 A cutoff instead of a reference-
propped 1.5 A); LOV CCref 88.3%->90.1%, R-free 0.336->0.331 with more reflections; rotation lyso_ref
with the reference gives ISa 17.8 == de-novo 15.6 (same 15975 reflections, CC1/2 99.8%) - the reference
demonstrably does not touch rotation scaling, only cell/SG + ambiguity + CCref.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 13:01:56 +02:00
leonarski_fandClaude Opus 4.8 9527fa6e2c rugnux: scale self-referenced stills in a single pass (fix weak-data collapse)
The stills self-scaling loop rebuilt the merge reference FROM the just-scaled reflections
every iteration, so on weak data each pass re-fit its own noise and the merged CC1/2
collapsed (PfluDING combine: 0.3% at the default 3 iters). It is provably pointless too:
ScaleOnTheFly::Scale re-solves the per-image G from raw I and never reads the prior
correction, so against a fixed reference passes 2..N are bit-identical - the single G is the
exact one-pass solution and iteration only ever does the harmful reference rebuild (N=1 is
best on every dataset, including strong lyso 82% vs 76% at N=3; leave-one-out and external
anchors were tested and do not beat it). Do one self-reference pass; rotation (RotationScaleMerge)
and the external-reference branch are untouched.

Validated: PfluDING-combined CC1/2 0.3% -> 42.0% by default (pinned 2.5 A); strong data unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 12:05:08 +02:00
leonarski_fandClaude Opus 4.8 4a5028d98d rugnux: add -r multi geometry refinement (per-image best of three)
Per-image geometry refinement is a tradeoff that flips per dataset: beam+cell refinement
extends OCP merge quality but DIVERGES on sparse-spot stills (e.g. KR2's ~20 spots around a
232 A axis), pushing good lattices out of tolerance so they fail the acceptance floor.
`-r multi` runs all three (none / orientation / beam_and_lattice) on a copy per image and
keeps whichever indexes the most spots (scorer = fractional-Miller-within-tolerance count,
mirroring AnalyzeIndexing); ties prefer less refinement, to avoid overfitting the sparse list.

Validated: KR2 index 7.08% (-r beam_and_lattice default) -> 10.05% (matches the -r none best),
while OCP R-free stays ~equal to beam_and_lattice. New GeomRefinementAlgorithmEnum::Multi handled
in the CLI/HDF5/command-line echoes; the API convert maps it to beam_and_lattice (offline only).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 12:04:32 +02:00
leonarski_fandClaude Opus 4.8 fb399480e5 rugnux: add opt-in stills partiality (--still-partiality)
Serial stills currently treat every reflection as a full (partiality hardcoded to 1).
Add an opt-in Gaussian excitation-error partiality set at prediction time (CPU + CUDA):
p = exp(-dist_ewald^2 / (2*sigma^2)), sigma^2 = profile_radius^2 + (bandwidth_sigma*|recip_z|)^2,
with sigma = the per-image profile radius (ewald_dist_cutoff/2), so an edge-of-acceptance
reflection keeps p ~ exp(-2). Off by default; the merge weight (~p^2) then down-weights
far-from-Ewald partials instead of trusting them as fulls.

Validated: helps medium/strong stills (LOV R-free 0.336->0.329, lyso8 0.433->0.410, lowers
the systematic error-model b in both) but HURTS weak OCP (dividing by a small, uncertain p
amplifies orientation error -> high-res noise, resolution collapse), so it is left opt-in.
A static forward p explains only ~6-10% of the partiality scatter; the full win needs per-image
post-refinement (future work), for which this is the prediction-side groundwork.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 12:03:21 +02:00
leonarski_fandClaude Opus 4.8 b0202a3aa2 rugnux: default the stills integration box to r=6 (6,8,12)
Serial-stills spots span a range of crystal orientations within a single shot, so they
land wider on the detector than the r1=4 monochromatic-rotation default assumes, and the
r1=4 signal box truncates the (bandwidth/mosaicity-broadened) spot wings. The profile-fit
integrator can use a larger box for free - its profile weighting drives far-out background
pixels to ~zero weight, so the estimator variance saturates rather than growing (a plain
box-sum, which sums every pixel at weight 1, degrades). Gated on stills (!rotation_indexing);
rotation stays at 4,6,10 (a larger box there only adds background - measured wash-to-negative
on the XDS rotation battery, with an SG regression); an explicit --integration-radius wins.

Validated: OCP R-free 0.406->0.400, LOV 0.354->0.336; lyso8 1.60->1.57 A; lyso5 (1% DMM)
1.80->1.72 A with +13% reflections at equal CC1/2 - the broadened case benefits most.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 12:00:26 +02:00
leonarski_fandClaude Opus 4.8 db8ae0452e rugnux: fix --scale on a self-contained _process.h5 (reflections + error model)
Offline --scale re-scales the reflections stored in a _process.h5 without
re-integration, but was broken for a self-contained integrated snapshot:

1. HDF5MetadataSource::ReadReflections fell back per-image to the linked
   source pixel files for every non-indexed frame (a snapshot's master holds
   /entry/reflections only for the sparse indexed images). With the raw
   _data_NNNNNN.h5 absent or not co-located this threw an HDF5 error; when
   present it needlessly reopened multi-GB files thousands of times. Decide
   once whether the master is the authoritative reflection store and, if so,
   never fall back - a missing per-image group just means the frame has none.
   Legacy/VDS acquisitions (no /entry/reflections in the master) still resolve
   reflections lazily to the source data files.

2. The scale-only stills branch never fit the (a,b) error model, so it merged
   with the identity model - far worse intensities than the full pipeline
   (lyso8 CC1/2 76%->21%). Fit RefineErrorModel and honour --reject-outliers,
   mirroring Rugnux.cpp.

Round-trip validated: full merge == integrate(--no-merge) + --scale (identical
error model a=0.793 b=2.287, matching unique reflection counts), and --scale
now reads reflections in ~2.5s with no raw-file access.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 10:06:07 +02:00
leonarski_fandClaude Opus 4.8 097b9a29d1 rugnux: add --spot-low-resolution CLI option (exclude beam halo)
The spot-finding low-resolution limit was hardcoded at 50 A (r ~36 px), which
admits the direct-beam halo/overload zone (24-50 A) on weakly-diffracting serial
data. On KR2 (I222, 235 A axis, ~3.9 A diffraction) that halo is ~387 strong
pixels/frame vs ~25 real Bragg pixels, swamping the signal ~15:1 (CrystFEL cuts
it with min-res=75 px = 24 A). Expose the limit so it can be tightened, e.g.
--spot-low-resolution 24. Default unchanged (50 A).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 23:14:27 +02:00
leonarski_fandClaude Opus 4.8 2f3041c44e rugnux: add --min-pix-per-spot CLI option (spot finding)
The minimum connected strong-pixel count per spot was hardcoded to 2
(SpotFindingSettings::min_pix_per_spot). Expose it on the CLI so serial-stills
data can be run with min-pix 1 (plus a higher --spot-threshold), matching the
CrystFEL peakfinder8 practice that trades noisier spots for a higher indexing
rate. Default unchanged (2).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 22:02:49 +02:00
leonarski_fandClaude Opus 4.8 2d7ddb1b67 ScaleOnTheFly: resolve the stills indexing ambiguity per image vs a reference
Build Packages / build:windows:nocuda (push) Failing after 2m41s
Build Packages / build:windows:cuda (push) Successful in 12m21s
Build Packages / build:viewer-tgz:cpu (push) Successful in 6m40s
Build Packages / build:viewer-tgz:cuda (push) Successful in 7m33s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 10m13s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 10m5s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 10m36s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 10m7s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 10m54s
Build Packages / build:rpm (rocky8) (push) Successful in 10m50s
Build Packages / build:rpm (rocky9) (push) Successful in 11m39s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 11m9s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 21m2s
Build Packages / Generate python client (push) Successful in 16s
Build Packages / Build documentation (push) Successful in 48s
Build Packages / Create release (push) Skipped
Build Packages / build:rpm (ubuntu2404) (push) Successful in 10m42s
Build Packages / XDS test (durin plugin) (push) Successful in 7m33s
Build Packages / XDS test (neggia plugin) (push) Successful in 6m52s
Build Packages / DIALS test (push) Successful in 12m9s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 7m26s
Build Packages / Unit tests (push) Successful in 59m4s
Serial stills index each crystal in one of the merohedrally-equivalent hands
at random, so the ambiguity must be broken per image, not globally as the
rotation path (RotationScaleMerge/ChooseReindex) does. When an external
reference MTZ is supplied, IndexAndRefine::ReferenceIntensities now builds the
per-image scaler with resolve_ambiguity=true: for each image it picks the
reindexing (identity or a twin law from ReindexAmbiguityOperators) whose
partiality/Lorentz-corrected intensities correlate best with the reference,
then reindexes that image's reflections before scaling. Off for the self-merge
scaling pass (no trusted reference to break the tie).

Holohedral crystals (no twin law, e.g. lysozyme P43212) are a no-op. Validated
on OCP P3221 (twin law -x,-y,z) with a 7ZSJ reference: CCref 24->48% and
CC1/2 24->64% at 30k images; CC1/2 96.9% / CCref 76% at 150k.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 19:46:48 +02:00
leonarski_fandClaude Opus 4.8 87778c6500 reader: treat negative total_flux as unknown/absent
Serial-stills master files can store /entry/instrument/beam/total_flux as a
-1.0 "unknown flux" sentinel (seen in the OCP dark dataset). DatasetSettings
rejects values below 0, so opening such a file hard-failed with
"Input parameter below min (Total flux)". Reset a negative flux to nullopt so
it is treated as absent instead of aborting the read.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 19:46:48 +02:00
leonarski_fandClaude Opus 4.8 3df9ad631b docker: fix build_in_rocky9.sh shed-check for RHEL9's glib/selinux sources
Build Packages / build:viewer-tgz:cpu (push) Successful in 6m52s
Build Packages / build:viewer-tgz:cuda (push) Successful in 8m0s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 13m5s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 13m34s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 13m45s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 13m54s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 14m22s
Build Packages / build:windows:nocuda (push) Successful in 16m5s
Build Packages / build:windows:cuda (push) Successful in 18m23s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 13m6s
Build Packages / build:rpm (rocky8) (push) Successful in 11m56s
Build Packages / XDS test (durin plugin) (push) Successful in 8m7s
Build Packages / Generate python client (push) Successful in 35s
Build Packages / Build documentation (push) Successful in 1m11s
Build Packages / Create release (push) Skipped
Build Packages / build:rpm (ubuntu2404) (push) Successful in 12m11s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 12m54s
Build Packages / build:rpm (rocky9) (push) Successful in 13m30s
Build Packages / DIALS test (push) Successful in 14m5s
Build Packages / XDS test (neggia plugin) (push) Successful in 8m8s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 8m57s
Build Packages / Unit tests (push) Successful in 1h16m16s
The old check flagged glib/selinux/pcre as failures, inheriting a rocky8-host
assumption (glib is Qt-only, selinux is dbus-only) that does not hold on RHEL9:

- libglib is pulled by the system harfbuzz/fontconfig/freetype text stack
  (glib-linked on RHEL9), not by Qt. QT_FEATURE_glib=OFF is honoured (Qt's
  enabled_features has no glib) but cannot drop the font stack's libglib.
- libselinux/libpcre2-8 come from the krb5/GSSAPI stack (libgssapi_krb5 ->
  libselinux) that static curl links for auth -- kept for the reverse-proxy
  Kerberos plan, same bucket as libcrypto.

So hard-fail only on the dbus/systemd tail we actually remove (libdbus/
libsystemd/zstd/lz4/cap/gcrypt/gpg-error), and just report glib/selinux as
expected residuals with the reason. Verified in the rocky9 image: that tail is
gone; the survivors trace to the font stack and krb5.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 19:27:43 +02:00
leonarski_fandClaude Opus 4.8 d90d498cdb docker: put the static libdbus on CMAKE_PREFIX_PATH for Qt6::DBus consumers
The Qt build found dbus via -DDBus1_DIR, but a static Qt records the dependency
and every consumer re-runs find_package(DBus1) through Qt's exported config
(Qt6Gui -> Qt6DBus -> find_dependency(WrapDBus1)). Without the dbus prefix on
the consumer's search path that fails:

  Could NOT find WrapDBus1 (missing: DBus1_LIBRARY DBus1_INCLUDE_DIR ...)
  Qt6DBus could not be found because dependency WrapDBus1 could not be found.

Add /opt/dbus-<ver>-static to the image's CMAKE_PREFIX_PATH env so the viewer
build (and the CI .deb/.rpm and tarball builds) resolve it. Verified against the
rocky9 image: find_package(Qt6 ... DBus) fails with the old path and passes with
dbus on the env CMAKE_PREFIX_PATH.

Also make build_in_rocky9.sh self-sufficient on images built before this fix:
it discovers /opt/dbus-*-static/lib/cmake/DBus1 and passes -DDBus1_DIR, so the
viewer verification works without rebuilding the image first.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 19:13:29 +02:00
leonarski_fandClaude Opus 4.8 b6c2d5848d docker: build the static libdbus with -fPIC so Qt's PIE tools link it
The static libdbus linked fine into libQt6DBus.a, but Qt links its D-Bus code
generators (qdbusxml2cpp/qdbuscpp2xml) as position-independent executables
(-fPIE -pie), and the default autotools dbus build produces non-PIC objects:

  ld: libdbus-1.a(...dbus-address.o): relocation R_X86_64_32 against `.rodata'
      can not be used when making a PIE object; recompile with -fPIE

Build libdbus with --with-pic and CFLAGS=-fPIC so its archive objects are
position-independent and link into both the static Qt libs and the PIE tools.
Reproduced (non-PIC -> R_X86_64_32 fail) and fixed (PIC -> PIE whole-archive
link passes) in a rocky8 container before applying.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 15:52:50 +02:00
leonarski_fandClaude Opus 4.8 254bd82d52 docker: add parallel image-build + in-container viewer-verify scripts
build_images.sh builds (and optionally pushes) the four build-environment
images as gitea.psi.ch/leonarski_f/jfjoch_<variant>:<TAG>. Runs a JOBS-capped
parallel job pool (default 2; each build internally runs make -j$(nproc), so a
low cap avoids CPU/RAM thrash while still overlapping the network-bound base
pull / install / download phases), streams each build to
docker/build-logs/<variant>-<TAG>.log, prints an OK/FAIL summary, pushes only
the ones that succeeded, and exits non-zero on any failure. Context is the tiny
per-variant dir (no COPY in the Dockerfiles), so the repo is never sent to the
daemon. build-logs/ is already covered by the root .gitignore build*/ rule.

build_in_rocky9.sh builds the viewer (JFJOCH_VIEWER_ONLY) inside a chosen
variant's image and ldd-checks that the dbus/systemd/glib/selinux tail is gone
-- the quick verification for the static-libdbus + glib-off changes. The repo is
mounted but the build tree lives in the container's /tmp, so nothing root-owned
lands in the working copy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 15:43:18 +02:00
leonarski_fandClaude Opus 4.8 5baf2a2cac docker: static libdbus + disable Qt glib to shed the viewer's .so tail
The jfjoch_viewer runtime pulled a large dynamic .so tail that traces to two
Qt-side integrations, neither of which the viewer actually needs:

- Qt6::DBus -> system libdbus-1.so -> libsystemd (libzstd/liblz4/libcap/
  libgcrypt/libgpg-error) + libselinux (libpcre2). The viewer is a pure
  session-bus client (registers ch.psi.jfjoch_viewer + exports an adaptor for
  single-instance/remote-control), so the daemon-side systemd/selinux features
  are irrelevant. Build a static libdbus from source with those integrations
  disabled and link it into the viewer, the same from-source-static pattern
  already used for OpenSSL. Swap the dbus dev package for expat (dbus's
  configure-time dep; the client libdbus-1 links neither expat nor systemd) so
  nothing pulls the system shared dbus back in.

  Qt discovers dbus through find_package(DBus1) (its FindWrapDBus1.cmake), NOT
  pkg-config -- so point it at our build with -DDBus1_DIR=<prefix>/lib/cmake/
  DBus1 (the CMake package config dbus installs, which imports libdbus-1.a) and
  force QT_FEATURE_dbus_linked=ON so QtDBus links the archive instead of
  dlopen'ing a (now nonexistent) libdbus-1.so.3 at runtime.

- Qt's glib event-dispatcher -> libglib-2.0/libgthread/libpcre. Nothing in the
  viewer (or any lib it links) drives a GLib main context, so switch Qt to its
  own QEventDispatcherUNIX via QT_FEATURE_glib=OFF and drop the glib dev package.

Applied identically across rocky8, rocky9, ubuntu2204, ubuntu2404.

Note: system libcrypto still appears at runtime, but it is dragged in by the
dynamic system krb5/GSSAPI (built against OpenSSL on RHEL/Rocky), which we keep
dynamic for the planned httpd-reverse-proxy Kerberos auth -- not from Qt or curl,
which both statically link the from-source OpenSSL.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 15:35:43 +02:00
leonarski_f dd0bffb283 v1.0.0-rc.159 (#69)
Build Packages / Unit tests (push) Skipped
Build Packages / build:windows:nocuda (push) Successful in 11m6s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 10m27s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 10m54s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 9m25s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 10m5s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 11m33s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 11m19s
Build Packages / build:rpm (rocky8) (push) Successful in 12m23s
Build Packages / build:rpm (rocky9) (push) Successful in 13m21s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 12m30s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 11m55s
Build Packages / DIALS test (push) Successful in 13m42s
Build Packages / XDS test (durin plugin) (push) Successful in 9m26s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 6m41s
Build Packages / XDS test (neggia plugin) (push) Successful in 6m12s
Build Packages / Generate python client (push) Successful in 19s
Build Packages / Build documentation (push) Successful in 52s
Build Packages / Create release (push) Skipped
Build Packages / build:viewer-tgz:cpu (push) Successful in 5m29s
Build Packages / build:viewer-tgz:cuda (push) Successful in 6m12s
Build Packages / build:windows:cuda (push) Successful in 18m36s
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.

* rugnux: Add `--model model.pdb` - score the merged data against an atomic model and compute initial maps. It reports R-work/R-free (scaling the model to the observed amplitudes with an overall scale, an anisotropic B and a flat bulk solvent - the standard few-parameter model, so a batch of maps stays directly comparable) and writes 2Fo-Fc / Fo-Fc electron-density maps (CCP4) plus a map-coefficient MTZ. The structure itself is not refined; the model is only re-fractionalised into the data cell.
* rugnux: The merged reflection output now carries French-Wilson amplitudes (|F| and its sigma) next to the intensities - MTZ `F`/`SIGF`, mmCIF `_refln.F_meas_au`, and the text HKL - computed with the correct centric/acentric Wilson prior and epsilon multiplicity, so a downstream program (e.g. phenix.refine) can refine against amplitudes. The intensity columns are unchanged.
* rugnux: R-free test-set flags are now assigned deterministically and consistently across symmetry - a Bijvoet pair I(+)/I(-) is never split between the work and free sets, and the assignment is a reproducible per-hkl hash that depends only on the reflection index, so every dataset of one crystal form gets the same ~5% free set (what a multi-dataset campaign such as PanDDA needs). On small data the fraction is floored so the test set stays large enough for a stable R-free (~500 reflections, capped at 10%); it stays flat at 5% on ordinary data. When a reference MTZ carries a `FreeR_flag` column its test set is imported instead, letting a whole campaign inherit one shared free set.
* rugnux: A reference MTZ (`--reference-mtz`) can now fix the space group and cell for rotation data too (previously rejected), without being used to scale - the rotation merge stays self-consistent. When the crystal has an indexing (merohedral) ambiguity - a lattice symmetry higher than its Laue symmetry, e.g. P3/P4/P6/C2 - the reference also resolves it: each candidate reindexing (identity plus the twin-law cosets of the metric symmetry) is scored by its intensity correlation against the reference and the data are re-merged in the best-correlating one. This is a metric-preserving relabelling of hkl (the cell is unchanged) and a no-op for a holohedral crystal such as lysozyme.
* rugnux: `--model` validation now aligns the data to the model before scoring - the observed reflections are reindexed into the model's enantiomorph when the two differ only by hand (indistinguishable from merged intensities). A merohedral indexing ambiguity is resolved against the reference MTZ when one is given (so a whole campaign shares one indexing convention); only with a model and no reference does validation fall back to fitting each candidate reindexing and keeping the lowest R-free.
* rugnux: De-novo symmetry - recover a genuine high-symmetry group whose data are imperfectly scaled. Such a merge's within-orbit chi² lands just past the self-consistency bound (each real symmetry step adds a little systematic scatter), right where a merohedral twin also lands, so the chi² ratio alone cannot separate them. The candidate is now rescued when the extra intensity-proportional systematic error it invokes stays small relative to the confirmed subgroup - a genuine symmetry step gains multiplicity without inflating the merge error model's b, whereas a twin forces non-equivalent reflections together and b balloons. Fixes cubic insulin (I23 instead of I222) with no change to any other crystal in the test battery, including the twins that must stay in their lower symmetry.
* Docs: Document the French-Wilson amplitude estimation, R-free flagging, reference-based space-group/ambiguity resolution, and model-based validation/maps in CPU_DATA_ANALYSIS.md.
* Frontend: The status-bar pill now shows a progress bar during detector calibration (previously only during measurement), and the calibration state and its button are labelled "Calibration"/"CALIBRATE" (the internal `Pedestal` state name is unchanged for back-compatibility).Reviewed-on: #69

Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
2026-07-13 13:54:03 +02:00
leonarski_f 451310f43d v1.0.0-rc.158 (#68)
Build Packages / Unit tests (push) Successful in 1h32m35s
Build Packages / build:windows:cuda (push) Successful in 18m0s
Build Packages / build:viewer-tgz:cpu (push) Successful in 7m37s
Build Packages / build:viewer-tgz:cuda (push) Successful in 8m55s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 14m13s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 14m11s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 14m35s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 13m57s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 14m23s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 12m45s
Build Packages / build:rpm (rocky8) (push) Successful in 11m39s
Build Packages / build:rpm (rocky9) (push) Successful in 14m0s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 13m42s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 12m38s
Build Packages / DIALS test (push) Successful in 14m55s
Build Packages / XDS test (durin plugin) (push) Successful in 7m11s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 9m7s
Build Packages / XDS test (neggia plugin) (push) Successful in 8m34s
Build Packages / Generate python client (push) Successful in 28s
Build Packages / Build documentation (push) Successful in 1m3s
Build Packages / Create release (push) Skipped
Build Packages / build:windows:nocuda (push) Successful in 9m55s
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.

* Analysis: The azimuthal-integration solid-angle correction now follows the incidence angle to the detector normal (`cos^3` of that angle) instead of `cos^3(2*theta)`, so it is correct for a tilted detector and matches PyFAI `solidAngleArray` and MAX IV azint (unchanged for an untilted detector). Crystal geometry refinement (`XtalOptimizer`) no longer silently ignores an imported PONI `rot3` (rotation about the beam): it is applied as a fixed rotation in the residual so refinement stays consistent with the rest of the pipeline. Polarization and azimuthal binning already honoured `rot3` through the full PONI rotation.
* jfjoch_viewer: Open datasets on the WSL2/UNC filesystem (paths starting `\\`); write processing outputs next to the input file, with a Browse button and independent `_process.h5` / merged `.mtz`/`.cif` toggles; and show the determined space group in the merge-statistics window.
* rugnux: Accept an absolute `-o` output prefix in offline processing.
* Packaging: The self-contained Linux viewer `.tgz` now bundles cuFFT, so it runs without a system CUDA toolkit (`.deb`/`.rpm` are unchanged, distro-managed).
* Docs: Bring the analysis references up to date with the code. `docs/CPU_DATA_ANALYSIS.md` now reflects the unified profile-fit Bragg integration engine, multi-lattice indexing, azimuthal phi binning, the radial parallax/bandwidth profile with sub-pixel centring, the rot3d capture-fraction handling and the automatic CC1/2 resolution cutoff, and drops the descriptions of features that were never implemented (French-Wilson amplitudes, the still excitation-error partiality model); `docs/RUGNUX.md` documents the new `--resolution-cutoff`/`--resolution-cc-target`/`--resolution-shells`, `--min-captured-fraction`, `--mosaicity`, `--reference-column`, the azimuthal correction toggles and the geometry-override options, and corrects the `-N` default. The outdated in-source design notes (ICE_RING_DETECTION, BRAGG_INTEGRATION_ENGINE, NEXTGEN_INTEGRATOR) are removed.Reviewed-on: #68

Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
2026-07-12 19:42:29 +02:00
leonarski_f 54c0100e8e v1.0.0-rc.157 (#67)
Build Packages / Unit tests (push) Successful in 1h28m28s
Build Packages / build:windows:nocuda (push) Successful in 14m45s
Build Packages / build:windows:cuda (push) Successful in 13m13s
Build Packages / build:viewer-tgz:cpu (push) Successful in 6m47s
Build Packages / build:viewer-tgz:cuda (push) Successful in 7m22s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 13m52s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 14m16s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 13m19s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 12m50s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 14m40s
Build Packages / build:rpm (rocky8) (push) Successful in 11m18s
Build Packages / build:rpm (rocky9) (push) Successful in 12m4s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 11m55s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 11m22s
Build Packages / DIALS test (push) Successful in 13m37s
Build Packages / XDS test (durin plugin) (push) Successful in 8m47s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 9m4s
Build Packages / XDS test (neggia plugin) (push) Successful in 7m45s
Build Packages / Generate python client (push) Successful in 34s
Build Packages / Build documentation (push) Successful in 1m4s
Build Packages / Create release (push) Skipped
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 7m16s
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.

* rugnux: Rebrand the offline data-processing subsystem as `rugnux` and consolidate all offline analysis into the single `rugnux` binary - `jfjoch_process` is now `rugnux`, the former `jfjoch_azint` is now `rugnux --azint-only`, and `jfjoch_scale` is now `rugnux --scale` (see the new docs/NAMING.md and docs/RUGNUX.md). Scaling and merging are on by default for rotation and stills (`--no-merge` disables them), replacing the previous opt-in `-M, --scale-merge`.
* rugnux: CLI fixes - default `-N` to all hardware threads, parse numeric option arguments strictly (reject non-numeric or trailing input instead of silently yielding 0), require `--wavelength > 0`, and correct the reproduced command line and `--scale` reference-cell handling.
* rugnux: De-novo space-group improvements - recover genuine high symmetry and centred Bravais lattices from intensities, add an automatic CC1/2 high-resolution cutoff, and report L-test twinning statistics.
* rugnux: Index weakly-diffracting low-resolution rotation data that previously failed (e.g. F-cubic crystals that diffract only to ~4 A on a detector reaching ~1.5 A). The per-frame indexing gate now measures the indexed fraction only within the resolution range the lattice actually diffracts to, so the many sub-diffraction ice/noise spots no longer make the fraction floor unreachable; the two-pass first pass tries several image-sampling schemes (spread across the whole rotation vs a consecutive wedge whose native stride keeps a reflection's rocking curve continuous, letting the FFT resolve a long axis) and keeps the one that indexes the most frames; and the de-novo space-group search no longer discards all reflections (and crashes) when every resolution shell falls below <I/sigma> = 1.
* rugnux: Lower the low-resolution R-meas for strongly-diffracting rotation data - drop edge-of-sweep truncated fulls whose rocking curve was captured below `--min-captured-fraction` (default 0.7 for rotation), and report R-meas only over the observations kept by outlier rejection (matching XDS). The 0.7 default also strips the partiality-extrapolated fulls that dominate the intensity second moment on weakly-diffracting crystals, so the de-novo space-group search is no longer starved by the error-model I/sigma floor and recovers the correct symmetry (e.g. the F-cubic Benas crystals: Benas_3 -> F432, Benas_7 -> P6122, instead of P4/P1); on the reference battery every other crystal keeps its space group.
* rugnux: Write the refined geometry (beam, tilt, axis) to _process.h5 and place non-standard mmCIF items under a reserved `jfjoch` prefix.
* jfjoch_broker: Ordinary acquisition failures (receiver/writer/analysis problems, missed packets, writer disconnect) now return to the Idle state with an Error-severity message, so a run can be retried without an expensive re-initialisation; only failures that leave the detector in an undefined state (new JFJochCriticalException, e.g. PCIe/FPGA faults) go to the Error state and force re-initialisation.
* jfjoch_broker: A synchronous /start now reports its failure to the HTTP caller instead of returning HTTP 200, and an incomplete or truncated dataset (missing packets, writer disconnect) is reported as an error rather than a "reduce frame rate" warning.
* jfjoch_broker: Drop uncollected placeholder rows (number = -1) from the scan_result REST endpoint.
* jfjoch_broker: Fix the inverted per-image compression ratio reported by the Lite receiver (was compressed/uncompressed instead of uncompressed/compressed).
* jfjoch_broker: Bragg integration adds a quantization-noise variance floor with a box-sum fallback, and treats the type-maximum marker as an invalid pixel for unsigned image types.
* jfjoch_writer: Detect file-overwrite conflicts at start for back-channel transports, and reset the writer when end-of-collection finalisation fails.
* jfjoch_viewer: Preview overlays follow the geometry (resolution/ROI arcs, true beam centre, predictions, coral secondary-lattice spots, legend), add save-as-JPEG, and fix an HTTP live-follow memory leak.
* Frontend: Improved aesthetics and usability, and added in-browser pixel-mask and JUNGFRAU-pedestal visualisation.
* CI: Name the Windows installer jfjoch-viewer-* instead of jfjoch-*.Reviewed-on: #67

Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
2026-07-11 07:19:11 +02:00
leonarski_f d6389e12da v1.0.0-rc.156 (#66)
Build Packages / Unit tests (push) Skipped
Build Packages / build:windows:nocuda (push) Successful in 15m31s
Build Packages / build:viewer-tgz:cpu (push) Successful in 5m46s
Build Packages / build:viewer-tgz:cuda (push) Successful in 6m9s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 9m25s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 10m21s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 9m41s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 9m18s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 10m26s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 11m33s
Build Packages / build:rpm (rocky8) (push) Successful in 10m32s
Build Packages / build:rpm (rocky9) (push) Successful in 12m23s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 10m50s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 10m12s
Build Packages / DIALS test (push) Successful in 12m6s
Build Packages / XDS test (durin plugin) (push) Successful in 8m15s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 7m12s
Build Packages / XDS test (neggia plugin) (push) Successful in 5m35s
Build Packages / Generate python client (push) Successful in 27s
Build Packages / Build documentation (push) Successful in 54s
Build Packages / Create release (push) Skipped
Build Packages / build:windows:cuda (push) Successful in 12m37s
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_process: Major rotation (rot3d) data processing overhaul - robust profile-fit integration, Cauchy-loss scaling with optional absorption surface, de-novo indexing and space-group/centering determination fixes, and merging statistics + ISa in the mmCIF output.
* jfjoch_process: Add EXPERIMENTAL ice-ring detection (--detect-ice-rings) that excludes ice reflections from scaling.
* Compression: Add BSHUF_ZSTD_RLE_HUFF, make compression size-aware (drop frames that don't fit rather than aborting), and add the jfjoch_recompress tool.
* jfjoch_viewer: Report "Multiple lattices detected" and grey out "Analyze dataset" on a live connection.
* jfjoch_broker: Write smargon chi/phi goniometer positions to NXmx; read sensor thickness/material from HDF5 metadata.
* CI: Build Windows (CUDA and non-CUDA) installers.Reviewed-on: #66

Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
2026-07-03 19:18:56 +02:00
leonarski_f 54c667190f v1.0.0-rc.155 (#65)
Build Packages / Unit tests (push) Successful in 1h26m8s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 13m38s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 13m45s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 13m39s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 12m55s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 13m51s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 14m35s
Build Packages / build:rpm (rocky8) (push) Successful in 12m28s
Build Packages / build:rpm (rocky9) (push) Successful in 13m20s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 12m15s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 11m43s
Build Packages / DIALS test (push) Successful in 14m21s
Build Packages / XDS test (durin plugin) (push) Successful in 7m48s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 7m52s
Build Packages / XDS test (neggia plugin) (push) Successful in 7m31s
Build Packages / Generate python client (push) Successful in 15s
Build Packages / Build documentation (push) Successful in 53s
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_process: Remove pixelrefine option (replaced with ProfileIntegrate2D)
* jfjoch_viewer: Some graphical improvements.
* jfjoch_viewer: Simplify und unify data analysis settings.
* jfjoch_writer: Add TCP keepalive to increase robustness if jfjoch_broker "dies" in the middle of data acquisition.

Reviewed-on: #65
2026-06-25 22:01:48 +02:00
leonarski_f 6136f858af v1.0.0-rc.154 (#64)
Build Packages / Unit tests (push) Successful in 1h26m51s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 13m23s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 13m56s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 13m43s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 12m53s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 13m44s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 14m22s
Build Packages / build:rpm (rocky8) (push) Successful in 13m1s
Build Packages / build:rpm (rocky9) (push) Successful in 14m6s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 13m0s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 11m51s
Build Packages / DIALS test (push) Successful in 13m52s
Build Packages / XDS test (durin plugin) (push) Successful in 9m24s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 9m35s
Build Packages / XDS test (neggia plugin) (push) Successful in 6m57s
Build Packages / Generate python client (push) Successful in 35s
Build Packages / Build documentation (push) Successful in 47s
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: Fix to TCP file pusher (remove kernel zero copy to improve reliability)

Reviewed-on: #64
Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
Co-committed-by: Filip Leonarski <filip.leonarski@psi.ch>
2026-06-25 18:12:00 +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
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
2026-06-17 20:36:24 +02:00
leonarski_f ef52dac2ee v1.0.0-rc.151 (#61)
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 11m34s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 12m52s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 12m54s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 9m48s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 12m50s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 13m54s
Build Packages / build:rpm (rocky8) (push) Successful in 12m46s
Build Packages / build:rpm (rocky9) (push) Successful in 11m56s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 10m34s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 9m54s
Build Packages / DIALS test (push) Successful in 13m1s
Build Packages / XDS test (durin plugin) (push) Successful in 8m32s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 8m44s
Build Packages / XDS test (neggia plugin) (push) Successful in 8m3s
Build Packages / Generate python client (push) Successful in 13s
Build Packages / Build documentation (push) Successful in 47s
Build Packages / Create release (push) Skipped
Build Packages / Unit tests (push) Successful in 43m38s
* jfjoch_broker: For PSI EIGER detector allow to disable individual half-modules by putting empty hostname

Reviewed-on: #61
Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
Co-committed-by: Filip Leonarski <filip.leonarski@psi.ch>
2026-06-16 14:13:29 +02:00
leonarski_f 90e804acd7 v1.0.0-rc.150 (#60)
Build Packages / Unit tests (push) Successful in 42m49s
Build Packages / DIALS test (push) Successful in 29m45s
Build Packages / XDS test (durin plugin) (push) Successful in 19m27s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 18m52s
Build Packages / XDS test (neggia plugin) (push) Successful in 13m0s
Build Packages / Generate python client (push) Successful in 28s
Build Packages / Build documentation (push) Successful in 1m25s
Build Packages / Create release (push) Skipped
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 10m53s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 12m49s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 13m7s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 13m9s
Build Packages / build:rpm (rocky8) (push) Successful in 13m24s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 14m11s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 14m15s
Build Packages / build:rpm (rocky9) (push) Successful in 14m30s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 8m14s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 9m5s
* jfjoch_broker: When in FPGA workflow (with PSI detectors) azimuthal integration might be forced to CPU - this will require more computational power, but it enables more integration bins and reports standard deviation of each bin.
* jfjoch_broker: Raise error if one is in FPGA flow and there are too many azimuthal integration bins.

Reviewed-on: #60
2026-06-15 20:24:15 +02:00
leonarski_f ea575f790a v1.0.0-rc.149 (#59)
Build Packages / Unit tests (push) Skipped
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 24m44s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 23m45s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 26m12s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 26m53s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 28m49s
Build Packages / build:rpm (rocky8) (push) Successful in 25m28s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 29m49s
Build Packages / XDS test (durin plugin) (push) Successful in 18m59s
Build Packages / Generate python client (push) Successful in 51s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 23m42s
Build Packages / Create release (push) Skipped
Build Packages / Build documentation (push) Successful in 1m51s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 26m30s
Build Packages / XDS test (neggia plugin) (push) Successful in 19m47s
Build Packages / build:rpm (rocky9) (push) Successful in 29m37s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 22m18s
Build Packages / DIALS test (push) Successful in 30m9s
* XDS plugin: Fix HDF5 mutex to run on multiple processors

Reviewed-on: #59
2026-06-13 21:27:41 +02:00
leonarski_f cc3eb8352c v1.0.0-rc.148 (#58)
Build Packages / Unit tests (push) Skipped
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 9m28s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 10m9s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 9m47s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 10m58s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 11m39s
Build Packages / build:rpm (rocky8) (push) Successful in 11m43s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 12m59s
Build Packages / Generate python client (push) Successful in 35s
Build Packages / Build documentation (push) Successful in 59s
Build Packages / Create release (push) Skipped
Build Packages / build:rpm (ubuntu2204) (push) Successful in 11m48s
Build Packages / build:rpm (rocky9) (push) Successful in 12m32s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 10m24s
Build Packages / XDS test (durin plugin) (push) Successful in 7m35s
Build Packages / XDS test (neggia plugin) (push) Successful in 6m50s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 7m40s
Build Packages / DIALS test (push) Successful in 11m19s
This is an UNSTABLE release. The release has significant modifications for data processing - in case of troubles go back to 1.0.0-rc.144.

* jfjoch_broker: Improve azimuthal integration (add <I^2> calculation)
* jfjoch_broker: Fixes around indexing, aiming to handle multi-lattice crystals (work in progress, it is not fully integrated)
* jfjoch_writer: Save mean(I), stddev(I), and count(I) for each azimuthal bin

Reviewed-on: #58
2026-06-08 08:30:35 +02:00
leonarski_f 75de40f52b v1.0.0-rc.147 (#57)
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 7m27s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 8m20s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 7m35s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 5m59s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 7m25s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 8m30s
Build Packages / build:rpm (rocky8) (push) Successful in 7m39s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 8m16s
Build Packages / build:rpm (rocky9) (push) Successful in 9m35s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 8m6s
Build Packages / Generate python client (push) Successful in 12s
Build Packages / Build documentation (push) Successful in 31s
Build Packages / Create release (push) Skipped
Build Packages / XDS test (durin plugin) (push) Successful in 7m6s
Build Packages / DIALS test (push) Successful in 12m3s
Build Packages / XDS test (neggia plugin) (push) Successful in 5m11s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 5m50s
Build Packages / Unit tests (push) Successful in 57m33s
This is an UNSTABLE release. The release has significant modifications for data processing - in case of troubles go back to 1.0.0-rc.144.

* jfjoch_viewer: Add reciprocal space viewer
* jfjoch_process: Two pass algorithm that does spot finding/indexing + integration of full dataset
* jfjoch_process: Improve logic for rotation indexer, to make execution more deterministic (still work in progress)

Reviewed-on: #57
Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
Co-committed-by: Filip Leonarski <filip.leonarski@psi.ch>
2026-06-02 11:49:24 +02:00
leonarski_f fc68a9baed v1.0.0-rc.146 (#56)
Build Packages / Unit tests (push) Skipped
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 8m34s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 10m0s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 10m23s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 10m23s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 11m16s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 11m49s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 8m32s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 9m15s
Build Packages / XDS test (durin plugin) (push) Successful in 7m16s
Build Packages / Generate python client (push) Successful in 16s
Build Packages / build:rpm (rocky9) (push) Successful in 10m12s
Build Packages / Create release (push) Skipped
Build Packages / Build documentation (push) Successful in 47s
Build Packages / DIALS test (push) Successful in 10m18s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 5m46s
Build Packages / build:rpm (rocky8) (push) Successful in 1h41m2s
Build Packages / XDS test (neggia plugin) (push) Successful in 1h59m18s
This is an UNSTABLE release. The release has significant modifications for data processing - in case of troubles go back to 1.0.0-rc.144.

jfjoch_process: Generate a dedicated file (_process.h5), which can be used as a replacement for the _master.h5 file for a reanalyzed dataset.
jfjoch_process: Improve the performance of scaling and merging, implement on the fly scaling.
jfjoch_writer: All final data analysis results are repopulated in the _master.h5 file.
jfjoch_scale: Dedicated tool for rescaling/merging existing data.
jfjoch_viewer: Fix bugs where pixel labels where displayed on a wrong pixel.

WARNING! Scaling and merging are experimental at the moment, and may not provide reasonable results for the time being.

Reviewed-on: #56
2026-05-28 18:48:35 +02:00
leonarski_f 75f1c5f954 SHIM library improvements from the HDF Group
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 13m40s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 15m26s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 17m15s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 17m22s
Build Packages / build:rpm (rocky8) (push) Successful in 17m28s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 17m42s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 18m32s
Build Packages / build:rpm (rocky9) (push) Successful in 10m0s
Build Packages / Generate python client (push) Successful in 43s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 9m31s
Build Packages / Create release (push) Has been skipped
Build Packages / Build documentation (push) Successful in 57s
Build Packages / XDS test (neggia plugin) (push) Successful in 9m46s
Build Packages / XDS test (durin plugin) (push) Successful in 11m1s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 10m54s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 11m58s
Build Packages / DIALS test (push) Successful in 13m41s
Build Packages / Unit tests (push) Successful in 1h1m14s
2026-05-08 11:39:51 +02:00
leonarski_f caef26873e v1.0.0-rc.145 (#55)
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 16m26s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 14m26s
Build Packages / build:rpm (rocky8) (push) Successful in 17m23s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 17m32s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 18m16s
Build Packages / build:rpm (rocky9) (push) Successful in 12m45s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 12m58s
Build Packages / XDS test (durin plugin) (push) Successful in 11m22s
Build Packages / DIALS test (push) Successful in 14m28s
Build Packages / Generate python client (push) Successful in 1m1s
Build Packages / Build documentation (push) Successful in 2m40s
Build Packages / Create release (push) Has been skipped
Build Packages / XDS test (neggia plugin) (push) Successful in 10m52s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 15m2s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 17m25s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 11m49s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 11m34s
Build Packages / Unit tests (push) Successful in 44m51s
This is an UNSTABLE release. The release has significant modifications for HDF5 writing logic - in case of troubles go back to 1.0.0-rc.144.

* **Default HDF5 writing mode is with VDS, not soft-links** - this improves DIALS compatibility and makes format more future-proof, NXmx legacy format might be phased-out in the future.
* XDS plugin: Improve performance of VDS reading.
* jfjoch_writer: Significant improvement on how file systems I/O are handled through a dedicated pass-through VFD.
* jfjoch_writer: Clean-up of HDF5 routines to better handle issues.

Reviewed-on: #55
2026-05-06 21:50:02 +02:00
leonarski_f 7d34e8a049 v1.0.0-rc.144 (#54)
Build Packages / build:rpm (ubuntu2404) (push) Successful in 8m58s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 11m53s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 10m39s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 7m34s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 9m18s
Build Packages / build:rpm (rocky8) (push) Successful in 10m4s
Build Packages / build:rpm (rocky9) (push) Successful in 11m17s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 9m47s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 10m47s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 10m33s
Build Packages / Generate python client (push) Successful in 27s
Build Packages / Unit tests (push) Has been skipped
Build Packages / Create release (push) Has been skipped
Build Packages / Build documentation (push) Successful in 1m8s
Build Packages / XDS test (durin plugin) (push) Successful in 7m40s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 7m23s
Build Packages / XDS test (neggia plugin) (push) Successful in 7m9s
Build Packages / DIALS test (push) Successful in 11m15s
This is an UNSTABLE release. The release has significant modifications and bug fixes, if things go wrong, it is better to revert to 1.0.0-rc.132.

* jfjoch_broker: Improve performance of preview JPEG image generator at receiver startup (saving about 150 ms on measurement start for 16M)

Reviewed-on: #54
Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
Co-committed-by: Filip Leonarski <filip.leonarski@psi.ch>
2026-05-01 17:06:36 +02:00
leonarski_f 6e0bb971ac v1.0.0-rc.143 (#53)
Build Packages / Unit tests (push) Successful in 1h13m11s
Build Packages / Generate python client (push) Successful in 33s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 14m1s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 15m12s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 14m34s
Build Packages / build:rpm (rocky8) (push) Successful in 15m43s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 16m35s
Build Packages / build:rpm (rocky9) (push) Successful in 16m19s
Build Packages / XDS test (durin plugin) (push) Successful in 12m11s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 14m1s
Build Packages / DIALS test (push) Successful in 16m59s
Build Packages / Create release (push) Has been skipped
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 13m32s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 15m12s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 11m33s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 10m25s
Build Packages / Build documentation (push) Successful in 58s
Build Packages / XDS test (neggia plugin) (push) Successful in 10m33s
This is an UNSTABLE release. The release has significant modifications and bug fixes, if things go wrong, it is better to revert to 1.0.0-rc.132.

jfjoch_broker: Avoid copying gain calibration together with DiffractionExperiment

Reviewed-on: #53
2026-04-30 22:16:50 +02:00
leonarski_f 87fde1b32e v1.0.0-rc.142 (#52)
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 16m19s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 16m29s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 16m51s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 9m17s
Build Packages / build:rpm (rocky8) (push) Successful in 12m7s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 14m34s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 14m44s
Build Packages / build:rpm (rocky9) (push) Successful in 16m4s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 12m49s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 12m56s
Build Packages / Generate python client (push) Successful in 1m0s
Build Packages / Unit tests (push) Has been skipped
Build Packages / Create release (push) Has been skipped
Build Packages / Build documentation (push) Successful in 1m43s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 8m14s
Build Packages / XDS test (durin plugin) (push) Successful in 8m58s
Build Packages / XDS test (neggia plugin) (push) Successful in 7m44s
Build Packages / DIALS test (push) Successful in 13m4s
This is an UNSTABLE release. The release has significant modifications and bug fixes, if things go wrong, it is better to revert to 1.0.0-rc.132.

* Support for newer CUDA architectures (notably Blackwell); minimum CUDA version 12.8
* Minor changes to jfjoch_process, jfjoch_fpga_test and jfjoch_lite_perf_test to make them more consistent

Reviewed-on: #52
Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
Co-committed-by: Filip Leonarski <filip.leonarski@psi.ch>
2026-04-30 16:47:53 +02:00
leonarski_f d760b12a18 v1.0.0-rc.141 (#51)
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 9m32s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 10m19s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 11m49s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 12m37s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 12m23s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 11m44s
Build Packages / build:rpm (rocky8) (push) Successful in 9m15s
Build Packages / build:rpm (rocky9) (push) Successful in 12m14s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 11m28s
Build Packages / Generate python client (push) Successful in 21s
Build Packages / XDS test (durin plugin) (push) Successful in 8m58s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 12m7s
Build Packages / Build documentation (push) Successful in 42s
Build Packages / Create release (push) Has been skipped
Build Packages / XDS test (JFJoch plugin) (push) Successful in 8m24s
Build Packages / DIALS test (push) Successful in 14m1s
Build Packages / XDS test (neggia plugin) (push) Successful in 7m26s
Build Packages / Unit tests (push) Failing after 1h20m14s
This is an UNSTABLE release. The release has significant modifications and bug fixes, if things go wrong, it is better to revert to 1.0.0-rc.132.

* jfjoch_broker: Azimuthal integration mapping is generated with parallel computations, significantly reducing setup times
* frontend: Fix selection of FFTW in indexing settings

Reviewed-on: #51
Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
Co-committed-by: Filip Leonarski <filip.leonarski@psi.ch>
2026-04-30 13:04:54 +02:00
leonarski_f 239a441ee6 v1.0.0-rc.140 (#50)
Build Packages / Unit tests (push) Successful in 1h20m34s
Build Packages / build:rpm (rocky8) (push) Successful in 13m32s
Build Packages / Generate python client (push) Successful in 24s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 13m6s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 11m32s
Build Packages / XDS test (durin plugin) (push) Successful in 10m49s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 14m8s
Build Packages / DIALS test (push) Successful in 14m57s
Build Packages / Build documentation (push) Successful in 47s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 13m30s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 14m23s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 14m40s
Build Packages / Create release (push) Has been skipped
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 13m14s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 11m55s
Build Packages / build:rpm (rocky9) (push) Successful in 14m23s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 9m48s
Build Packages / XDS test (neggia plugin) (push) Successful in 7m10s
This is an UNSTABLE release. The release has significant modifications and bug fixes, if things go wrong, it is better to revert to 1.0.0-rc.132.

* jfjoch_broker: For DECTRIS detectors, ZeroMQ link is persistent, to save time for establishing new connection
* jfjoch_broker: Minor bug fixes for rare conditions

Reviewed-on: #50
2026-04-29 21:40:22 +02:00
leonarski_f 4878318c27 v1.0.0-rc.139 (#49)
Build Packages / Unit tests (push) Successful in 1h17m4s
Build Packages / Generate python client (push) Successful in 1m24s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 12m34s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 12m37s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 11m11s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 12m4s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 11m59s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 13m4s
Build Packages / build:rpm (rocky8) (push) Successful in 13m12s
Build Packages / XDS test (durin plugin) (push) Successful in 9m57s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 11m52s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 12m30s
Build Packages / build:rpm (rocky9) (push) Successful in 13m59s
Build Packages / Build documentation (push) Successful in 1m7s
Build Packages / XDS test (neggia plugin) (push) Successful in 9m24s
Build Packages / Create release (push) Has been skipped
Build Packages / XDS test (JFJoch plugin) (push) Successful in 9m54s
Build Packages / DIALS test (push) Successful in 13m14s
This is an UNSTABLE release. The release has significant modifications and bug fixes, if things go wrong, it is better to revert to 1.0.0-rc.132.

* jfjoch_broker: Further reduce startup time for DECTRIS detectors by selectively modifying SIMPLON parameters on `/start`
* jfjoch_broker: Further reduce startup time for DECTRIS detectors by not setting beam center and detector distance via SIMPLON API on '/start'
* jfjoch_broker: Add an extra message to ZeroMQ puller ready to monitor Lite worklow preparation time
* jfjoch_broker: Image buffer configuration is postponed for Lite receiver flow till start message is received
* jfjoch_broker: Use nanoseconds internally for frame/image/readout time
* jfjoch_broker: Extra messages added for receiver operation (to be removed after debugging finished)
* jfojch_broker: Improve profiling of different data analysis steps
* jfjoch_broker: Record integration reflection count
* jfjoch_broker: Fix bug where ZeroMQ preview frequency was confusing time units (micro vs. milliseconds)
* jfjoch_broker: Fix bug where '/wait_till_done' got deadlocked
* jfjoch_writer: Fix confusion between NaN and zero in floating-point datasets

**Breaking changes**: detector definition is now using nanoseconds to define minimum frame time, minimum count time and readout time.

Reviewed-on: #49
2026-04-29 09:50:50 +02:00
leonarski_fandtakaba_k 230480e390 v1.0.0-rc.138 (#48)
Build Packages / XDS test (durin plugin) (push) Successful in 8m5s
Build Packages / DIALS test (push) Successful in 12m55s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 14m41s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 16m13s
Build Packages / build:rpm (rocky8) (push) Successful in 18m17s
Build Packages / build:rpm (rocky9) (push) Successful in 19m14s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 9m59s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 9m17s
Build Packages / Generate python client (push) Successful in 1m15s
Build Packages / XDS test (neggia plugin) (push) Successful in 9m58s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 14m14s
Build Packages / Create release (push) Has been skipped
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 11m9s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 18m21s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 19m14s
Build Packages / Build documentation (push) Successful in 1m43s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 10m14s
Build Packages / Unit tests (push) Successful in 57m40s
This is an UNSTABLE release. The release has significant modifications and bug fixes, if things go wrong, it is better to revert to 1.0.0-rc.132.

    jfjoch_broker: Cleanup DECTRIS start-up code to enable a shorter start time
    jfjoch_broker: Allow for asynchronous start to allow overlapping detector configuration with other beamline preparations
    jfjoch_broker: Goniometer axis name is converted to lowercase
    jfjoch_broker: Fix bug, where wrong HTTP error codes were returned
    jfjoch_broker: Improve sigma estimation during merging (K. Takaba)

---------

Co-authored-by: takaba_k <kiyofumi.takaba@psi.ch>
Reviewed-on: #48
Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch>
Co-committed-by: Filip Leonarski <filip.leonarski@psi.ch>
2026-04-27 19:56:14 +02:00
leonarski_f c981e1b91c v1.0.0-rc.137 (#46)
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 10m7s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 10m35s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 11m8s
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 9m24s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 11m29s
Build Packages / build:rpm (rocky8) (push) Successful in 10m27s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 11m41s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 11m1s
Build Packages / Generate python client (push) Successful in 45s
Build Packages / Unit tests (push) Has been skipped
Build Packages / Create release (push) Has been skipped
Build Packages / build:rpm (rocky9) (push) Successful in 12m48s
Build Packages / Build documentation (push) Successful in 1m3s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 12m10s
Build Packages / XDS test (durin plugin) (push) Successful in 8m59s
Build Packages / XDS test (neggia plugin) (push) Successful in 7m32s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 8m39s
Build Packages / DIALS test (push) Successful in 13m13s
This is an UNSTABLE release. The release has significant modifications and bug fixes, if things go wrong, it is better to revert to 1.0.0-rc.132.

* jfjoch_broker: Better track time for each operation in the processing stack
* jfjoch_broker: Rewrite preprocessing of diffraction images in the non-FPGA workflow to better use GPUs (work in progress)
* jfjoch_broker: Remove ROI calculation in the non-FPGA workflow (work in progress)
* jfjoch_viewer: Toolbar displays image number starting from 1 (instead of 0)

Reviewed-on: #46
2026-04-25 19:59:21 +02:00
leonarski_f c1c170112c v1.0.0-rc.136 (#45)
Build Packages / build:rpm (ubuntu2404_nocuda) (push) Successful in 11m17s
Build Packages / build:rpm (ubuntu2204_nocuda) (push) Successful in 13m48s
Build Packages / build:rpm (rocky8_nocuda) (push) Successful in 13m57s
Build Packages / build:rpm (rocky8_sls9) (push) Successful in 15m15s
Build Packages / build:rpm (rocky9_nocuda) (push) Successful in 15m35s
Build Packages / build:rpm (rocky9_sls9) (push) Successful in 15m29s
Build Packages / build:rpm (ubuntu2204) (push) Successful in 10m55s
Build Packages / XDS test (durin plugin) (push) Successful in 8m17s
Build Packages / build:rpm (rocky9) (push) Successful in 12m17s
Build Packages / build:rpm (ubuntu2404) (push) Successful in 11m2s
Build Packages / Generate python client (push) Successful in 30s
Build Packages / Create release (push) Has been skipped
Build Packages / Build documentation (push) Successful in 51s
Build Packages / XDS test (JFJoch plugin) (push) Successful in 7m13s
Build Packages / DIALS test (push) Successful in 13m19s
Build Packages / XDS test (neggia plugin) (push) Successful in 5m52s
Build Packages / Unit tests (push) Successful in 1h18m25s
Build Packages / build:rpm (rocky8) (push) Successful in 7m2s
This is an UNSTABLE release. The release has significant modifications and bug fixes, if things go wrong, it is better to revert to 1.0.0-rc.132.

* jfjoch_broker: Improve logic regarding indexing architecture and thread pools (work in progress).

Reviewed-on: #45
2026-04-20 11:54:33 +02:00
1091 changed files with 120862 additions and 25190 deletions
+3
View File
@@ -1,2 +1,5 @@
*.mcs filter=lfs diff=lfs merge=lfs -text
*.mcs.gz filter=lfs diff=lfs merge=lfs -text
# Large reference datasets for the [large] Catch tests (git-LFS; may not be pulled in CI).
tests/data/*.h5 filter=lfs diff=lfs merge=lfs -text
+168 -40
View File
@@ -1,5 +1,8 @@
name: Build Packages
env:
MARCH_CMAKE_FLAGS: '-DCMAKE_CXX_FLAGS="-march=x86-64-v3" -DCMAKE_C_FLAGS="-march=x86-64-v3"'
on:
push:
branches:
@@ -16,6 +19,150 @@ on:
default: false
jobs:
unit-tests:
name: Unit tests
runs-on: jfjoch_rocky8
if: github.ref_type != 'tag' && github.ref_type != 'workflow_dispatch'
container:
image: gitea.psi.ch/leonarski_f/jfjoch_rocky8:2511
options: --gpus all
timeout-minutes: 90
env:
CTEST_OUTPUT_ON_FAILURE: '1'
steps:
- uses: actions/checkout@v4
- name: Configure auth and fetch LFS
shell: bash
env:
GITEA_TOKEN: ${{ secrets.PIP_REPOSITORY_API_TOKEN }}
run: |
git lfs install --local
AUTH=$(git config --local http.${{ github.server_url }}/.extraheader)
git config --local --unset http.${{ github.server_url }}/.extraheader
git config --local http.${{ github.server_url }}/${{ github.repository }}.git/info/lfs/objects/batch.extraheader "$AUTH"
git lfs pull
- name: Build tests
shell: bash
run: |
mkdir -p build
cd build
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ${{ env.MARCH_CMAKE_FLAGS }} ..
ninja -j48 jfjoch_test jfjoch_hdf5_test jfjoch_hdf5_enospc_test enospc_shim
- name: Run unit tests
shell: bash
run: |
cd build/tests
./jfjoch_test
- name: HDF5 ENOSPC test
shell: bash
run: |
cd build/tests
LD_PRELOAD=./enospc_shim.so ./jfjoch_hdf5_enospc_test HDF5File_enospc
LD_PRELOAD=./enospc_shim.so ./jfjoch_hdf5_enospc_test FileWriter_enospc
- name: Run hdf5 test
shell: bash
run: |
cd build/tools
./jfjoch_hdf5_test ../../tests/test_data/compression_benchmark.h5
build-windows:
name: build:windows:${{ matrix.variant }}
runs-on: windows-11-cuda-qt
timeout-minutes: 120
strategy:
fail-fast: false
matrix:
include:
- variant: cuda
use_cuda: 'ON'
- variant: nocuda
use_cuda: 'OFF'
steps:
- uses: actions/checkout@v4
- name: Configure viewer build
shell: cmd
run: |
for /f "usebackq tokens=*" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath`) do set "VSPATH=%%i"
call "%VSPATH%\VC\Auxiliary\Build\vcvars64.bat"
cmake -G Ninja -B build -DJFJOCH_USE_CUDA=${{ matrix.use_cuda }} -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="C:/deps;C:/Qt/6.11.1/msvc2022_64"
- name: Build viewer
shell: cmd
run: |
for /f "usebackq tokens=*" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath`) do set "VSPATH=%%i"
call "%VSPATH%\VC\Auxiliary\Build\vcvars64.bat"
cmake --build build
- name: Build installer (NSIS)
shell: cmd
run: |
for /f "usebackq tokens=*" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath`) do set "VSPATH=%%i"
call "%VSPATH%\VC\Auxiliary\Build\vcvars64.bat"
cd build
cpack
- name: Upload installer to release
if: github.ref_type == 'tag'
shell: powershell
env:
TOKEN: ${{ secrets.PIP_REPOSITORY_API_TOKEN }}
run: |
# NSIS installer named jfjoch-viewer-<version>-win64-{cuda<major>|cpu}.exe (see CMakeLists.txt).
$files = Get-ChildItem -Path build -Filter 'jfjoch-viewer-*-win64-*.exe'
if ($files.Count -eq 0) { throw 'No Windows installer found in build/' }
foreach ($file in $files) {
python gitea_upload_file.py $file.FullName
if ($LASTEXITCODE -ne 0) { throw "Upload failed for $($file.Name)" }
}
build-viewer-tgz:
name: build:viewer-tgz:${{ matrix.variant }}
runs-on: jfjoch_rocky8
timeout-minutes: 120
strategy:
fail-fast: false
matrix:
include:
- variant: cuda
use_cuda: 'ON'
- variant: cpu
use_cuda: 'OFF'
steps:
- uses: actions/checkout@v4
- name: Clean previous build
shell: bash
run: rm -rf build # self-hosted runners reuse the workspace volume; a stale build dir
# can leave the viewer linking a system libcurl instead of the vendored one
- name: Configure viewer build
shell: bash
run: |
mkdir -p build
cd build
cmake -G Ninja -DJFJOCH_VIEWER_ONLY=ON -DJFJOCH_USE_CUDA=${{ matrix.use_cuda }} ${{ env.MARCH_CMAKE_FLAGS }} -DCMAKE_BUILD_TYPE=Release ..
- name: Build viewer tgz
shell: bash
run: |
cd build
# Build the whole viewer-only tree, not just the GUI: the "viewer" CPack component also
# contains the portable CLI tools (rugnux/rugnux_scale/azint/recompress/extract_hkl),
# which must exist on disk before cpack installs the component.
ninja -j16
cpack
- name: Upload viewer tgz to release
if: github.ref_type == 'tag'
shell: bash
env:
TOKEN: ${{ secrets.PIP_REPOSITORY_API_TOKEN }}
run: |
set -euo pipefail
shopt -s nullglob
# CMakeLists.txt names the archive jfjoch_viewer-<version>-linux-{cuda<major>|cpu}.tar.gz;
# rename to .tgz (matching the Windows installer's release naming) before upload.
files=(build/jfjoch_viewer-*.tar.gz)
if [ ${#files[@]} -eq 0 ]; then
echo "No viewer archive found in build/"
exit 1
fi
for file in "${files[@]}"; do
tgz="${file%.tar.gz}.tgz"
mv "$file" "$tgz"
python3 gitea_upload_file.py "$tgz"
done
build-rpm:
name: build:rpm (${{ matrix.distro }})
if: github.ref_type != 'workflow_dispatch'
@@ -76,12 +223,16 @@ jobs:
upload_url: https://gitea.psi.ch/api/packages/mx/debian/pool/noble/nocuda/upload
steps:
- uses: actions/checkout@v4
- name: Clean previous build
shell: bash
run: rm -rf build # self-hosted runners reuse the workspace volume; a stale build dir
# can leave the viewer linking a system libcurl instead of the vendored one
- name: Setup build (cmake)
shell: bash
run: |
mkdir -p build
cd build
cmake -G Ninja -DJFJOCH_INSTALL_DRIVER_SOURCE=ON -DJFJOCH_VIEWER_BUILD=ON -DCMAKE_BUILD_TYPE=Release ${{ matrix.cmake_flags }} ..
cmake -G Ninja -DJFJOCH_INSTALL_DRIVER_SOURCE=ON -DJFJOCH_VIEWER_BUILD=ON ${{ env.MARCH_CMAKE_FLAGS }} -DCMAKE_BUILD_TYPE=Release ${{ matrix.cmake_flags }} ..
- name: Build packages
shell: bash
run: |
@@ -102,23 +253,30 @@ jobs:
echo "No package files found for pattern: ${{ matrix.pkg_glob }}"
exit 1
fi
url="${{ matrix.upload_url }}"
if [[ "$url" == *"/rpm/"* ]]; then
url="${url}?sign=true"
fi
for file in "${files[@]}"; do
echo "Uploading $file -> ${{ matrix.upload_url }}"
curl --fail --user __token__:"$TOKEN" --upload-file "$file" "${{ matrix.upload_url }}"
echo "Uploading $file -> $url"
curl --fail --user __token__:"$TOKEN" --upload-file "$file" "$url"
done
cd ..
# The viewer is shipped to the release as a Linux-version-agnostic .tgz by the
# build-viewer-tgz job; only the writer (and the XDS plugin .so on rocky8) go to the
# release as distro packages here.
if [ "${{ matrix.distro }}" = "rocky8_nocuda" ]; then
for file in build/jfjoch-viewer*.rpm build/jfjoch-writer*rpm build/xds-plugin/libjfjoch_xds_plugin.so.*; do
for file in build/jfjoch-writer*rpm build/xds-plugin/libjfjoch_xds_plugin.so.*; do
python3 gitea_upload_file.py "$file"
done
elif [ "${{ matrix.distro }}" = "rocky9_nocuda" ]; then
for file in build/jfjoch-viewer*.rpm build/jfjoch-writer*rpm; do
for file in build/jfjoch-writer*rpm; do
python3 gitea_upload_file.py "$file"
done
elif [ "${{ matrix.distro }}" = "ubuntu2204_nocuda" ]; then
for file in build/jfjoch*viewer*.deb build/jfjoch*writer*.deb; do
for file in build/jfjoch*writer*.deb; do
python3 gitea_upload_file.py "$file"
done
fi
@@ -132,7 +290,7 @@ jobs:
run: |
mkdir -p build
cd build
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ..
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ${{ env.MARCH_CMAKE_FLAGS }} ..
ninja -j16 jfjoch_hdf5_test
- name: Run DIALS processing on legacy format
shell: bash
@@ -168,7 +326,7 @@ jobs:
run: |
mkdir -p build
cd build
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ..
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ${{ env.MARCH_CMAKE_FLAGS }} ..
ninja -j16 jfjoch_hdf5_test
- name: Run XDS with Durin and legacy HDF5 format
shell: bash
@@ -204,7 +362,7 @@ jobs:
run: |
mkdir -p build
cd build
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ..
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ${{ env.MARCH_CMAKE_FLAGS }} ..
ninja -j16 jfjoch_hdf5_test
ninja -j16 jfjoch_xds_plugin
- name: Run XDS with legacy HDF5 format
@@ -240,7 +398,7 @@ jobs:
run: |
mkdir -p build
cd build
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ..
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ${{ env.MARCH_CMAKE_FLAGS }} ..
ninja -j16 jfjoch_hdf5_test
- name: Run XDS with Neggia and legacy HDF5 format
shell: bash
@@ -296,36 +454,6 @@ jobs:
git add .
git commit -m "Deploy site"
git push -f https://${{secrets.GITHUB_TOKEN}}@gitea.psi.ch/${{ github.repository }}.git gitea-pages
unit-tests:
name: Unit tests
runs-on: jfjoch_rocky8
if: github.ref_type != 'tag' && github.ref_type != 'workflow_dispatch'
container:
image: gitea.psi.ch/leonarski_f/jfjoch_rocky8:2511
options: --gpus all
timeout-minutes: 90
env:
CTEST_OUTPUT_ON_FAILURE: '1'
steps:
- uses: actions/checkout@v4
- name: Build tests
shell: bash
run: |
mkdir -p build
cd build
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ..
ninja -j48 jfjoch_test jfjoch_hdf5_test
- name: Run unit tests
shell: bash
run: |
cd build/tests
./jfjoch_test
- name: Run hdf5 test
shell: bash
run: |
cd build/tools
./jfjoch_hdf5_test ../../tests/test_data/compression_benchmark.h5
create-release:
name: Create release
runs-on: jfjoch_rocky8
+3
View File
@@ -3,3 +3,6 @@ cmake-build-release/
build*/
python-client/
openapi-generator-cli.jar
# rugnux_vs_xds.py default output dir
rugnux_cmp/
-406
View File
@@ -1,406 +0,0 @@
stages:
- build
- test
- synthesis
- release
variables:
PKG_CONFIG_PATH: /opt/openssl-3.5.4/lib/pkgconfig:/opt/openssl-3.5.4/lib64/pkgconfig
CMAKE_PREFIX_PATH: /opt/qt-6.9.0-static:/opt/eigen-3.4
build:x86:gcc-12:
stage: build
variables:
CC: gcc
CXX: g++
tags:
- gcc
- x86
needs: []
script:
- mkdir build
- cd build
- source /opt/rh/gcc-toolset-12/enable
- cmake -DCMAKE_BUILD_TYPE=Release -DJFJOCH_VIEWER_BUILD=ON ..
- make -j48
build:x86:gcc-13:
stage: build
variables:
CC: gcc
CXX: g++
tags:
- gcc
- x86
needs: []
script:
- mkdir build
- cd build
- source /opt/rh/gcc-toolset-13/enable
- cmake -DCMAKE_BUILD_TYPE=Release -DJFJOCH_VIEWER_BUILD=ON ..
- make -j48
build:x86:gcc_writer:
stage: build
variables:
CC: gcc
CXX: g++
tags:
- gcc
- x86
needs: []
script:
- mkdir build
- cd build
- source /opt/rh/gcc-toolset-12/enable
- cmake -DCMAKE_BUILD_TYPE=Release -DJFJOCH_WRITER_ONLY=ON ..
- make -j48
build:x86:gcc_nocuda:
stage: build
variables:
CC: gcc
CXX: g++
tags:
- gcc
- x86
needs: []
script:
- mkdir build
- cd build
- source /opt/rh/gcc-toolset-12/enable
- cmake -DCMAKE_BUILD_TYPE=Release -DJFJOCH_USE_CUDA=OFF ..
- make -j48
build:x86:driver:
stage: build
variables:
CC: gcc
CXX: g++
tags:
- gcc
- x86
needs: []
script:
- cd fpga/pcie_driver
- make
build:x86:python_client:
stage: build
needs: []
tags:
- python
script:
- bash gen_python_client.sh
artifacts:
paths:
- dist/jfjoch_client-*whl
- dist/jfjoch_client-*tar.gz
expire_in: 1 week
build:x86:frontend:
stage: build
tags:
- x86
needs: []
script:
- mkdir build
- cd build
- /usr/bin/cmake ..
- make frontend
- cd ../frontend/dist
- tar czf ../../jfjoch_frontend.tar.gz *
artifacts:
paths:
- jfjoch_frontend.tar.gz
expire_in: 1 week
build:x86:rpm:
stage: build
tags:
- x86
needs: []
script:
- mkdir build
- cd build
- source /opt/rh/gcc-toolset-12/enable
- cmake -DCMAKE_BUILD_TYPE=Release -DJFJOCH_INSTALL_DRIVER_SOURCE=ON -DJFJOCH_VIEWER_BUILD=ON ..
- make frontend
- make -j48 package
- mv *.rpm ..
artifacts:
paths:
- "jfjoch-*.rpm"
expire_in: 1 week
build:x86:rpm_nocuda:
stage: build
tags:
- x86
needs: []
script:
- mkdir build
- cd build
- source /opt/rh/gcc-toolset-12/enable
- cmake -DCMAKE_BUILD_TYPE=Release -DJFJOCH_INSTALL_DRIVER_SOURCE=ON -DJFJOCH_VIEWER_BUILD=ON -DJFJOCH_USE_CUDA=OFF ..
- make frontend
- make -j48 package
- mv *.rpm ..
artifacts:
paths:
- "jfjoch-viewer*.rpm"
expire_in: 1 week
build:x86:sls9:rpm:
stage: build
tags:
- x86
needs: []
script:
- mkdir build
- cd build
- source /opt/rh/gcc-toolset-12/enable
- cmake -DCMAKE_BUILD_TYPE=Release -DJFJOCH_INSTALL_DRIVER_SOURCE=OFF -DJFJOCH_VIEWER_BUILD=OFF -DSLS9=ON ..
- make frontend
- make -j48 package
- mv *.rpm ..
artifacts:
paths:
- "jfjoch-slsdet9*.rpm"
expire_in: 1 week
test:x86:gcc:
stage: test
timeout: 90m
variables:
CTEST_OUTPUT_ON_FAILURE: 1
CC: gcc
CXX: g++
needs: ["build:x86:gcc-12"]
dependencies: []
tags:
- gcc
- x86
script:
- source /opt/rh/gcc-toolset-12/enable
- mkdir -p build
- cd build
- cmake -DCMAKE_BUILD_TYPE=Release ..
- make -j48 jfjoch_test jfjoch_hdf5_test
- cd tests
- ./jfjoch_test -r junit -o report.xml
- cd ../tools
- ./jfjoch_hdf5_test ../../tests/test_data/compression_benchmark.h5
artifacts:
expire_in: 1 week
reports:
junit: build/tests/report.xml
test:x86:crystfel:
stage: test
timeout: 90m
variables:
CTEST_OUTPUT_ON_FAILURE: 1
CC: gcc
CXX: g++
needs: ["build:x86:gcc-12"]
dependencies: []
tags:
- gcc
- x86
- crystfel
script:
- source /opt/rh/gcc-toolset-12/enable
- mkdir -p build
- cd build
- cmake -DCMAKE_BUILD_TYPE=Release ..
- make -j8 jfjoch_hdf5_test
- cd ../tests/crystfel
- ../../build/tools/jfjoch_hdf5_test ../../tests/test_data/compression_benchmark.h5 10
- indexamajig -i writing_test.lst -g jf4m.geom -o x.stream --indexing=xgandalf
test:x86:xds_durin:
stage: test
timeout: 90m
variables:
CTEST_OUTPUT_ON_FAILURE: 1
CC: gcc
CXX: g++
needs: ["build:x86:gcc-12"]
dependencies: []
tags:
- gcc
- x86
- xds
script:
- source /opt/rh/gcc-toolset-12/enable
- mkdir -p build
- cd build
- cmake -DCMAKE_BUILD_TYPE=Release ..
- make -j8 jfjoch_hdf5_test
- cd ../tests/xds_durin
- ../../build/tools/jfjoch_hdf5_test ../../tests/test_data/compression_benchmark.h5 25
- xds_par |grep -a1 ISa |tail -n1
test:x86:xds_durin_new_hdf5_format:
stage: test
timeout: 90m
variables:
CTEST_OUTPUT_ON_FAILURE: 1
CC: gcc
CXX: g++
needs: ["build:x86:gcc-12"]
dependencies: []
tags:
- gcc
- x86
- xds
script:
- source /opt/rh/gcc-toolset-12/enable
- mkdir -p build
- cd build
- cmake -DCMAKE_BUILD_TYPE=Release ..
- make -j8 jfjoch_hdf5_test
- cd ../tests/xds_durin
- HDF5MASTER_NEW_FORMAT=1 ../../build/tools/jfjoch_hdf5_test ../../tests/test_data/compression_benchmark.h5 25
- xds_par |grep -a1 ISa |tail -n1
test:x86:xds_neggia:
stage: test
timeout: 90m
variables:
CTEST_OUTPUT_ON_FAILURE: 1
CC: gcc
CXX: g++
needs: ["build:x86:gcc-12"]
dependencies: []
tags:
- gcc
- x86
- xds
script:
- source /opt/rh/gcc-toolset-12/enable
- mkdir -p build
- cd build
- cmake -DCMAKE_BUILD_TYPE=Release ..
- make -j8 jfjoch_hdf5_test
- cd ../tests/xds_neggia
- ../../build/tools/jfjoch_hdf5_test ../../tests/test_data/compression_benchmark.h5 25
- xds_par |grep -a1 ISa |tail -n1
test:x86:xia2.ssx:
stage: test
timeout: 90m
variables:
CTEST_OUTPUT_ON_FAILURE: 1
CC: gcc
CXX: g++
needs: ["build:x86:gcc-12"]
dependencies: []
tags:
- gcc
- x86
- xds
script:
- source /opt/rh/gcc-toolset-12/enable
- mkdir -p build
- mkdir -p dials_test
- cd build
- cmake -DCMAKE_BUILD_TYPE=Release ..
- make -j8 jfjoch_hdf5_test
- cd ../dials_test
- ../build/tools/jfjoch_hdf5_test ../tests/test_data/compression_benchmark.h5 100
- source /usr/local/dials-v3-17-0/dials_env.sh
- xia2.ssx image=writing_test_master.h5 space_group=P43212 unit_cell=78.551,78.551,36.914,90.000,90.000,90.000
synthesis:hls:
stage: synthesis
dependencies: []
variables:
CC: gcc
CXX: g++
rules:
- if: $CI_COMMIT_MESSAGE =~ /^FPGA/
- if: $CI_COMMIT_MESSAGE =~ /^HLS/
tags:
- vivado
script:
- source /opt/rh/gcc-toolset-12/enable
- source /opt/Xilinx/Vivado/2022.2/settings64.sh
- mkdir -p build
- cd build
- /usr/bin/cmake ..
- make hls
needs: ["build:x86:gcc-12", "test:x86:gcc"]
synthesis:100g:
stage: synthesis
dependencies: []
retry: 2
variables:
CC: gcc
CXX: g++
allow_failure: true
rules:
- if: $CI_COMMIT_MESSAGE =~ /^FPGA/
- if: $CI_COMMIT_MESSAGE =~ /^100G/
tags:
- vivado
artifacts:
paths:
- "jfjoch_fpga_pcie_100g.mcs"
expire_in: 1 week
script:
- source /opt/rh/gcc-toolset-12/enable
- source /opt/Xilinx/Vivado/2022.2/settings64.sh
- mkdir -p build
- cd build
- /usr/bin/cmake ..
- make -j4 pcie_100g
- mv fpga/jfjoch_fpga_pcie_100g.mcs ..
needs: ["build:x86:gcc-12", "test:x86:gcc"]
synthesis:8x10g:
stage: synthesis
dependencies: []
variables:
CC: gcc
CXX: g++
retry: 2
allow_failure: true
rules:
- if: $CI_COMMIT_MESSAGE =~ /^FPGA/
- if: $CI_COMMIT_MESSAGE =~ /^8x10G/
tags:
- vivado
artifacts:
paths:
- "jfjoch_fpga_pcie_8x10g.mcs"
expire_in: 1 week
script:
- source /opt/rh/gcc-toolset-12/enable
- source /opt/Xilinx/Vivado/2022.2/settings64.sh
- mkdir -p build
- cd build
- /usr/bin/cmake ..
- make -j4 pcie_8x10g
- mv fpga/jfjoch_fpga_pcie_8x10g.mcs ..
needs: [ "build:x86:gcc-12", "test:x86:gcc" ]
release:
stage: release
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
when: manual
tags:
- x86
- python
dependencies:
- build:x86:frontend
- build:x86:rpm
- build:x86:rpm_nocuda
- build:x86:sls9:rpm
- build:x86:python_client
script:
- bash gitlab_upload_release.sh
+254
View File
@@ -0,0 +1,254 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## What this is
Jungfraujoch is the data-acquisition and analysis system for the PSI JUNGFRAU and EIGER
X-ray detectors. It receives detector data, runs it through an FPGA-accelerated pipeline
(spot finding, azimuthal/ROI integration, compression), streams images out over ZeroMQ for
writing to HDF5, and runs crystallographic analysis (indexing, integration, scaling/merging).
Most authoritative documentation lives in `docs/` and on Read The Docs
(https://jungfraujoch.readthedocs.io). When changing CLI behaviour, the program's own
usage message is the source of truth, not the docs.
## Build
Out-of-source CMake build, C++20, heavy use of `FetchContent` (spdlog, zstd, HDF5,
slsDetectorPackage, Catch2, cpp-httplib, libzmq, Ceres, fast-feedback-indexer are downloaded
and statically linked — the **first configure needs network access** and is slow).
```
mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j$(nproc) jfjoch_broker # the main service; build other targets by name
```
Key CMake options:
- `JFJOCH_USE_CUDA` (default ON) — GPU path. Needs CUDA ≥ 12.8. Provides the `ffbidx` and `fft`
GPU indexers; without it only the CPU `fftw` indexer is available (requires FFTW at configure
time, auto-detected). CUDA absence is not a build error.
- `JFJOCH_WRITER_ONLY` (default OFF) — builds only the HDF5 writer; skips broker, FPGA,
receiver, analysis, tests, frontend.
- `JFJOCH_VIEWER_BUILD` (default OFF) — builds the Qt6 `jfjoch_viewer` desktop app.
- `SLS9` (default OFF) — build against slsDetectorPackage 9.2.0 instead of 8.0.2.
The frontend is a separate custom target: `make frontend` (runs `npm ci && npm run build` in
`frontend/`). It is not built by default unless installing.
## Test
Tests use **Catch2** and are collected into a single binary `tests/jfjoch_test`.
```
make -j$(nproc) jfjoch_test
cd tests
./jfjoch_test # all tests
./jfjoch_test "<test name>" # one test case (exact name in TEST_CASE)
./jfjoch_test "[tag]" # by tag
./jfjoch_test -r junit -o report.xml
```
`make jfjoch_hdf5_test` builds the HDF5 write-speed benchmark, also used by CI to produce files
that are validated against XDS (Durin/Neggia) and CrystFEL.
Lint config is `.clang-tidy` (broad `*` check set with many exceptions; namespaces lower_case,
classes CamelCase, global constants UPPER_CASE).
## Code style
The overriding principle is **simple, readable code** — favour the smallest, most direct
implementation that a reader can verify at a glance. Extra abstraction, speculative guards, and
clever-but-dense constructs are treated as actively harmful, not as polish. When torn between a
tidy abstraction and a flat, obvious version, pick the obvious one.
This matters most in `image_analysis/pixel_refinement/` (e.g. `PixelRefine.cpp`), which is an
experimental prototype where readability is how the physics gets verified — keep it especially
plain. **Do not add defensive/unrequested code** (extra validation, rejection heuristics, "just in
case" branches) without asking first; if a guard isn't clearly needed, leave it out.
Match the surrounding code's idiom, naming, and comment density rather than importing a different
style.
## No sample identities in the repository
**Never put sample names or sample-specific measured values into source code, comments,
documentation, commit messages, or test fixtures.** Datasets belong to users and may be
confidential or embargoed; anything committed can leak outside the group working on them. This is
a hard rule, not a preference.
- **Forbidden**: sample/dataset names or internal codes (a protein name, a beamline dataset ID, a
run label), and **measured unit-cell parameters tied to a real sample** (this is the most
sensitive — never hardcode "protein X has cell a,b,c").
- **Fine**: general crystallographic descriptors — space group / Laue class ("a P2₁ crystal", "a
holohedral 422 case"), lattice centering, twinning, "a crystal whose true axis is reported as its
3× harmonic", pseudo-symmetry, etc. Describe the *crystallographic situation*, not the specimen.
- **Exception — plain lysozyme.** Lysozyme (HEWL) is the field's universal standard test specimen,
not a user's confidential dataset, so naming it and using its well-known reference cell
(tetragonal ~79/79/38, P4₃2₁2) in tests, docs and comments is allowed. This carve-out is only for
generic lysozyme as a benchmark; a *named user dataset* that happens to be lysozyme is still off
limits, and every other real sample remains forbidden.
- **Tests** must otherwise use neutral names (e.g. `tetragonal_uc`, not a specimen-named variable)
and, where a cell is needed, a synthetic cell chosen for the test — not a real dataset's parameters.
When a bug was found on a specific dataset, commit the *behaviour* ("de-novo indexing adopted a
spurious axis-multiple supercell"), never the dataset.
## Local end-to-end run (no detector / no FPGA)
The FPGA HLS logic can be simulated on the CPU (`HLSSimulatedDevice`), so the full software
stack runs without hardware (slowly — fixed-point math on CPU). See
`docs/JFJOCH_BROKER.md` for the canonical walkthrough.
```
cd build/broker
./jfjoch_broker ../../etc/broker_local.json 5232 # config JSON + HTTP port
# then, separately:
cd tests/test_data && python jfjoch_broker_test.py # feeds a test image, starts collection
# observe at http://localhost:5232 ; HDF5 is written under build/broker
```
`etc/broker_local.json`, `broker_eiger.json`, `broker_crmx.json` are example broker configs
(schema = `jfjoch_settings` in `broker/jfjoch_api.yaml`).
## Architecture
**Data flow (online):** detector → FPGA acquisition (`fpga/`, `acquisition_device/`) →
`receiver/` builds full images from per-module FPGA output → `image_pusher/` streams CBOR-encoded
images over ZeroMQ → `jfjoch_writer` (`writer/`) consumes the stream and writes NXmx HDF5. The
broker also emits a low-rate preview stream and a metadata stream (`preview/`).
**Writer file split:** one acquisition produces one `_master.h5` plus many `_data_NNNNNN.h5`
files. Dataset-wide metadata (geometry, detector config, ROI/azimuthal definitions — anything
fixed for the whole run) is written to the **master** file in `writer/HDF5NXmx.cpp` (the `NXmx`
class). Per-image arrays (one entry per frame) are written to the **data** files by the
`HDF5DataFilePlugin` subclasses in `writer/`. Put shared metadata in `NXmx`, not in a data-file
plugin.
The HDF5 master/data layout is one of three `FileWriterFormat`s (`common/JFJochMessages.h`),
all NXmx: **`NXmxLegacy`** (master + `_data_NNNNNN.h5` joined by external links),
**`NXmxVDS`** (master + data joined by HDF5 virtual datasets — the default), and
**`NXmxIntegrated`** (a single self-contained file, no separate data files). Per-image plugins
must work for all three; with `NXmxIntegrated` "master" and "data" are the same file.
**Two acquisition workflows:** the FPGA-accelerated path (JUNGFRAU at PSI; FPGA does masking,
summation, spot finding, ROI/azimuthal integration, compression) and the DECTRIS SIMPLON path
(EIGER), which has no FPGA — masking/ROI/azimuthal analysis then runs on CPU through the shared
`image_analysis/` library. Treat ROI and azimuthal features as available in **both** workflows,
not FPGA-only.
**`jfjoch_broker`** (`broker/`) is the central online service: HTTP/REST + OpenAPI control plane,
FPGA configuration, image building, ZeroMQ output. `JFJochStateMachine` drives acquisition state;
`JFJochServices` wires the pieces; `OpenAPIConvert`/`JFJochBrokerParser` translate between the
generated API model and internal types.
**Three analysis frontends share one analysis library** (`image_analysis/`, built as
`JFJochImageAnalysis`):
- `jfjoch_broker` — online, real-time (FPGA + GPU).
- `jfjoch_viewer` — interactive Qt desktop (`viewer/`), results not persisted.
- `rugnux` (`tools/rugnux_cli.cpp`, built on the `Rugnux` library in `rugnux/`) — offline batch over
a stored HDF5; writes `_process.h5` and `.mtz`/`.cif`/`.hkl`. Merging is on by default (`--no-merge`
to disable); `--azint-only` runs only azimuthal integration and `--scale` re-scales/merges the
already-integrated reflections in a `_process.h5`. (rugnux = the data-processing half of the system;
see `docs/NAMING.md`.)
**`image_analysis/` pipeline** (subdirs): `spot_finding`, `indexing` (`ffbidx`/`fft` GPU,
`fftw` CPU), `lattice_search`, `geom_refinement`, `pixel_refinement`, `bragg_prediction`,
`bragg_integration`, `rotation_indexer`, `azint`, `roi`, `scale_merge`. Least-squares refinement
uses **Ceres** (fetched, built with miniglog, no MKL, CXX_THREADS). `ffbidx` needs a known cell
(`-C`) and suits sparse serial stills; `fft`/`fftw` index de novo and suit strong rotation data.
**FPGA** (`fpga/`): `hls/` is the Vitis HLS source (image-analysis kernels), `hls_simulation/`
runs that same HLS on CPU for hardware-free testing, `host_library/` is the host-side driver,
`pcie_driver/` is the kernel module. The HLS algorithms are documented in
`docs/FPGA_DATA_ANALYSIS.md`.
**Detector control** (`detector_control/`): wrappers for SLS (JUNGFRAU) and DECTRIS SIMPLON
(EIGER). **`jungfrau/`**: JUNGFRAU ADU→energy gain/pedestal calibration.
**Other libs:** `common/` (geometry, diffraction experiment, image buffer, CUDA wrappers — the
shared core, linked nearly everywhere), `compression/` (zstd + bitshuffle + sqrt lossy),
`frame_serialize/` (CBOR stream codec), `gemmi_gph/` (vendored GEMMI for MTZ/XDS_ASCII I/O),
`xds-plugin/` (XDS HDF5 read plugin).
## Portability (jfjoch_viewer)
Cross-platform support is a goal **only for `jfjoch_viewer` and its dependency tree** — keep that
code, and any shared library it transitively links (`common/`, `image_analysis/`, `reader/`,
`gemmi_gph/`, etc.), **MSVC-compatible** so the viewer can build on Windows. The rest of the
project (broker, receiver, FPGA host, detector control, …) is Linux-only and does not need to be
portable; don't constrain it for portability's sake.
- **Windows/MSVC** is the primary portability target. The end goal is a Windows viewer built
with **MSVC *and* CUDA** (`JFJOCH_USE_CUDA=ON`): GPU processing is a wanted feature, not
optional, so the intended Windows config is the full GPU path (`ffbidx`, GPU `fft`), not a
CPU-only fallback. MSVC is required regardless, because CUDA on Windows requires it. Avoid
GCC/Clang-only extensions, POSIX-only APIs, and other non-MSVC constructs in viewer-reachable
code, and keep CUDA-reachable viewer code (`ffbidx`, GPU indexers) MSVC-buildable too.
- **macOS** is a nice-to-have for the viewer. It rules out CUDA, so anything the viewer depends on
must also have a working CPU-only / non-CUDA path (the `JFJOCH_USE_CUDA=OFF`, `fftw`-indexer
configuration). This non-CUDA path must keep working, but it is the macOS fallback — *not* the
intended Windows configuration.
A self-contained Windows build still needs a few dependencies that the Linux build picks up from
the system and that are **not** auto-provided via `FetchContent` (besides Qt, supplied
externally): **ZLIB** (pulled by hdf5/libtiff/gemmi/libzmq — a bundled zlib-ng in `ZLIB_COMPAT`
mode is the intended fix, presented as the `ZLIB::ZLIB` target so the scattered
`find_package(ZLIB)` calls resolve), **libjpeg-turbo** (used by `preview/`; upstream discourages
`add_subdirectory`, so bring it in via `ExternalProject`), and **Eigen** (header-only; needed by
Ceres, by the analysis libs directly, and by `ffbidx` under CUDA — fetch it and point Ceres'
internal `find_package(Eigen3)` at it). Wire each guarded so the Linux build, which finds these on
the system, stays unchanged.
## OpenAPI is the single source of truth
`broker/jfjoch_api.yaml` defines the entire REST API **and the shared data schemas**. From it,
`update_version.sh` regenerates three clients — **do not hand-edit generated code**:
- C++ server model → `broker/gen/` (cpp-pistache-server generator; compiled as `JFJochAPI`).
- Python client → `python-client/` (and `gen_python_client.sh`, published as PyPI `jfjoch-client`).
- TypeScript frontend client → `frontend/src/client/` (hey-api `openapi-ts`, `npm run openapi`).
When you change `jfjoch_api.yaml`, regenerate the relevant client(s); for a version bump run
`update_version.sh` (also rewrites `VERSION`, `frontend/src/version.ts`, and the Redoc html).
## Frontend
React 19 + TypeScript + MUI + Vite (`frontend/`). Data layer is generated from the OpenAPI spec
(`@hey-api/openapi-ts` → fetch client + TanStack Query hooks + zod schemas). Scripts:
`npm start` (dev server), `npm run build` (tsc + vite), `npm run openapi` (regen client),
`npm run redocly4broker` (regen `broker/redoc-static.html`).
## Adding a per-image scalar quantity
A per-image scalar (e.g. `ice_ring_score`, `bkg_estimate`, `mosaicity`) flows analysis → message → CBOR
→ HDF5 → scan-result/plot → API → viewer/frontend. To add one, mirror an existing float scalar
(`bkg_estimate` is a clean template) at every layer:
1. **Compute** where the azint profile is finalized: `image_analysis/MXAnalysisWithoutFPGA.cpp` (CPU),
`receiver/JFJochReceiverFPGA.cpp` (FPGA), and the offline azint worker in `rugnux/Rugnux.cpp`.
2. **Message** (`common/JFJochMessages.h`): `std::optional<float>` in `DataMessage`, `std::vector<float>`
in `EndMessage`.
3. **CBOR**: encode in `frame_serialize/CBORStream2Serializer.cpp` (DataMessage block *and* END block),
decode in `CBORStream2Deserializer.cpp` (both). Optional fields are back-compatible — no version bump.
4. **HDF5** write: `writer/HDF5DataFilePluginMX.{h,cpp}` — an `AutoIncrVector<float>` with reserve /
per-image write / `SaveVector("/entry/MX/<name>")` (per-image arrays live in the data-file plugin);
plus the NXmx master write in `writer/HDF5NXmx.cpp` (`SaveVectorIfMissing(..., end.<name>)`). HDF5
**read-back** (so a stored file re-opens, e.g. in the viewer) is in `reader/HDF5MetadataSource.cpp`,
NOT `JFJochHDF5Reader.cpp`: mirror the three `bkgEstimate` sites — master `ReadOptVector`, data-file
`ReadVector` into the dataset, and the per-image message population.
5. **Scan result**: `common/ScanResult.h` (`ScanResultElem`) + `common/ScanResultGenerator.cpp`
(copy in `Add`, resize+fill in `FillEndMessage`).
6. **Receiver plot**: `common/Plot.h` (`PlotType`) + `common/JFJochReceiverPlots.{h,cpp}` (`StatusVector`
+ Clear / AddElement / GetPlots / GetPlotRaw cases).
7. **API**: add to the `plot_type` enum and the `scan_result` images schema in `broker/jfjoch_api.yaml`,
regenerate the C++ model (`java -jar openapi-generator-cli.jar generate -i broker/jfjoch_api.yaml -o
broker/gen -g cpp-pistache-server`) and the frontend client (`cd frontend && npm run openapi`), then
wire `broker/OpenAPIConvert.cpp` (`ConvertPlotType` string→enum and the `Convert(ScanResult)` setter).
8. **Reader/viewer**: `reader/JFJochReaderDataset.h` + `reader/JFJochHttpReader.cpp` (`GetPlot_i`) and
`viewer/JFJochViewerDatasetInfo.cpp` (combo item + `ExtractMetric`).
9. **Frontend**: `frontend/src/components/DataProcessingPlots.tsx` (`MenuItem`) + `DataProcessingPlot.tsx`
(y-axis label).
10. **Docs**: `docs/CBOR.md`, `docs/HDF5.md`, `docs/CPU_DATA_ANALYSIS.md`.
Gotcha: an existing `build/` dir needs a `cmake .` reconfigure to pick up a newly-added `broker/gen`
source file (the source list is a configure-time glob).
+321 -61
View File
@@ -8,16 +8,24 @@ SET(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
SET(CMAKE_CXX_STANDARD 20)
SET(CMAKE_CXX_STANDARD_REQUIRED True)
SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -Wno-deprecated-enum-enum-conversion")
SET(CMAKE_C_FLAGS_RELEASE "-O3")
SET(JFJOCH_WRITER_ONLY OFF CACHE BOOL "Compile HDF5 writer only")
SET(JFJOCH_INSTALL_DRIVER_SOURCE OFF CACHE BOOL "Install kernel driver source (ignored if building writer only; necessary for RPM building)")
SET(JFJOCH_USE_CUDA ON CACHE BOOL "Compile Jungfraujoch with CUDA")
SET(JFJOCH_VIEWER_BUILD OFF CACHE BOOL "Compile Jungfraujoch viewer")
# Only the viewer (and its portable dependency tree) is supported on Windows and macOS -- the
# broker/receiver/FPGA/writer server stack is Linux-only. Force viewer-only on those platforms so a
# plain configure builds the right subset; on Linux it remains a user-togglable option.
IF (WIN32 OR APPLE)
SET(JFJOCH_VIEWER_ONLY ON CACHE BOOL "Compile only jfjoch_viewer and its dependencies" FORCE)
ELSE()
SET(JFJOCH_VIEWER_ONLY OFF CACHE BOOL "Compile only jfjoch_viewer and its dependencies")
ENDIF()
SET (ZLIB_USE_STATIC_LIBS TRUE)
FIND_PACKAGE(ZLIB REQUIRED)
OPTION(SLS9 "Build with sls_detector_package v9.2.0" OFF)
SET(BUILD_SHARED_LIBS OFF)
@@ -37,42 +45,53 @@ SET(BUILD_FAST_INDEXER_STATIC ON)
INCLUDE(CheckLanguage)
INCLUDE(CheckIncludeFile)
# Locate nvcc ourselves when it isn't already pinned (-DCMAKE_CUDA_COMPILER / $CUDACXX). CHECK_LANGUAGE
# below only searches PATH, which is missed routinely on Windows and intermittently on Linux; the
# standard CUDA install locations (CUDA_PATH on Windows, /usr/local/cuda on Linux) cover both, so the
# compiler need not be passed by hand. Only set it when actually found, leaving CHECK_LANGUAGE to run
# its normal detection otherwise.
IF (JFJOCH_USE_CUDA AND NOT CMAKE_CUDA_COMPILER AND NOT DEFINED ENV{CUDACXX})
FIND_PROGRAM(_jfjoch_nvcc nvcc
HINTS ENV CUDA_PATH ENV CUDA_HOME ENV CUDA_ROOT /usr/local/cuda /opt/cuda
PATH_SUFFIXES bin)
IF (_jfjoch_nvcc)
SET(CMAKE_CUDA_COMPILER "${_jfjoch_nvcc}")
ENDIF()
ENDIF()
CHECK_LANGUAGE(CUDA)
SET(CMAKE_CUDA_ARCHITECTURES 75 80 86 89) # T4, A100, RTX A4000, L4
SET(CMAKE_CUDA_STANDARD 17)
SET(CMAKE_CUDA_FLAGS_RELEASE "-O3")
SET(CMAKE_CUDA_ARCHITECTURES 75 80 86 89 90 100 120) # T4, A100, RTX A4000, L4
SET(CMAKE_CUDA_STANDARD 20)
SET(CMAKE_CUDA_STANDARD_REQUIRED True)
SET(CMAKE_CUDA_FLAGS_RELEASE "-O3 -lineinfo")
SET(CMAKE_CUDA_RUNTIME_LIBRARY Static)
SET(JFJOCH_CUDA_AVAILABLE OFF)
IF (CMAKE_CUDA_COMPILER)
IF (JFJOCH_USE_CUDA)
ENABLE_LANGUAGE(CUDA)
FIND_PACKAGE(CUDAToolkit REQUIRED)
SET(CMAKE_CUDA_RUNTIME_LIBRARY Static)
MESSAGE(STATUS "CUDA VERSION: ${CMAKE_CUDA_COMPILER_VERSION}")
ADD_COMPILE_DEFINITIONS(JFJOCH_USE_CUDA)
FIND_LIBRARY(CUDART_LIBRARY cudart_static PATHS ${CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES} REQUIRED)
SET(JFJOCH_CUDA_AVAILABLE ON)
IF (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "12.8")
FIND_PACKAGE(CUDAToolkit REQUIRED)
ADD_COMPILE_DEFINITIONS(JFJOCH_USE_CUDA)
SET(JFJOCH_CUDA_AVAILABLE ON)
# Blackwell GB10 (DGX Spark) is sm_121, only known to nvcc >= 12.9; add it there so the
# binary launches natively on Spark (the list above tops out at sm_120 and embeds no PTX).
IF (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "12.9")
LIST(APPEND CMAKE_CUDA_ARCHITECTURES 121)
ENDIF()
ELSE()
MESSAGE(WARNING "CUDA older than 12.8 not supported")
ENDIF()
ELSE()
MESSAGE(WARNING "CUDA Available, but disabled by user")
ENDIF()
ENDIF()
FIND_LIBRARY(FFTWF_LIBRARY NAMES libfftw3f.a libfftw3f.so fftw3f DOC "FFTW single-precision library"
PATHS /usr/lib /usr/lib64 /usr/lib/x86_64-linux-gnu/)
CHECK_INCLUDE_FILE(fftw3.h HAS_FFTW3_H)
IF(HAS_FFTW3_H AND FFTWF_LIBRARY)
ADD_COMPILE_DEFINITIONS(JFJOCH_USE_FFTW)
ENDIF()
INCLUDE_DIRECTORIES(include)
INCLUDE(CheckIncludeFile)
FIND_LIBRARY(NUMA_LIBRARY NAMES numa DOC "NUMA Library")
CHECK_INCLUDE_FILE(numaif.h HAS_NUMAIF)
CHECK_INCLUDE_FILE(numa.h HAS_NUMA_H)
include(FetchContent)
@@ -138,43 +157,210 @@ FetchContent_Declare(
GIT_TAG v0.39.0
EXCLUDE_FROM_ALL
)
# httplib enables Brotli content-encoding whenever it finds system Brotli; we don't use it
# (gzip/zlib is enough for the broker), so disable it to avoid linking libbrotli.
SET(HTTPLIB_USE_BROTLI_IF_AVAILABLE OFF CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(zstd sls_detector_package catch2 hdf5 spdlog httplib)
# httplib auto-enables HTTPS by linking system OpenSSL whenever it finds it. The broker serves
# plain HTTP only (TLS, if ever wanted, is terminated by a front reverse proxy), so disable it --
# otherwise jfjoch_broker would pull in libssl/libcrypto for no reason.
SET(HTTPLIB_USE_OPENSSL_IF_AVAILABLE OFF CACHE BOOL "" FORCE)
ADD_SUBDIRECTORY(jungfrau)
ADD_SUBDIRECTORY(compression)
ADD_SUBDIRECTORY(common)
ADD_SUBDIRECTORY(writer)
ADD_SUBDIRECTORY(frame_serialize)
ADD_SUBDIRECTORY(reader)
ADD_SUBDIRECTORY(detector_control)
ADD_SUBDIRECTORY(image_puller)
ADD_SUBDIRECTORY(preview)
ADD_SUBDIRECTORY(symmetry)
ADD_SUBDIRECTORY(xds-plugin)
# ZeroMQ (libzmq): fetch it here, at the top level, so that THIS project - not
# slsDetectorPackage - controls the version. slsDetectorPackage bundles its own libzmq
# archive, but only populates it behind `if(NOT libzmq_POPULATED)`; by making libzmq
# available before sls below, sls reuses this copy and a single libzmq-static target is
# built (no duplicate target / double-symbol clash). A future viewer-only / Windows build
# (which does not build sls) fetches the same libzmq standalone.
SET(BUILD_SHARED OFF CACHE BOOL "" FORCE) # libzmq: static only (matches sls)
SET(BUILD_TESTS OFF CACHE BOOL "" FORCE) # libzmq: no test build
SET(WITH_PERF_TOOL OFF CACHE BOOL "" FORCE) # libzmq: no perf tools
SET(WITH_DOCS OFF CACHE BOOL "" FORCE) # libzmq: no docs
SET(ENABLE_CPACK OFF CACHE BOOL "" FORCE) # libzmq: no CPack injection
FetchContent_Declare(
libzmq
GIT_REPOSITORY https://github.com/zeromq/libzmq.git
GIT_TAG v4.3.5
EXCLUDE_FROM_ALL
)
IF (JFJOCH_WRITER_ONLY)
MESSAGE(STATUS "Compiling HDF5 writer only")
# CMake >= 4.0 (e.g. the 4.x bundled with Visual Studio 2026) makes any
# cmake_minimum_required(VERSION < 3.5) a fatal error. Some fetched dependencies still
# declare such old floors (libzmq: 3.0.2), so raise the policy-version floor for the
# FetchContent subprojects. Ignored (harmless) on CMake < 3.30, which lacks this variable.
SET(CMAKE_POLICY_VERSION_MINIMUM 3.5)
# libzmq must be made available BEFORE sls_detector_package for the override above to take effect.
FetchContent_MakeAvailable(libzmq)
IF (JFJOCH_VIEWER_ONLY)
# A viewer-only build still needs zstd/hdf5/spdlog/httplib (JFJochReader uses httplib).
# Only sls_detector_package (detector) and catch2 (tests) are not built here -- and sls
# in particular does not configure under MSVC -- so skip just those two.
FetchContent_MakeAvailable(zstd hdf5 spdlog httplib)
ELSE()
ADD_SUBDIRECTORY(image_pusher)
ADD_SUBDIRECTORY(broker)
ADD_SUBDIRECTORY(fpga)
ADD_SUBDIRECTORY(acquisition_device)
ADD_SUBDIRECTORY(receiver)
FetchContent_MakeAvailable(zstd sls_detector_package catch2 hdf5 spdlog httplib)
ENDIF()
# libtiff (used by JFJochPreview in every build mode): build it ourselves. Its C++ binding
# (tiffxx) is packaged inconsistently across distros (missing on Rocky 9) and absent on
# Windows. Library only; the SET()s below are libtiff's own codec/tool switches.
# We only need DEFLATE (zlib) + the internal LZW codec, matching what Python tifffile writes
# by default. The remaining codecs default to ON whenever their library is found on the build
# host, so each must be explicitly turned OFF to keep the dependency set minimal -- otherwise
# webp pulls in libwebp + libsharpyuv and lerc pulls in libLerc.
SET(jbig OFF)
SET(zstd OFF)
SET(lzma OFF)
SET(jpeg OFF)
SET(old-jpeg OFF)
SET(webp OFF)
SET(lerc OFF)
SET(tiff-tools OFF)
SET(tiff-tests OFF)
FetchContent_Declare(tiff
GIT_REPOSITORY https://gitlab.com/libtiff/libtiff.git
GIT_TAG v4.7.1
EXCLUDE_FROM_ALL)
FetchContent_MakeAvailable(tiff)
# FFTW single precision (target fftw3f): the CPU fallback indexer, enables JFJOCH_USE_FFTW.
# Built from the release tarball -- the git repo ships no pre-generated codelets (needs the
# OCaml genfft).
SET(ENABLE_FLOAT ON CACHE BOOL "" FORCE)
SET(BUILD_TESTS OFF CACHE BOOL "" FORCE)
# SIMD codelets are runtime-dispatched (cpuid), so enabling AVX2 does NOT require an AVX2 CPU
# -- FFTW falls back at runtime. The codelet sets are arch-specific, so guard by processor:
# x86 gets SSE2/AVX/AVX2, aarch64 (e.g. Grace on DGX Spark) gets NEON; other arches build scalar.
IF (CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64|amd64")
SET(ENABLE_SSE2 ON CACHE BOOL "" FORCE)
SET(ENABLE_AVX ON CACHE BOOL "" FORCE)
SET(ENABLE_AVX2 ON CACHE BOOL "" FORCE)
ELSEIF (CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|ARM64")
SET(ENABLE_NEON ON CACHE BOOL "" FORCE)
ENDIF()
FetchContent_Declare(fftw
URL https://www.fftw.org/fftw-3.3.10.tar.gz
URL_HASH SHA256=56c932549852cddcfafdab3820b0200c7742675be92179e59e6215b340e26467
EXCLUDE_FROM_ALL)
FetchContent_MakeAvailable(fftw)
# FFTW exposes fftw3.h only via $<INSTALL_INTERFACE:include>, so consuming fftw3f straight from
# the build tree (FetchContent) leaves the header unreachable. On Linux a system-installed
# fftw3.h masks this; on Windows it does not. Add the source-tree api/ dir for build-tree use.
TARGET_INCLUDE_DIRECTORIES(fftw3f INTERFACE $<BUILD_INTERFACE:${fftw_SOURCE_DIR}/api>)
ADD_COMPILE_DEFINITIONS(JFJOCH_USE_FFTW)
# Eigen is an EXTERNAL dependency (like ZLIB), resolved by find_package(Eigen3) in the subdirectories
# that need it (image_analysis, and transitively Ceres and ffbidx). It is deliberately NOT vendored
# via FetchContent: declaring Eigen with OVERRIDE_FIND_PACKAGE makes the CMake bundled with Visual
# Studio (cmake 4.x "-msvc") intermittently SEGFAULT during configure. The fault is in CMake's own
# FetchContent variable-stack cleanup, reached when Ceres' find_package(Eigen3) resolves the override
# through a nested FetchContent_MakeAvailable -- ~1 in 3 fresh configures, and 100% with Ceres CUDA on.
# Stock Kitware CMake runs the identical scripts fine, so it is a bug in the VS-bundled cmake binary;
# providing Eigen externally avoids that code path entirely and is stable (verified, both Ceres CUDA
# on and off). Provide it via the system package on Linux (eigen3-devel / libeigen3-dev) or a build
# prefix on Windows (point CMAKE_PREFIX_PATH / Eigen3_DIR at it), exactly as for ZLIB.
# getopt/getopt_long shim for Windows: the MSVC CRT has no <getopt.h>. Vendored OpenBSD/NetBSD
# implementation (BSD-licensed). Built only on Windows and defined here, before the subdirectories,
# so the portable CLI tools in tools/ can link it. A no-op on Linux/macOS, where getopt lives in
# libc (macOS uses the system getopt even though it is also a forced viewer-only platform).
IF (WIN32)
ADD_LIBRARY(wingetopt STATIC tools/wingetopt/getopt.c tools/wingetopt/getopt.h)
TARGET_INCLUDE_DIRECTORIES(wingetopt PUBLIC tools/wingetopt)
ENDIF()
# libcurl: the jfjoch_viewer HTTP client (viewer/JFJochHttpReader). Fetched and STATICALLY linked
# ONLY for viewer builds, so the broker/writer never pull in a TLS/Kerberos stack. Backends are
# OS-native per platform to keep the Windows build self-contained: Schannel (TLS) + SSPI
# (Negotiate/Kerberos) on Windows -- no external OpenSSL/krb5 -- and system OpenSSL + GSSAPI (krb5)
# on Linux. Trimmed to HTTP(S) only, mirroring the libtiff codec pruning above.
IF (JFJOCH_VIEWER_BUILD OR JFJOCH_VIEWER_ONLY)
SET(BUILD_CURL_EXE OFF CACHE BOOL "" FORCE)
SET(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE) # static libcurl only, never a shared lib
SET(BUILD_STATIC_LIBS ON CACHE BOOL "" FORCE)
SET(BUILD_TESTING OFF CACHE BOOL "" FORCE)
SET(CURL_DISABLE_INSTALL ON CACHE BOOL "" FORCE)
SET(HTTP_ONLY ON CACHE BOOL "" FORCE) # HTTP/HTTPS only; drop FTP/LDAP/SMTP/...
SET(CURL_USE_LIBPSL OFF CACHE BOOL "" FORCE) # avoid the libpsl dependency
SET(CURL_USE_LIBSSH2 OFF CACHE BOOL "" FORCE)
SET(CURL_ZLIB ON CACHE BOOL "" FORCE) # reuse the project's ZLIB
IF (WIN32)
SET(CURL_USE_SCHANNEL ON CACHE BOOL "" FORCE) # native Windows TLS (no OpenSSL)
SET(CURL_USE_SSPI ON CACHE BOOL "" FORCE) # native Negotiate/Kerberos (no krb5)
ELSE()
SET(CURL_USE_OPENSSL ON CACHE BOOL "" FORCE)
SET(CURL_USE_GSSAPI ON CACHE BOOL "" FORCE) # Kerberos via system krb5 (needs krb5-dev)
ENDIF()
FetchContent_Declare(curl
GIT_REPOSITORY https://github.com/curl/curl.git
GIT_TAG curl-8_11_1
EXCLUDE_FROM_ALL)
FetchContent_MakeAvailable(curl)
# The viewer links libcurl_static (curl's concrete static-lib target) directly rather than the
# CURL::libcurl alias: the alias can be shadowed by a system libcurl (find_package / dependency
# provider / a distro CURL config), silently linking the OS curl with the wrong TLS/Kerberos
# backend. libcurl_static is unambiguous; guard that FetchContent actually produced it.
IF (NOT TARGET libcurl_static)
MESSAGE(FATAL_ERROR "libcurl_static missing after FetchContent_MakeAvailable(curl) -- "
"the vendored static libcurl was not built.")
ENDIF()
ENDIF()
IF (JFJOCH_VIEWER_ONLY)
# Minimal subtree: jfjoch_viewer and only the libraries it transitively links.
# (broker here provides JFJochAPI only; its service targets are gated out.)
ADD_SUBDIRECTORY(jungfrau)
ADD_SUBDIRECTORY(compression)
ADD_SUBDIRECTORY(common)
ADD_SUBDIRECTORY(gemmi_gph)
ADD_SUBDIRECTORY(frame_serialize)
ADD_SUBDIRECTORY(preview)
ADD_SUBDIRECTORY(writer)
ADD_SUBDIRECTORY(image_analysis)
ADD_SUBDIRECTORY(tests)
ADD_SUBDIRECTORY(tools)
ENDIF()
IF (JFJOCH_VIEWER_BUILD)
ADD_SUBDIRECTORY(broker)
ADD_SUBDIRECTORY(reader)
ADD_SUBDIRECTORY(rugnux)
ADD_SUBDIRECTORY(viewer)
ADD_SUBDIRECTORY(tools) # builds only the portable analysis tools (rugnux/extract_hkl)
ELSE()
ADD_SUBDIRECTORY(jungfrau)
ADD_SUBDIRECTORY(compression)
ADD_SUBDIRECTORY(common)
ADD_SUBDIRECTORY(writer)
ADD_SUBDIRECTORY(frame_serialize)
ADD_SUBDIRECTORY(reader)
ADD_SUBDIRECTORY(detector_control)
ADD_SUBDIRECTORY(image_puller)
ADD_SUBDIRECTORY(preview)
ADD_SUBDIRECTORY(gemmi_gph)
ADD_SUBDIRECTORY(xds-plugin)
IF (JFJOCH_WRITER_ONLY)
MESSAGE(STATUS "Compiling HDF5 writer only")
ELSE()
ADD_SUBDIRECTORY(image_pusher)
ADD_SUBDIRECTORY(broker)
ADD_SUBDIRECTORY(fpga)
ADD_SUBDIRECTORY(acquisition_device)
ADD_SUBDIRECTORY(receiver)
ADD_SUBDIRECTORY(image_analysis)
ADD_SUBDIRECTORY(rugnux)
ADD_SUBDIRECTORY(tests)
ADD_SUBDIRECTORY(tools)
ENDIF()
IF (JFJOCH_VIEWER_BUILD)
ADD_SUBDIRECTORY(viewer)
ENDIF()
ENDIF()
IF (NOT JFJOCH_WRITER_ONLY)
IF (NOT JFJOCH_WRITER_ONLY AND NOT JFJOCH_VIEWER_ONLY)
ADD_CUSTOM_COMMAND(OUTPUT frontend/dist/index.html
COMMAND npm ci
COMMAND npm run build
COMMAND npm run licenses # write dist/THIRD_PARTY_LICENSES.txt (npm deps attribution)
COMMAND npm run redocly
COMMAND npm run docs # bundle Sphinx docs into dist/docs (served at /frontend/docs)
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/frontend)
ADD_CUSTOM_TARGET(frontend DEPENDS frontend/dist/index.html)
@@ -202,20 +388,19 @@ IF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
ENDIF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
# Set Package Name
# Initialize CPACK_COMPONENTS_ALL with common components
set(CPACK_COMPONENTS_ALL jfjoch writer)
SET(CPACK_PACKAGE_NAME "jfjoch")
# Add optional components
if (JFJOCH_INSTALL_DRIVER_SOURCE)
list(APPEND CPACK_COMPONENTS_ALL driver-dkms)
# Select the components to package based on build mode
if (JFJOCH_VIEWER_ONLY)
set(CPACK_COMPONENTS_ALL viewer)
else()
set(CPACK_COMPONENTS_ALL jfjoch writer)
endif()
if (JFJOCH_VIEWER_BUILD)
list(APPEND CPACK_COMPONENTS_ALL viewer)
if (JFJOCH_INSTALL_DRIVER_SOURCE)
list(APPEND CPACK_COMPONENTS_ALL driver-dkms)
endif()
if (JFJOCH_VIEWER_BUILD)
list(APPEND CPACK_COMPONENTS_ALL viewer)
endif()
endif()
# Common metadata
@@ -223,8 +408,69 @@ set(CPACK_PACKAGE_CONTACT "Filip Leonarski <filip.leonarski@psi.ch>")
set(CPACK_PACKAGE_VENDOR "Paul Scherrer Institut")
set(CPACK_PACKAGE_VERSION ${JFJOCH_VERSION})
# OS-aware packaging: DEB on Debian/Ubuntu, RPM on RHEL/Rocky
if (EXISTS "/etc/debian_version")
# OS-aware packaging: DragNDrop (.dmg) on macOS, NSIS installer on Windows, DEB on Debian/Ubuntu,
# RPM on RHEL/Rocky. macOS/Windows are checked first because the /etc/* probes below are Linux-only.
if (APPLE)
# .dmg containing jfjoch_viewer.app (Qt runtime already deployed into the bundle).
set(CPACK_GENERATOR "DragNDrop")
elseif (WIN32)
# NSIS installer .exe (Qt runtime deployed next to the binary by windeployqt).
set(CPACK_GENERATOR "NSIS")
# GPLv3 text shown as the click-through license page of the installer.
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
# Branding is split across three CPack knobs so the CUDA/CPU variant surfaces exactly where we
# want it and nowhere else:
# - Install folder + Start Menu group come from CPACK_PACKAGE_INSTALL_DIRECTORY and
# CPACK_NSIS_PACKAGE_NAME (the latter feeds $(^Name), the Start Menu group's default folder).
# Both stay plain "Jungfraujoch", so the Start Menu group carries no variant tag and the two
# builds install to the same place (CUDA is a strict superset -- they replace, not coexist).
# - CPACK_NSIS_DISPLAY_NAME is the Add/Remove Programs entry -- tagged "(CUDA)"/"(CPU)".
# - CPACK_PACKAGE_FILE_NAME is the installer .exe filename -- tagged "-cuda<major>"/"-cpu", so
# the (much larger) CUDA download is self-identifying, with the CUDA major version baked in.
# The tag follows JFJOCH_CUDA_AVAILABLE automatically; CUDAToolkit_VERSION_MAJOR is set whenever
# it is ON (find_package(CUDAToolkit) ran in the same guard above).
set(CPACK_PACKAGE_INSTALL_DIRECTORY "Jungfraujoch")
set(CPACK_NSIS_PACKAGE_NAME "Jungfraujoch")
if (JFJOCH_CUDA_AVAILABLE)
set(CPACK_NSIS_DISPLAY_NAME "Jungfraujoch (CUDA)")
set(CPACK_PACKAGE_FILE_NAME "jfjoch-viewer-${JFJOCH_VERSION}-win64-cuda${CUDAToolkit_VERSION_MAJOR}")
else()
set(CPACK_NSIS_DISPLAY_NAME "Jungfraujoch (CPU)")
set(CPACK_PACKAGE_FILE_NAME "jfjoch-viewer-${JFJOCH_VERSION}-win64-cpu")
endif()
# Start Menu shortcut for the viewer ("<exe basename>;<label>"). The shortcut and the
# Add/Remove Programs entry both use the .exe's embedded icon.
set(CPACK_PACKAGE_EXECUTABLES "jfjoch_viewer;Jungfraujoch Viewer")
# Forward slash on purpose: CPack writes this value verbatim into CPackConfig.cmake, and a
# backslash there ("bin\jfjoch...") is an invalid escape that cmake 4.x (CMP0010 strict, e.g. the
# VS-bundled cmake) rejects when cpack re-parses it. Windows accepts the forward slash at runtime.
set(CPACK_NSIS_INSTALLED_ICON_NAME "bin/jfjoch_viewer.exe")
elseif (JFJOCH_VIEWER_ONLY)
# Linux portable viewer: a single self-contained .tar.gz of jfjoch_viewer (Qt is linked
# statically here, so there is nothing external to ship alongside the binary). Built on the
# oldest supported distro (RHEL 8) for a low glibc floor, so the archive runs on any newer
# Linux -- unlike the per-distro .rpm/.deb this is meant to replace in the release. Named to
# mirror the Windows/macOS artifacts, with the same -cuda<major>/-cpu tag so the (larger) GPU
# build is self-identifying. CI renames the .tar.gz to .tgz before upload.
set(CPACK_GENERATOR "TGZ")
# Package only the components in CPACK_COMPONENTS_ALL (here: viewer). Without this the archive
# generator falls back to a monolithic install and walks every install() rule in the tree --
# including the fetched HDF5 command-line tools, abseil's EXCLUDE_FROM_ALL sub-libraries and the
# non-viewer components -- none of which the viewer-only build produces, so cpack aborts with
# "cannot find <artifact>". ALL_COMPONENTS_IN_ONE keeps the output a single tarball named
# CPACK_PACKAGE_FILE_NAME (no per-component suffix), matching the CI upload glob. This mirrors
# CPACK_DEB_COMPONENT_INSTALL / CPACK_RPM_COMPONENT_INSTALL in the DEB/RPM branches below.
set(CPACK_ARCHIVE_COMPONENT_INSTALL ON)
set(CPACK_COMPONENTS_GROUPING ALL_COMPONENTS_IN_ONE)
if (JFJOCH_CUDA_AVAILABLE)
set(CPACK_PACKAGE_FILE_NAME "jfjoch_viewer-${JFJOCH_VERSION}-linux-cuda${CUDAToolkit_VERSION_MAJOR}")
else()
set(CPACK_PACKAGE_FILE_NAME "jfjoch_viewer-${JFJOCH_VERSION}-linux-cpu")
endif()
elseif (EXISTS "/etc/debian_version")
set(CPACK_PACKAGE_LICENSE "GPL-3.0-only")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE")
@@ -290,4 +536,18 @@ else()
endif()
# Ship the license notices (top-level LICENSE, the third-party manifest, and the verbatim
# license texts) with every package variant, under share/doc/jfjoch. Installed per component so
# the file lands in whichever component package(s) the current build mode produces.
SET(JFJOCH_NOTICE_FILES
${CMAKE_SOURCE_DIR}/LICENSE
${CMAKE_SOURCE_DIR}/THIRD_PARTY_NOTICES.md)
FOREACH(_component IN LISTS CPACK_COMPONENTS_ALL)
INSTALL(FILES ${JFJOCH_NOTICE_FILES}
DESTINATION share/doc/jfjoch COMPONENT ${_component})
INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/licenses/
DESTINATION share/doc/jfjoch/licenses COMPONENT ${_component}
PATTERN "COLLECT.sh" EXCLUDE)
ENDFOREACH()
INCLUDE(CPack)
+4 -1
View File
@@ -679,7 +679,10 @@ Public License instead of this License. But first, please read
================
As a special exception, we specifically permit linking Jungfraujoch code with Nvidia CUDA libraries.
As a special exception, we specifically permit linking Jungfraujoch code with Nvidia CUDA libraries and Intel MKL.
We also permit to link Jungfraujoch software (GPLv3) with Jungfraujoch high-level synthesis code (CERN OHL 2.0) for the purpose
of simulating FPGA design on CPU.
If OpenAPI definition file (jfjoch_api.yaml) is solely used to generate client code or to interact with the Jungfraujoch
API it may be distributed under terms of your choosing without being subject to GPL requirements.
+86
View File
@@ -0,0 +1,86 @@
# Third-party software notices
Jungfraujoch is licensed under **GPL-3.0** (see [`LICENSE`](LICENSE)); the FPGA design is
licensed under **CERN-OHL-S-2.0** (see [`fpga/LICENSE`](fpga/LICENSE)). It builds on a number of
third-party components, acknowledged below as required by their licenses.
This file is the human-readable manifest. The verbatim license texts live in the
[`licenses/`](licenses/) directory (regenerate with `bash licenses/COLLECT.sh`). The frontend's
bundled JavaScript dependencies are listed separately in
`frontend/dist/THIRD_PARTY_LICENSES.txt`, generated at build time (`npm run licenses`).
All licenses below are GPL-3.0-compatible.
## Fetched at build time and statically linked into the C++ binaries
These are downloaded by CMake (`FetchContent` / `ExternalProject`) during the first configure and
linked into the Jungfraujoch executables.
| Component | Version | Copyright | License (SPDX) | License text |
|---|---|---|---|---|
| [spdlog](https://github.com/gabime/spdlog) | 1.17.0 | Gabi Melman | MIT | [spdlog.txt](licenses/spdlog.txt) |
| [Zstandard](https://github.com/facebook/zstd) | (pinned) | Meta Platforms, Inc. | BSD-3-Clause | [zstd.txt](licenses/zstd.txt) |
| [HDF5](https://github.com/HDFGroup/hdf5) | 2.1.0 | The HDF Group; UIUC | BSD-3-Clause-style | [hdf5.txt](licenses/hdf5.txt) |
| [slsDetectorPackage](https://github.com/slsdetectorgroup/slsDetectorPackage) | 8.0.2 / 9.2.0 | PSI | LGPL-3.0-or-later | [LGPL](licenses/slsDetectorPackage-LGPL-3.0.txt), [GPL](licenses/slsDetectorPackage-GPL-3.0.txt) |
| [cpp-httplib](https://github.com/yhirose/cpp-httplib) | 0.39.0 | Yuji Hirose | MIT | [cpp-httplib.txt](licenses/cpp-httplib.txt) |
| [libzmq (ZeroMQ)](https://github.com/zeromq/libzmq) | 4.3.5 | iMatix and contributors | MPL-2.0 | [libzmq.txt](licenses/libzmq.txt) |
| [libtiff](https://gitlab.com/libtiff/libtiff) | 4.7.1 | Sam Leffler; SGI | libtiff (BSD-like) | [libtiff.txt](licenses/libtiff.txt) |
| [FFTW](https://www.fftw.org/) | 3.3.10 | Matteo Frigo; MIT | GPL-2.0-or-later | [fftw.txt](licenses/fftw.txt) |
| [Ceres Solver](https://github.com/ceres-solver/ceres-solver) | (pinned) | Google Inc. and contributors | BSD-3-Clause | [ceres-solver.txt](licenses/ceres-solver.txt) |
| [fast-feedback-indexer](https://github.com/paulscherrerinstitute/fast-feedback-indexer) | (pinned) | PSI | BSD-3-Clause | [fast-feedback-indexer.txt](licenses/fast-feedback-indexer.txt) |
| [libjpeg-turbo](https://github.com/libjpeg-turbo/libjpeg-turbo) | (pinned) | D. R. Commander and others; IJG | IJG + BSD-3-Clause + Zlib | [libjpeg-turbo.txt](licenses/libjpeg-turbo.txt) |
| [Catch2](https://github.com/catchorg/Catch2) | 3.13.0 | Catch2 Authors | BSL-1.0 | [catch2.txt](licenses/catch2.txt) |
Catch2 is used only to build the test binary (`jfjoch_test`) and is not part of any shipped
artifact; it is listed here for completeness.
## Vendored directly in the repository
These are copied into the source tree (see the path) rather than fetched.
| Component | Path | Copyright | License (SPDX) | License text |
|---|---|---|---|---|
| [nlohmann/json](https://github.com/nlohmann/json) | `include/nlohmann/` | Niels Lohmann | MIT | [nlohmann-json.txt](licenses/nlohmann-json.txt) |
| [Macaron Base64](https://gist.github.com/tomykaira/f0fd86b6c73063283afe550bc5d77594) | `include/base64/` | tomykaira | MIT | [base64-macaron.txt](licenses/base64-macaron.txt) |
| [TinyCBOR](https://github.com/intel/tinycbor) | `frame_serialize/tinycbor/` | Intel Corporation | MIT | [tinycbor.txt](licenses/tinycbor.txt) |
| [Bitshuffle](https://github.com/kiyo-masui/bitshuffle) | `compression/bitshuffle/` | Kiyoshi Masui | MIT | [bitshuffle.txt](licenses/bitshuffle.txt) |
| [Bitshuffle (h-perf)](https://github.com/kalcutter/bitshuffle) | `compression/bitshuffle_hperf/` | Kal Cutter (DECTRIS) | Apache-2.0 | [bitshuffle-hperf.txt](licenses/bitshuffle-hperf.txt) |
| [LZ4](https://github.com/lz4/lz4) | `compression/lz4/` | Yann Collet | BSD-2-Clause | [lz4.txt](licenses/lz4.txt) |
| [HLS arbitrary-precision types](https://github.com/Xilinx/HLS_arbitrary_Precision_Types) | `fpga/include/` | Xilinx, Inc. | Apache-2.0 | [xilinx-hls-headers.txt](licenses/xilinx-hls-headers.txt) |
| [GEMMI](https://github.com/project-gemmi/gemmi) | `gemmi_gph/` | Global Phasing Ltd. | MPL-2.0 | [gemmi.txt](licenses/gemmi.txt) |
| [xbflash.qspi](https://github.com/Xilinx/XRT) | `tools/xbflash.qspi/` | Xilinx / AMD | Apache-2.0 | [xbflash-qspi.txt](licenses/xbflash-qspi.txt) |
| [wingetopt](https://github.com/alex85k/wingetopt) | `tools/wingetopt/` | Todd C. Miller; The NetBSD Foundation | ISC AND BSD-2-Clause | [wingetopt.txt](licenses/wingetopt.txt) |
## Runtime libraries and SDKs (shipped in binaries, not in the source tree)
| Component | Used by | License | Notice |
|---|---|---|---|
| [Qt 6](https://www.qt.io/) | `jfjoch_viewer` | LGPL-3.0 | [notice](licenses/Qt6-NOTICE.txt), [LGPL-3.0](licenses/Qt6-LGPL-3.0.txt) |
| [NVIDIA CUDA Toolkit](https://developer.nvidia.com/cuda-toolkit) (cudart, cuFFT) | CUDA builds | NVIDIA CUDA EULA | [notice](licenses/NVIDIA-CUDA-NOTICE.txt), [EULA](licenses/NVIDIA-CUDA-EULA.txt) |
| [zlib](https://zlib.net/) | everywhere (compression) | Zlib | [zlib.txt](licenses/zlib.txt) |
| [Eigen](https://gitlab.com/libeigen/eigen) | analysis libs, Ceres, ffbidx (header-only) | MPL-2.0 (+ BSD parts) | [eigen.txt](licenses/eigen.txt), [README](licenses/eigen-README.txt) |
## Frontend (npm) dependencies
The React/TypeScript frontend (`frontend/`) bundles a large transitive tree of npm packages,
overwhelmingly MIT/ISC/BSD/Apache-2.0 licensed. Their full notices are generated automatically:
```
cd frontend && npm run licenses # writes dist/THIRD_PARTY_LICENSES.txt
```
The generated file is produced as part of the `frontend` build target and installed alongside the
served frontend, so the shipped web UI carries its own attribution.
## Notes on weak-copyleft and attribution-sensitive components
* **MPL-2.0** (Eigen, GEMMI, libzmq): file-level copyleft. GEMMI is vendored in `gemmi_gph/` in
trimmed form; libzmq is fetched at build time; Eigen is provided externally (header-only). The
corresponding source is available from each project upstream.
* **FFTW** is GPL-2.0-or-later — compatible with, and absorbed by, this project's GPL-3.0 license.
* **Apache-2.0** components: where upstream ships a `NOTICE` file, it is reproduced in the
corresponding `licenses/` text.
* **Qt (LGPL-3.0)** and **NVIDIA CUDA (EULA)** carry redistribution conditions beyond a copyright
notice; see their dedicated notice files. The verbatim LGPL-3.0 and CUDA EULA texts are bundled
(`licenses/Qt6-LGPL-3.0.txt`, `licenses/NVIDIA-CUDA-EULA.txt`); the CUDA EULA is the one shipped
with CUDA Toolkit 12.8 — replace it if you build against a different toolkit version.
+1 -1
View File
@@ -1 +1 @@
1.0.0-rc.136
1.0.0-rc.160
+1 -5
View File
@@ -1,8 +1,7 @@
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#ifndef JUNGFRAUJOCH_ACQUISITIONCOUNTERS_H
#define JUNGFRAUJOCH_ACQUISITIONCOUNTERS_H
#pragma once
#include <condition_variable>
#include <shared_mutex>
@@ -67,6 +66,3 @@ public:
uint64_t GetModuleNumber() const;
};
#endif //JUNGFRAUJOCH_ACQUISITIONCOUNTERS_H
+15 -45
View File
@@ -1,11 +1,6 @@
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#ifdef JFJOCH_USE_NUMA
#include <numaif.h>
#endif
#include <sys/mman.h>
#include <thread>
#include <fstream>
#include <cmath>
@@ -14,24 +9,6 @@
#include "AcquisitionDevice.h"
#include "../common/NetworkAddressConvert.h"
void *mmap_acquisition_buffer(size_t size, int16_t numa_node) {
void *ret = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (ret == MAP_FAILED) {
throw JFJochException(JFJochExceptionCategory::MemAllocFailed, "frame_buffer");
}
#ifdef JFJOCH_USE_NUMA
if (numa_node >= 0) {
unsigned long nodemask = 1L << numa_node;;
if (numa_node > sizeof(nodemask)*8)
throw JFJochException(JFJochExceptionCategory::MemAllocFailed, "Mask too small for NUMA node");
if (mbind(ret, size, MPOL_BIND, &nodemask, sizeof(nodemask)*8, MPOL_MF_STRICT) == -1)
throw JFJochException(JFJochExceptionCategory::MemAllocFailed, "Cannot apply NUMA policy");
}
#endif
memset(ret, 0, size);
return ret;
}
AcquisitionDevice::AcquisitionDevice(uint16_t in_data_stream) {
logger = nullptr;
data_stream = in_data_stream;
@@ -200,27 +177,35 @@ void AcquisitionDevice::InitializeEmptyPixelMask(const DiffractionExperiment &ex
void AcquisitionDevice::InitializeDataProcessing(const DiffractionExperiment &experiment,
const AzimuthalIntegration &azint) {
const AzimuthalIntegrationMapping &azint) {
auto offset = experiment.GetFirstModuleOfDataStream(data_stream);
size_t modules = experiment.GetModulesNum(data_stream);
// When azimuthal integration is forced onto the CPU, the FPGA must not bin pixels
// (the integration map can address more bins than the FPGA supports); the CPU path
// computes the profile from the assembled image instead.
const bool load_integration_map = !experiment.GetAzimuthalIntegrationSettings().IsForceCPUinFPGAWorkflow();
if (experiment.IsGeometryTransformed()) {
std::vector<float> tmp1(RAW_MODULE_SIZE);
std::vector<uint16_t> tmp2(RAW_MODULE_SIZE);
for (int m = 0; m < modules; m++) {
ConvertedToRawGeometry(experiment, offset + m, tmp1.data(), azint.Corrections().data());
ConvertedToRawGeometry(experiment, offset + m, tmp2.data(), azint.GetPixelToBin().data());
InitializeIntegrationMap(tmp2.data(), tmp1.data(), m);
if (load_integration_map) {
ConvertedToRawGeometry(experiment, offset + m, tmp1.data(), azint.Corrections().data());
ConvertedToRawGeometry(experiment, offset + m, tmp2.data(), azint.GetPixelToBin().data());
InitializeIntegrationMap(tmp2.data(), tmp1.data(), m);
}
ConvertedToRawGeometry(experiment, offset + m, tmp1.data(), azint.Resolution().data());
InitializeSpotFinderResolutionMap(tmp1.data(), m);
}
} else {
for (int m = 0; m < modules; m++) {
InitializeIntegrationMap(azint.GetPixelToBin().data() + (offset + m) * RAW_MODULE_SIZE,
azint.Corrections().data() + (offset + m) * RAW_MODULE_SIZE,
m);
if (load_integration_map)
InitializeIntegrationMap(azint.GetPixelToBin().data() + (offset + m) * RAW_MODULE_SIZE,
azint.Corrections().data() + (offset + m) * RAW_MODULE_SIZE,
m);
InitializeSpotFinderResolutionMap(azint.Resolution().data() + (m + offset) * RAW_MODULE_SIZE,
m);
}
@@ -238,21 +223,6 @@ void AcquisitionDevice::InitializePixelMask(const DiffractionExperiment &experim
}
}
void AcquisitionDevice::MapBuffersStandard(size_t c2h_buffer_count, int16_t numa_node) {
try {
for (int i = 0; i < c2h_buffer_count; i++)
buffer_device.emplace_back((DeviceOutput *) mmap_acquisition_buffer(FPGA_BUFFER_LOCATION_SIZE, numa_node));
} catch (const JFJochException &e) {
UnmapBuffers();
throw;
}
}
void AcquisitionDevice::UnmapBuffers() {
for (auto &i: buffer_device)
if (i != nullptr) munmap(i, FPGA_BUFFER_LOCATION_SIZE);
}
void AcquisitionDevice::FrameBufferRelease(size_t frame_number, uint16_t module_number) {
auto handle = counters.GetBufferHandleAndClear(frame_number, module_number);
if (handle != AcquisitionCounters::HandleNotFound)
+7 -9
View File
@@ -1,8 +1,7 @@
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#ifndef JUNGFRAUJOCH_ACQUISITIONDEVICE_H
#define JUNGFRAUJOCH_ACQUISITIONDEVICE_H
#pragma once
#include <map>
#include <mutex>
@@ -21,7 +20,7 @@
#include "Completion.h"
#include "../fpga/pcie_driver/jfjoch_fpga.h"
#include "../common/NetworkAddressConvert.h"
#include "../common/AzimuthalIntegration.h"
#include "../common/AzimuthalIntegrationMapping.h"
struct AcquisitionDeviceStatistics {
uint64_t good_packets;
@@ -50,6 +49,9 @@ protected:
ThreadSafeFIFO<Completion> work_completion_queue;
ThreadSafeFIFO<WorkRequest> work_request_queue;
// Non-owning view of the per-buffer addresses. Each device subclass owns the backing memory
// and its lifecycle: PCIExpressDevice mmap's/munmap's kernel DMA buffers, HLSSimulatedDevice
// points these at plain heap buffers it owns.
std::vector<DeviceOutput *> buffer_device;
Logger *logger;
@@ -59,8 +61,6 @@ protected:
uint32_t ipv4_addr;
explicit AcquisitionDevice(uint16_t data_stream);
void UnmapBuffers();
void MapBuffersStandard(size_t c2h_buffer_count, int16_t numa_node);
const DeviceOutput *GetDeviceOutput(size_t handle) const;
DeviceOutput *GetDeviceOutput(size_t handle);
virtual void HW_RunInternalGenerator(const FrameGeneratorConfig& config) = 0;
@@ -71,7 +71,7 @@ public:
static constexpr const uint64_t HandleNotValid = UINT64_MAX;
virtual ~AcquisitionDevice() { UnmapBuffers(); };
virtual ~AcquisitionDevice() = default;
void StartAction(const DiffractionExperiment &experiment, uint32_t optional_flags = 0);
void PrepareAction(const DiffractionExperiment &experiment);
@@ -101,7 +101,7 @@ public:
void InitializePixelMask(const DiffractionExperiment &experiment, const PixelMask &mask_raw);
virtual void InitializePixelMask(const uint32_t *module_mask, size_t module_number);
void InitializeROIMap(const DiffractionExperiment& experiment, const std::vector<uint16_t>& raw_roi_map);
void InitializeDataProcessing(const DiffractionExperiment &experiment, const AzimuthalIntegration& azint);
void InitializeDataProcessing(const DiffractionExperiment &experiment, const AzimuthalIntegrationMapping& azint);
const AcquisitionCounters& Counters() const;
@@ -119,5 +119,3 @@ public:
void RunInternalGenerator(const DiffractionExperiment& experiment);
};
#endif //JUNGFRAUJOCH_ACQUISITIONDEVICE_H
+1 -4
View File
@@ -1,8 +1,7 @@
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#ifndef JUNGFRAUJOCH_ACQUISITIONDEVICEGROUP_H
#define JUNGFRAUJOCH_ACQUISITIONDEVICEGROUP_H
#pragma once
#include <vector>
#include "AcquisitionDevice.h"
@@ -20,5 +19,3 @@ public:
std::vector<DeviceStatus> GetDeviceStatus() const;
void EnableLogging(Logger *logger);
};
#endif //JUNGFRAUJOCH_ACQUISITIONDEVICEGROUP_H
+1 -4
View File
@@ -1,8 +1,7 @@
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#ifndef JUNGFRAUJOCH_COMPLETION_H
#define JUNGFRAUJOCH_COMPLETION_H
#pragma once
#include <cstdint>
@@ -21,5 +20,3 @@ struct Completion {
};
Completion parse_hw_completion(uint32_t hw_input);
#endif //JUNGFRAUJOCH_COMPLETION_H
+1 -4
View File
@@ -1,8 +1,7 @@
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#ifndef JUNGFRAUJOCH_FPGAACQUISITIONDEVICE_H
#define JUNGFRAUJOCH_FPGAACQUISITIONDEVICE_H
#pragma once
#include "AcquisitionDevice.h"
#include "../fpga/pcie_driver/jfjoch_fpga.h"
@@ -49,5 +48,3 @@ public:
void SetInternalGeneratorFrame(const uint16_t *input, size_t module_number) override;
uint32_t GetExpectedDescriptorsPerModule() const override;
};
#endif //JUNGFRAUJOCH_FPGAACQUISITIONDEVICE_H
+6 -2
View File
@@ -3,14 +3,18 @@
#include "HLSSimulatedDevice.h"
HLSSimulatedDevice::HLSSimulatedDevice(uint16_t data_stream, size_t in_frame_buffer_size_modules, int16_t numa_node)
HLSSimulatedDevice::HLSSimulatedDevice(uint16_t data_stream, size_t in_frame_buffer_size_modules)
: FPGAAcquisitionDevice(data_stream) {
mac_addr = 0xCCAA11223344;
ipv4_addr = 0x0132010A;
max_modules = MAX_MODULES_FPGA;
MapBuffersStandard(in_frame_buffer_size_modules, numa_node);
buffers.reserve(in_frame_buffer_size_modules);
for (size_t i = 0; i < in_frame_buffer_size_modules; i++) {
buffers.push_back(std::make_unique<FrameBuffer>()); // zero-initialised, 64-byte aligned
buffer_device.push_back(reinterpret_cast<DeviceOutput *>(buffers.back().get()));
}
device = std::make_unique<HLSDevice>(buffer_device);
}
+9 -6
View File
@@ -1,8 +1,7 @@
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#ifndef JUNGFRAUJOCH_HLSSIMULATEDDEVICE_H
#define JUNGFRAUJOCH_HLSSIMULATEDDEVICE_H
#pragma once
#include <thread>
@@ -12,6 +11,13 @@
#include "FPGAAcquisitionDevice.h"
class HLSSimulatedDevice : public FPGAAcquisitionDevice {
// Owns the simulated frame buffers. Plain heap (this path is not performance-critical, so no
// NUMA placement and no mmap), but page-aligned (4 KiB) to match the real device's kernel DMA
// buffers - more than enough for the data path's alignment needs (AXI datamover 64 B,
// FPGAIntegrationTest 128 B). Declared before `device` so the buffers outlive the HLSDevice
// action thread that writes into them; buffer_device points into these.
struct alignas(4096) FrameBuffer { uint8_t data[FPGA_BUFFER_LOCATION_SIZE]; };
std::vector<std::unique_ptr<FrameBuffer>> buffers;
std::unique_ptr<HLSDevice> device;
void HW_ReadActionRegister(DataCollectionConfig *job) override;
@@ -26,7 +32,7 @@ class HLSSimulatedDevice : public FPGAAcquisitionDevice {
void HW_SetSpotFinderParameters(const SpotFinderParameters &params) override;
void HW_RunInternalGenerator(const FrameGeneratorConfig &config) override;
public:
HLSSimulatedDevice(uint16_t data_stream, size_t in_frame_buffer_size_modules, int16_t numa_node = -1);
HLSSimulatedDevice(uint16_t data_stream, size_t in_frame_buffer_size_modules);
~HLSSimulatedDevice() override = default;
void CreateJFPacket(const DiffractionExperiment& experiment, uint64_t frame_number, uint32_t eth_packet,
uint32_t module_number, const uint16_t *data, int8_t adjust_axis = 0, uint8_t user = 0);
@@ -41,6 +47,3 @@ public:
void Cancel() override;
DeviceStatus GetDeviceStatus() const override;
};
#endif //JUNGFRAUJOCH_HLSSIMULATEDDEVICE_H
+9
View File
@@ -33,6 +33,15 @@ PCIExpressDevice::PCIExpressDevice(uint16_t data_stream, const std::string &devi
}
}
PCIExpressDevice::~PCIExpressDevice() {
UnmapBuffers();
}
void PCIExpressDevice::UnmapBuffers() {
for (auto &buf: buffer_device)
if (buf != nullptr) dev.UnmapKernelBuffer(buf);
}
bool PCIExpressDevice::HW_ReadMailbox(uint32_t *values) {
PCI_EXCEPT(return dev.ReadWorkCompletion(values);)
}
+3 -4
View File
@@ -1,8 +1,7 @@
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#ifndef JUNGFRAUJOCH_PCIEXPRESSDEVICE_H
#define JUNGFRAUJOCH_PCIEXPRESSDEVICE_H
#pragma once
#include "FPGAAcquisitionDevice.h"
#include "../fpga/host_library/JungfraujochDevice.h"
@@ -21,10 +20,12 @@ class PCIExpressDevice : public FPGAAcquisitionDevice {
void FPGA_EndAction() override;
uint32_t GetNumKernelBuffers() const;
void HW_RunInternalGenerator(const FrameGeneratorConfig &config) override;
void UnmapBuffers();
public:
explicit PCIExpressDevice(uint16_t data_stream);
PCIExpressDevice(uint16_t data_stream, uint16_t pci_slot);
PCIExpressDevice(uint16_t data_stream, const std::string &device_name);
~PCIExpressDevice() override;
void Cancel() override;
int32_t GetNUMANode() const override;
@@ -36,5 +37,3 @@ public:
DeviceStatus GetDeviceStatus() const override;
DataCollectionStatus GetDataCollectionStatus() const override;
};
#endif //JUNGFRAUJOCH_PCIEXPRESSDEVICE_H
+15 -11
View File
@@ -6,17 +6,21 @@ AUX_SOURCE_DIRECTORY(gen/model MODEL_SOURCES)
ADD_LIBRARY(JFJochAPI STATIC ${MODEL_SOURCES})
TARGET_INCLUDE_DIRECTORIES(JFJochAPI PUBLIC gen/model)
# Jungfraujoch Broker (abstract from HTTP service)
ADD_LIBRARY(JFJochBroker STATIC
JFJochStateMachine.cpp JFJochStateMachine.h
JFJochServices.cpp JFJochServices.h
JFJochBrokerParser.cpp JFJochBrokerParser.h
OpenAPIConvert.h OpenAPIConvert.cpp)
# The broker service pulls in the receiver/detector stack. A viewer-only build
# needs JFJochAPI (the shared OpenAPI model, above) but none of this machinery.
IF (NOT JFJOCH_VIEWER_ONLY)
# Jungfraujoch Broker (abstract from HTTP service)
ADD_LIBRARY(JFJochBroker STATIC
JFJochStateMachine.cpp JFJochStateMachine.h
JFJochServices.cpp JFJochServices.h
JFJochBrokerParser.cpp JFJochBrokerParser.h
OpenAPIConvert.h OpenAPIConvert.cpp)
TARGET_LINK_LIBRARIES(JFJochBroker JFJochReceiver JFJochDetector JFJochCommon JFJochAPI JFJochPreview)
TARGET_LINK_LIBRARIES(JFJochBroker JFJochReceiver JFJochDetector JFJochCommon JFJochAPI JFJochPreview)
ADD_EXECUTABLE(jfjoch_broker jfjoch_broker.cpp JFJochBrokerHttp.cpp JFJochBrokerHttp.h)
ADD_EXECUTABLE(jfjoch_broker jfjoch_broker.cpp JFJochBrokerHttp.cpp JFJochBrokerHttp.h)
TARGET_LINK_LIBRARIES(jfjoch_broker JFJochBroker httplib::httplib ${CMAKE_DL_LIBS})
TARGET_INCLUDE_DIRECTORIES(jfjoch_broker PUBLIC gen/api)
INSTALL(TARGETS jfjoch_broker RUNTIME COMPONENT jfjoch)
TARGET_LINK_LIBRARIES(jfjoch_broker JFJochBroker httplib::httplib ${CMAKE_DL_LIBS})
TARGET_INCLUDE_DIRECTORIES(jfjoch_broker PUBLIC gen/api)
INSTALL(TARGETS jfjoch_broker RUNTIME COMPONENT jfjoch)
ENDIF()
+75 -11
View File
@@ -138,10 +138,6 @@ std::pair<int, std::string> JFJochBrokerHttp::handleOperationException(const std
void JFJochBrokerHttp::attach(httplib::Server &server) {
register_routes(server);
server.set_error_handler([](const httplib::Request &, httplib::Response &res) {
res.status = 404;
res.set_content("The requested method does not exist", "text/plain");
});
}
void JFJochBrokerHttp::register_routes(httplib::Server &server) {
@@ -159,13 +155,23 @@ void JFJochBrokerHttp::register_routes(httplib::Server &server) {
auto bind_json = [this](auto method, auto model_tag) {
return [this, method](const httplib::Request &req, httplib::Response &res) {
using Model = decltype(model_tag);
Model v;
try {
Model v;
nlohmann::json::parse(req.body).get_to(v);
v.validate();
} catch (const std::exception &e) {
// Malformed or invalid request body.
auto [c, s] = handleParsingException(e);
send_plain(res, c, s);
return;
}
try {
(this->*method)(v, res);
} catch (const std::exception &e) {
auto [c, s] = handleParsingException(e);
// Operation failure (e.g. WrongDAQState, a failed synchronous start): return the
// structured Error_message JSON with a reason field, like the no-arg endpoints, so
// clients can distinguish the cause instead of receiving opaque plain text.
auto [c, s] = handleOperationException(e);
send_plain(res, c, s);
}
};
@@ -197,6 +203,8 @@ void JFJochBrokerHttp::register_routes(httplib::Server &server) {
server.Post("/config/image_format/raw", bind_noarg(&JFJochBrokerHttp::config_image_format_raw_post));
server.Get("/config/indexing", bind_noarg(&JFJochBrokerHttp::config_indexing_get));
server.Put("/config/indexing", bind_json(&JFJochBrokerHttp::config_indexing_put, Indexing_settings{}));
server.Get("/config/bragg_integration", bind_noarg(&JFJochBrokerHttp::config_bragg_integration_get));
server.Put("/config/bragg_integration", bind_json(&JFJochBrokerHttp::config_bragg_integration_put, Bragg_integration_settings{}));
server.Get("/config/instrument", bind_noarg(&JFJochBrokerHttp::config_instrument_get));
server.Put("/config/instrument", bind_json(&JFJochBrokerHttp::config_instrument_put, Instrument_metadata{}));
server.Put("/config/internal_generator_image", [this](const httplib::Request &req, httplib::Response &res) {
@@ -255,6 +263,7 @@ void JFJochBrokerHttp::register_routes(httplib::Server &server) {
parse_query_value<bool>(req, "show_user_mask"),
parse_query_value<bool>(req, "show_roi"),
parse_query_value<bool>(req, "show_spots"),
parse_query_value<bool>(req, "show_predictions"),
parse_query_value<bool>(req, "show_beam_center"),
parse_query_value<float>(req, "saturation"),
parse_query_value<int64_t>(req, "jpeg_quality"),
@@ -347,6 +356,15 @@ void JFJochBrokerHttp::register_routes(httplib::Server &server) {
}
});
server.Post("/wait_until_running", [this](const httplib::Request &req, httplib::Response &res) {
try {
wait_until_running_post(parse_query_value<int32_t>(req, "timeout"), res);
} catch (const std::exception &e) {
auto [c, s] = handleOperationException(e);
send_plain(res, c, s);
}
});
server.Get("/xfel/event_code", bind_noarg(&JFJochBrokerHttp::xfel_event_code_get));
server.Get("/xfel/pulse_id", bind_noarg(&JFJochBrokerHttp::xfel_pulse_id_get));
}
@@ -369,7 +387,7 @@ void JFJochBrokerHttp::initialize_post(httplib::Response &response) {
void JFJochBrokerHttp::start_post(const Dataset_settings &datasetSettings, httplib::Response &response) {
nlohmann::json j = datasetSettings;
logger.Info("Start {}", j.dump());
state_machine.Start(Convert(datasetSettings));
state_machine.Start(Convert(datasetSettings), datasetSettings.isAsyncStart());
response.status = 200;
}
@@ -377,6 +395,38 @@ void JFJochBrokerHttp::status_get(httplib::Response &response) {
ProcessOutput(Convert(state_machine.GetStatus()), response);
}
void JFJochBrokerHttp::wait_until_running_post(const std::optional<int32_t> &timeout, httplib::Response &response) {
BrokerStatus status;
if (!timeout)
status = state_machine.WaitTillNotBusy(std::chrono::minutes(1));
else if ((timeout.value() > 3600) || (timeout.value() < 0)) {
response.status = 400;
response.set_content("timeout must be in range 0..3600", "text/plain");
return;
} else if (timeout.value() == 0)
status = state_machine.GetStatus();
else
status = state_machine.WaitTillNotBusy(std::chrono::seconds(timeout.value()));
logger.Info("Wait until running");
switch (status.state) {
case JFJochState::Measuring:
response.status = 200;
break;
case JFJochState::Inactive:
response.status = 502;
break;
case JFJochState::Error:
throw WrongDAQStateException(status.message.value_or("Unknown error"));
case JFJochState::Idle:
case JFJochState::Busy:
case JFJochState::Calibration:
response.status = 504;
break;
}
}
void JFJochBrokerHttp::wait_till_done_post(const std::optional<int32_t> &timeout, httplib::Response &response) {
BrokerStatus status;
if (!timeout)
@@ -390,6 +440,8 @@ void JFJochBrokerHttp::wait_till_done_post(const std::optional<int32_t> &timeout
else
status = state_machine.WaitTillMeasurementDone(std::chrono::seconds(timeout.value()));
logger.Info("Wait till done");
switch (status.state) {
case JFJochState::Idle:
response.status = 200;
@@ -538,6 +590,7 @@ void JFJochBrokerHttp::statistics_get(httplib::Response &response) {
statistics.setAzInt(Convert(state_machine.GetRadialIntegrationSettings()));
statistics.setBuffer(Convert(state_machine.GetImageBufferStatus()));
statistics.setIndexing(Convert(state_machine.GetIndexingSettings()));
statistics.setBraggIntegration(Convert(state_machine.GetBraggIntegrationSettings()));
statistics.setDarkMask(Convert(state_machine.GetDarkMaskSettings()));
statistics.setImagePusher(Convert(state_machine.GetImagePusherStatus()));
@@ -627,6 +680,7 @@ void JFJochBrokerHttp::image_buffer_image_jpeg_get(const std::optional<int64_t>
const std::optional<bool> &showUserMask,
const std::optional<bool> &showRoi,
const std::optional<bool> &showSpots,
const std::optional<bool> &showPredictions,
const std::optional<bool> &showBeamCenter,
const std::optional<float> &saturation,
const std::optional<int64_t> &jpegQuality,
@@ -640,6 +694,7 @@ void JFJochBrokerHttp::image_buffer_image_jpeg_get(const std::optional<int64_t>
settings.show_user_mask = showUserMask.value_or(false);
settings.show_roi = showRoi.value_or(false);
settings.show_spots = showSpots.value_or(true);
settings.show_predictions = showPredictions.value_or(false);
settings.saturation_value = saturation;
settings.background_value = 0.0;
settings.jpeg_quality = jpegQuality.value_or(100);
@@ -704,9 +759,8 @@ void JFJochBrokerHttp::config_user_mask_tiff_get(httplib::Response &response) {
void JFJochBrokerHttp::config_user_mask_tiff_put(const httplib::Request &request,
httplib::Response &response) {
uint32_t cols, lines;
auto v = ReadTIFFFromString32(request.body, cols, lines);
state_machine.SetUserPixelMask(v);
std::vector<uint8_t> buffer;
state_machine.SetUserPixelMask(ReadTIFF(request.body, buffer));
response.status = 200;
}
@@ -771,6 +825,16 @@ void JFJochBrokerHttp::config_indexing_put(const Indexing_settings &indexingSett
response.status = 200;
}
void JFJochBrokerHttp::config_bragg_integration_get(httplib::Response &response) {
ProcessOutput(Convert(state_machine.GetBraggIntegrationSettings()), response);
}
void JFJochBrokerHttp::config_bragg_integration_put(const Bragg_integration_settings &braggIntegrationSettings,
httplib::Response &response) {
state_machine.SetBraggIntegrationSettings(Convert(braggIntegrationSettings));
response.status = 200;
}
void JFJochBrokerHttp::result_scan_get(httplib::Response &response) {
auto ret = state_machine.GetScanResult();
if (ret.has_value())
@@ -841,7 +905,7 @@ void JFJochBrokerHttp::preview_plot_get(const std::optional<std::string> &type,
if (azintUnit == "Q_recipA" || azintUnit == "q_recipa")
unit = PlotAzintUnit::Q_recipA;
else if (azintUnit == "d_A" || azintUnit == "d_a")
unit = PlotAzintUnit::D_A;
unit = PlotAzintUnit::d_A;
else if (azintUnit == "two_theta_deg")
unit = PlotAzintUnit::TwoTheta_deg;
}
+7
View File
@@ -17,6 +17,7 @@
#include "OpenAPIConvert.h"
#include "gen/model/Azim_int_settings.h"
#include "gen/model/Bragg_integration_settings.h"
#include "gen/model/Broker_status.h"
#include "gen/model/Dark_mask_settings.h"
#include "gen/model/Dataset_settings.h"
@@ -77,6 +78,8 @@ class JFJochBrokerHttp {
httplib::Response &response);
void status_get(httplib::Response &response);
void wait_till_done_post(const std::optional<int32_t> &timeout, httplib::Response &response);
void wait_until_running_post(const std::optional<int32_t> &timeout, httplib::Response &response);
void trigger_post(httplib::Response &response);
void pedestal_post(httplib::Response &response);
@@ -133,6 +136,7 @@ class JFJochBrokerHttp {
void image_buffer_image_cbor_get(const std::optional<int64_t> &id, httplib::Response &response);
void image_buffer_image_jpeg_get(const std::optional<int64_t> &id, const std::optional<bool> &showUserMask,
const std::optional<bool> &showRoi, const std::optional<bool> &showSpots,
const std::optional<bool> &showPredictions,
const std::optional<bool> &showBeamCenter, const std::optional<float> &saturation,
const std::optional<int64_t> &jpegQuality, const std::optional<float> &showResRing,
const std::optional<std::string> &color, const std::optional<bool> &showResEst,
@@ -174,6 +178,9 @@ class JFJochBrokerHttp {
void config_indexing_get(httplib::Response &response);
void config_indexing_put(const org::openapitools::server::model::Indexing_settings &indexingSettings,
httplib::Response &response);
void config_bragg_integration_get(httplib::Response &response);
void config_bragg_integration_put(const org::openapitools::server::model::Bragg_integration_settings &braggIntegrationSettings,
httplib::Response &response);
void config_dark_mask_get(httplib::Response &response);
void config_dark_mask_put(const org::openapitools::server::model::Dark_mask_settings &darkMaskSettings,
+29 -13
View File
@@ -91,10 +91,15 @@ DetectorSetup ParseDetectorSetup(const org::openapitools::server::model::Detecto
DetectorSetup setup(geom, detector_type, d.getDescription(), d.getHostname());
auto calib = d.getCalibrationFile();
auto trim_energies = d.getTrimEnergiesEV();
if (!calib.empty()) {
switch (detector_type) {
case DetectorType::EIGER:
setup.SetTrimFiles(calib);
if (trim_energies.empty())
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Trimming energies not provided");
setup.TrimEnergies_eV(trim_energies);
break;
case DetectorType::JUNGFRAU:
setup.LoadGain(calib);
@@ -118,25 +123,31 @@ DetectorSetup ParseDetectorSetup(const org::openapitools::server::model::Detecto
setup.HighVoltage(d.getHighVoltageV());
setup.UDPInterfaceCount(d.getUdpInterfaceCount())
.SensorThickness_um(d.getSensorThicknessUm())
// .PixelSize_um(GET_FLOAT(j, "pixel_size_um", 75.0f))
.SensorMaterial(d.getSensorMaterial())
.SerialNumber(d.getSerialNumber())
.ModuleSync(d.isModuleSync());
if (d.readoutTimeUsIsSet())
setup.ReadOutTime(std::chrono::microseconds(d.getReadoutTimeUs()));
// Only override the sensor from the request when it explicitly sets these. The API model defaults
// them (320 um / Si) with IsSet=false, so an unconditional set would clobber the detector-reported
// value (DECTRIS SIMPLON read) or a detector-specific default with 320 um (highVoltageV above is
// guarded the same way).
if (d.sensorThicknessUmIsSet())
setup.SensorThickness_um(d.getSensorThicknessUm());
if (d.sensorMaterialIsSet())
setup.SensorMaterial(d.getSensorMaterial());
if (d.readoutTimeNsIsSet())
setup.ReadOutTime(std::chrono::nanoseconds(d.getReadoutTimeNs()));
if (d.baseDataIpv4AddressIsSet())
setup.BaseIPv4Addr(d.getBaseDataIpv4Address());
if (d.txDelayIsSet())
setup.TxDelay(d.getTxDelay());
if (d.minimumCountTimeUsIsSet())
setup.MinCountTime(std::chrono::microseconds(d.getMinimumCountTimeUs()));
if (d.minCountTimeNsIsSet())
setup.MinCountTime(std::chrono::nanoseconds(d.getMinCountTimeNs()));
if (d.minimumFrameTimeUsIsSet())
setup.MinFrameTime(std::chrono::microseconds(d.getMinimumFrameTimeUs()));
if (d.minFrameTimeNsIsSet())
setup.MinFrameTime(std::chrono::nanoseconds(d.getMinFrameTimeNs()));
if (d.defaultSettingsIsSet())
setup.DefaultSettings(Convert(d.getDefaultSettings()));
@@ -166,6 +177,9 @@ void ParseFacilityConfiguration(const org::openapitools::server::model::Jfjoch_s
if (j.indexingIsSet())
experiment.ImportIndexingSettings(Convert(j.getIndexing()));
if (j.braggIntegrationIsSet())
experiment.ImportBraggIntegrationSettings(Convert(j.getBraggIntegration()));
if (j.darkMaskIsSet())
experiment.ImportDarkMaskSettings(Convert(j.getDarkMask()));
}
@@ -201,6 +215,12 @@ std::unique_ptr<ImagePusher> ParseTCPImagePusher(const org::openapitools::server
auto tmp = std::make_unique<TCPStreamPusher>(j.getTcp().getImageSocket(), j.getTcp().getNwriters(), send_buffer_size);
// Optional liveness/backpressure tuning; unset -> keep the pusher's built-in defaults.
if (j.getTcp().peerLivenessTimeoutMsIsSet() && j.getTcp().getPeerLivenessTimeoutMs() > 0)
tmp->SetPeerLivenessTimeout(std::chrono::milliseconds(j.getTcp().getPeerLivenessTimeoutMs()));
if (j.getTcp().maxBackpressureTimeoutMsIsSet() && j.getTcp().getMaxBackpressureTimeoutMs() > 0)
tmp->SetMaxBackpressureTimeout(std::chrono::milliseconds(j.getTcp().getMaxBackpressureTimeoutMs()));
return std::move(tmp);
}
@@ -234,10 +254,6 @@ void ParseAcquisitionDeviceGroup(const org::openapitools::server::model::Jfjoch_
}
void ParseReceiverSettings(const org::openapitools::server::model::Jfjoch_settings &input, JFJochReceiverService &service) {
std::string numa_policy = input.getNumaPolicy();
if (!numa_policy.empty())
service.NUMAPolicy(numa_policy);
// Using default in case
service.NumThreads(input.getReceiverThreads());
+1 -4
View File
@@ -1,8 +1,7 @@
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#ifndef JUNGFRAUJOCH_JFJOCHBROKERPARSER_H
#define JUNGFRAUJOCH_JFJOCHBROKERPARSER_H
#pragma once
#include "../common/DiffractionExperiment.h"
#include "../acquisition_device/AcquisitionDeviceGroup.h"
@@ -22,5 +21,3 @@ std::unique_ptr<ImagePusher> ParseImagePusher(const org::openapitools::server::m
void ParseAcquisitionDeviceGroup(const org::openapitools::server::model::Jfjoch_settings &input, AcquisitionDeviceGroup &aq_devices);
void ParseReceiverSettings(const org::openapitools::server::model::Jfjoch_settings &input, JFJochReceiverService &service);
SpotFindingSettings ParseSpotFindingSettings(const org::openapitools::server::model::Jfjoch_settings &input);
#endif //JUNGFRAUJOCH_JFJOCHBROKERPARSER_H
+62 -16
View File
@@ -15,22 +15,52 @@ void JFJochServices::Start(const DiffractionExperiment& experiment,
cannot_stop_detector = false;
if (receiver != nullptr) {
logger.Info(" ... receiver start");
receiver->Start(experiment, pixel_mask, calibration);
{
std::shared_lock ul(detector_mutex);
if (detector && !experiment.IsUsingInternalPacketGen()) {
logger.Info(" ... detector start");
detector->Start(experiment);
}
if (receiver == nullptr) {
logger.Info(" Done!");
return;
}
logger.Info(" ... receiver start");
if (image_puller)
image_puller->ResumeAndClear();
receiver->Start(experiment, pixel_mask, calibration, image_puller);
// From here the receiver is running asynchronously. If starting the detector fails, stop the
// receiver again so the service returns to idle and the run can be retried without
// re-initialising. The detector failure is then propagated (a critical detector error stays
// critical, so the broker still goes to the Error state).
try {
std::shared_lock ul(detector_mutex);
if (detector && !experiment.IsUsingInternalPacketGen()) {
logger.Info(" ... detector start");
detector->Start(experiment);
}
} catch (const std::exception &e) {
logger.Error(" ... detector failed to start ({}) - stopping detector and receiver", e.what());
// Best-effort cleanup - it must not replace the original detector exception (which may be
// critical), so swallow anything it throws and let the throw below re-raise e. The detector
// may have partially armed before failing, so stop it too; otherwise it lingers in a BUSY
// state and the next start fails with "detector busy" until a manual re-initialisation.
try {
{
std::shared_lock ul(detector_mutex);
if (detector)
detector->Stop();
}
receiver->Cancel(false);
receiver->Stop();
} catch (const std::exception &stop_error) {
logger.Warning("Stop after failed start reported: {}", stop_error.what());
}
throw;
}
logger.Info(" Done!");
}
void JFJochServices::Off() {
image_puller.reset();
std::unique_ptr<DetectorWrapper> old_detector;
{
std::unique_lock ul(detector_mutex);
@@ -53,9 +83,12 @@ void JFJochServices::On(DiffractionExperiment &x) {
case DetectorType::EIGER:
case DetectorType::JUNGFRAU:
new_detector = std::make_unique<SLSDetectorWrapper>();
image_puller.reset();
break;
case DetectorType::DECTRIS:
new_detector = std::make_unique<DectrisDetectorWrapper>();
image_puller = std::make_shared<ZMQImagePuller>(x.GetDetectorSetup().GetDECTRISStream2Addr());
image_puller->Suspend();
break;
}
new_detector->Initialize(x, receiver->GetNetworkConfig());
@@ -70,7 +103,10 @@ void JFJochServices::On(DiffractionExperiment &x) {
JFJochServicesOutput JFJochServices::Stop() {
JFJochServicesOutput ret;
std::unique_ptr<JFJochException> exception;
// Captured as an exception_ptr (not a copied JFJochException) so the dynamic type survives: a
// critical hardware fault (e.g. PCIeDeviceException) must stay critical when re-thrown, otherwise
// slicing it to a plain JFJochException would send the state machine to Idle instead of Error.
std::exception_ptr exception;
bool detector_error = false;
@@ -100,6 +136,8 @@ JFJochServicesOutput JFJochServices::Stop() {
logger.Info("Wait for receiver done");
ret.receiver_output = receiver->Stop();
if (image_puller)
image_puller->Suspend();
logger.Info(" ... Receiver efficiency: {} % Max delay: {} Compression ratio {}x",
static_cast<int>(ret.receiver_output.efficiency * 100.0),
@@ -113,11 +151,16 @@ JFJochServicesOutput JFJochServices::Stop() {
ret.receiver_output.received_packets[i], ret.receiver_output.expected_packets[i]);
}
}
// A writer that broke mid-run (e.g. a lost connection) leaves a truncated file. This is
// reported to the caller via receiver_output.writer_err (the state machine surfaces it as
// an error message) - it is not a detector fault, so it does not need re-initialisation.
logger.Info(" ... finished with success");
} catch (const JFJochException &e) {
logger.Error(" ... finished with error {}", e.what());
exception = std::make_unique<JFJochException>(e);
exception = std::current_exception();
}
logger.Info("Receiver finished with success");
} else {
logger.Info("No receiver - sleeping for 30 seconds");
std::this_thread::sleep_for(std::chrono::seconds(30));
@@ -125,11 +168,14 @@ JFJochServicesOutput JFJochServices::Stop() {
}
if (exception)
throw JFJochException(*exception);
// A detector fault must win over an ordinary receiver/writer error: it needs re-initialisation,
// so raise the critical exception first. If only the receiver failed, the run can be retried from
// Idle, so that ordinary error is raised second.
if (detector_error)
throw JFJochException(JFJochExceptionCategory::Detector, "Error in detector operation");
throw JFJochCriticalException("Error in detector operation");
if (exception)
std::rethrow_exception(exception);
return ret;
}
+2 -4
View File
@@ -1,8 +1,7 @@
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#ifndef JUNGFRAUJOCH_JFJOCHSERVICES_H
#define JUNGFRAUJOCH_JFJOCHSERVICES_H
#pragma once
#include <shared_mutex>
#include "../common/DiffractionExperiment.h"
@@ -20,6 +19,7 @@ class JFJochServices {
JFJochReceiverService *receiver = nullptr;
std::unique_ptr<DetectorWrapper> detector;
std::shared_ptr<ZMQImagePuller> image_puller;
std::atomic<bool> cannot_stop_detector = false;
Logger &logger;
@@ -74,5 +74,3 @@ public:
ImagePusherStatus GetImagePusherStatus() const;
};
#endif //JUNGFRAUJOCH_JFJOCHSERVICES_H
+125 -32
View File
@@ -7,6 +7,7 @@
#include "../preview/JFJochTIFF.h"
#include "../common/CUDAWrapper.h"
#include "../common/GitInfo.h"
#include "../common/JFJochException.h"
JFJochStateMachine::JFJochStateMachine(const DiffractionExperiment& in_experiment,
JFJochServices &in_services,
@@ -82,7 +83,7 @@ void JFJochStateMachine::CalibrateJUNGFRAU(std::unique_lock<std::mutex> &ul) {
pixel_mask.LoadDetectorBadPixelMask(experiment, calibration.get());
}
void JFJochStateMachine::CalibrateDetector(std::unique_lock<std::mutex> &ul) {
void JFJochStateMachine::CalibrateDetector(std::unique_lock<std::mutex> ul) {
cancel_sequence = false;
pixel_mask = PixelMask(experiment);
@@ -112,8 +113,9 @@ void JFJochStateMachine::CalibrateDetector(std::unique_lock<std::mutex> &ul) {
throw;
}
SetState(JFJochState::Idle, "Calibration sequence done", BrokerStatus::MessageSeverity::Success);
logger.Info("Pedestal sequence done");
logger.Info("Calibration sequence done");
ul.unlock(); // Notify all outside of mutex
c.notify_all();
}
void JFJochStateMachine::TakeDarkMaskInternal(std::unique_lock<std::mutex> &ul) {
@@ -144,7 +146,7 @@ void JFJochStateMachine::TakeDarkMaskInternal(std::unique_lock<std::mutex> &ul)
ul.lock();
if (mask_output.receiver_output.dark_mask_result.size() == local_experiment.GetPixelsNum()) {
pixel_mask.LoadDarkBadPixelMask(mask_output.receiver_output.dark_mask_result);
pixel_mask.LoadDarkBadPixelMask(local_experiment, mask_output.receiver_output.dark_mask_result);
SetState(JFJochState::Idle);
} else
SetState(JFJochState::Error, "Mask not collected properly", BrokerStatus::MessageSeverity::Error);
@@ -309,12 +311,9 @@ void JFJochStateMachine::Pedestal() {
if (state != JFJochState::Idle)
throw WrongDAQStateException("Must be idle to take pedestal");
measurement = std::async(std::launch::async, &JFJochStateMachine::PedestalThread, this, std::move(ul));
}
SetState(JFJochState::Busy, "Updating calibration", BrokerStatus::MessageSeverity::Info);
void JFJochStateMachine::PedestalThread(std::unique_lock<std::mutex> ul) {
CalibrateDetector(ul);
measurement = std::async(std::launch::async, &JFJochStateMachine::CalibrateDetector, this, std::move(ul));
}
void JFJochStateMachine::InitializeThread(std::unique_lock<std::mutex> ul) {
@@ -337,14 +336,14 @@ void JFJochStateMachine::InitializeThread(std::unique_lock<std::mutex> ul) {
SetState(JFJochState::Error, e.what(), BrokerStatus::MessageSeverity::Error);
throw;
}
CalibrateDetector(ul);
CalibrateDetector(std::move(ul));
}
void JFJochStateMachine::Trigger() {
services.Trigger();
}
void JFJochStateMachine::Start(const DatasetSettings &settings) {
void JFJochStateMachine::Start(const DatasetSettings &settings, bool async) {
std::unique_lock ul(m);
if (state != JFJochState::Idle)
@@ -363,20 +362,27 @@ void JFJochStateMachine::Start(const DatasetSettings &settings) {
experiment.IncrementRunNumber();
try {
SetState(JFJochState::Busy, "Preparing measurement", BrokerStatus::MessageSeverity::Info);
services.SetSpotFindingSettings(GetSpotFindingSettings());
services.Start(experiment, pixel_mask, calibration.get());
SetState(JFJochState::Measuring, "Measuring ...", BrokerStatus::MessageSeverity::Info);
measurement = std::async(std::launch::async, &JFJochStateMachine::MeasurementThread, this);
} catch (const std::exception &e) {
SetState(JFJochState::Error, e.what(), BrokerStatus::MessageSeverity::Error);
services.Cancel();
throw;
start_exception = nullptr;
SetState(JFJochState::Busy, "Preparing measurement", BrokerStatus::MessageSeverity::Info);
measurement = std::async(std::launch::async, &JFJochStateMachine::MeasurementThread, this);
if (!async) {
c.wait(ul, [&]() { return state != JFJochState::Busy; });
// A synchronous start propagates the failure to the caller. The state has already been set
// by MeasurementThread (Idle for an ordinary failure, Error for a critical detector fault).
if (start_exception) {
auto e = start_exception;
start_exception = nullptr;
std::rethrow_exception(e);
}
}
}
BrokerStatus JFJochStateMachine::WaitTillNotBusy(std::chrono::milliseconds timeout) {
std::unique_lock ul(m);
c.wait_for(ul, timeout, [&]() { return state != JFJochState::Busy; });
return GetStatus();
}
void JFJochStateMachine::UpdatePixelMaskStatistics(const PixelMaskStatistics &input) {
std::unique_lock ul(pixel_mask_statistics_mutex);
pixel_mask_statistics = input;
@@ -388,17 +394,62 @@ PixelMaskStatistics JFJochStateMachine::GetPixelMaskStatistics() const {
}
void JFJochStateMachine::MeasurementThread() {
try {
services.SetSpotFindingSettings(GetSpotFindingSettings());
services.Start(experiment, pixel_mask, calibration.get());
{
std::unique_lock ul(m);
SetState(JFJochState::Measuring, "Measuring ...", BrokerStatus::MessageSeverity::Info);
}
c.notify_all();
} catch (const JFJochCriticalException &e) {
// Detector left in an undefined state - force re-initialisation via the Error state.
logger.Error("Critical error starting measurement: {}", e.what());
{
std::unique_lock ul(m);
SetState(JFJochState::Error, e.what(), BrokerStatus::MessageSeverity::Error);
start_exception = std::current_exception();
}
c.notify_all();
return;
} catch (const std::exception &e) {
// Ordinary acquisition failure - the detector is still configured/calibrated, so return to
// Idle and let the user retry without re-initialising. services.Start has already stopped the
// receiver it launched.
logger.Error("Error starting measurement: {}", e.what());
{
std::unique_lock ul(m);
SetState(JFJochState::Idle, e.what(), BrokerStatus::MessageSeverity::Error);
start_exception = std::current_exception();
}
c.notify_all();
return;
}
try {
auto tmp_output = services.Stop();
{
std::unique_lock ul(m);
scan_result = tmp_output.receiver_output.scan_result;
if (tmp_output.receiver_output.writer_queue_full_warning)
SetState(JFJochState::Idle,
"Stream receiver (writer or downstream analysis) cannot cope with data; reduce frame rate",
BrokerStatus::MessageSeverity::Warning);
else if (tmp_output.receiver_output.status.cancelled)
auto image_mean_time = tmp_output.receiver_output.processing_time;
logger.Info("Per-image mean processing time (microseconds): compression {:.0f} preprocess {:.0f} azint {:.0f} spot finding {:.0f} indexing {:.0f} refinement {:.0f} indexing analysis {:.0f} prediction {:.0f} integration {:.0f} total {:.0f}",
image_mean_time.compression * 1e6,
image_mean_time.preprocessing * 1e6,
image_mean_time.azint * 1e6,
image_mean_time.spot_finding * 1e6,
image_mean_time.indexing * 1e6,
image_mean_time.refinement * 1e6,
image_mean_time.indexing_analysis * 1e6,
image_mean_time.bragg_prediction * 1e6,
image_mean_time.integration * 1e6,
image_mean_time.processing * 1e6);
// Priority order matters. A cancel is checked first (it legitimately leaves efficiency < 1),
// then the hard errors (missing packets, truncated writer output). The queue-full warning is
// only the primary status when the run otherwise succeeded - it must not mask a real error
// by downgrading an incomplete/truncated dataset to a "reduce frame rate" warning.
if (tmp_output.receiver_output.status.cancelled)
SetState(JFJochState::Idle,
"Data collection cancelled",
BrokerStatus::MessageSeverity::Info);
@@ -408,16 +459,28 @@ void JFJochStateMachine::MeasurementThread() {
BrokerStatus::MessageSeverity::Error);
else if (!tmp_output.receiver_output.writer_err.empty())
SetState(JFJochState::Idle,
tmp_output.receiver_output.writer_err,
"Writer error, written data may be incomplete: " + tmp_output.receiver_output.writer_err,
BrokerStatus::MessageSeverity::Error);
else if (tmp_output.receiver_output.writer_queue_full_warning)
SetState(JFJochState::Idle,
"Stream receiver (writer or downstream analysis) cannot cope with data; reduce frame rate",
BrokerStatus::MessageSeverity::Warning);
else
SetState(JFJochState::Idle,
"Data collection without problems",
BrokerStatus::MessageSeverity::Success);
}
} catch (const std::exception &e) {
} catch (const JFJochCriticalException &e) {
// Detector faulted during the run - it needs re-initialisation, so go to the Error state.
logger.Error("Critical error finishing measurement: {}", e.what());
std::unique_lock ul(m);
SetState(JFJochState::Error, e.what(), BrokerStatus::MessageSeverity::Error);
} catch (const std::exception &e) {
// Receiver/writer problem - the data may be incomplete, but the detector is still usable, so
// return to Idle rather than forcing re-initialisation.
logger.Error("Error finishing measurement: {}", e.what());
std::unique_lock ul(m);
SetState(JFJochState::Idle, e.what(), BrokerStatus::MessageSeverity::Error);
}
c.notify_all();
}
@@ -528,7 +591,7 @@ void JFJochStateMachine::LoadDetectorSettings(const DetectorSettings &settings)
case JFJochState::Idle:
if (ImportDetectorSettings(settings)) {
SetState(JFJochState::Busy, "Loading settings", BrokerStatus::MessageSeverity::Info);
measurement = std::async(std::launch::async, &JFJochStateMachine::PedestalThread, this, std::move(ul));
measurement = std::async(std::launch::async, &JFJochStateMachine::CalibrateDetector, this, std::move(ul));
} else {
try {
SetState(JFJochState::Busy, "Configure detector", BrokerStatus::MessageSeverity::Info);
@@ -785,7 +848,7 @@ void JFJochStateMachine::LoadInternalGeneratorImageTIFF(const std::string &s, ui
uint32_t cols, lines;
auto v = ReadTIFFFromString16(s, cols, lines);
if (((cols == experiment.GetXPixelsNum()) && (lines == experiment.GetYPixelsNum()))
|| ((cols == RAW_MODULE_SIZE) && (lines == RAW_MODULE_LINES * experiment.GetModulesNum())))
|| ((cols == RAW_MODULE_COLS) && (lines == RAW_MODULE_LINES * experiment.GetModulesNum())))
services.LoadInternalGeneratorImage(experiment, v, image_number);
else
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
@@ -876,6 +939,21 @@ void JFJochStateMachine::SetUserPixelMask(const std::vector<uint32_t> &v) {
}
}
void JFJochStateMachine::SetUserPixelMask(const CompressedImage &image) {
std::unique_lock ul(m);
if (state != JFJochState::Idle)
throw WrongDAQStateException("User mask can be only modified in Idle state");
try {
pixel_mask.LoadUserMask(experiment, image);
UpdatePixelMaskStatistics(pixel_mask.GetStatistics());
} catch (const JFJochException &e) {
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Problem handling user mask " + std::string(e.what()));
}
}
InstrumentMetadata JFJochStateMachine::GetInstrumentMetadata() const {
std::unique_lock ul(experiment_instrument_metadata_mutex);
return experiment.GetInstrumentMetadata();
@@ -1017,6 +1095,21 @@ void JFJochStateMachine::SetIndexingSettings(const IndexingSettings &input) {
}
}
BraggIntegrationSettings JFJochStateMachine::GetBraggIntegrationSettings() const {
std::unique_lock ul(experiment_indexing_settings_mutex);
return experiment.GetBraggIntegrationSettings();
}
void JFJochStateMachine::SetBraggIntegrationSettings(const BraggIntegrationSettings &input) {
std::unique_lock ul(m);
if (IsRunning())
throw WrongDAQStateException("Cannot change Bragg integration settings during data collection");
// The analysis engines read the integrator mode off the experiment when they are built at the start
// of the next run, so importing it here is all that is needed.
std::unique_lock ul2(experiment_indexing_settings_mutex);
experiment.ImportBraggIntegrationSettings(input);
}
std::optional<ScanResult> JFJochStateMachine::GetScanResult() const {
std::unique_lock ul(m);
if (IsRunning())
@@ -1042,7 +1135,7 @@ void JFJochStateMachine::SetDarkMaskSettings(const DarkMaskSettings &settings) {
if ((experiment.GetDetectorType() == DetectorType::DECTRIS) && (state == JFJochState::Idle)) {
// Need to redo the calibration
SetState(JFJochState::Busy, "Loading settings", BrokerStatus::MessageSeverity::Info);
measurement = std::async(std::launch::async, &JFJochStateMachine::PedestalThread, this, std::move(ul));
measurement = std::async(std::launch::async, &JFJochStateMachine::CalibrateDetector, this, std::move(ul));
}
}
+15 -11
View File
@@ -1,13 +1,13 @@
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#ifndef JUNGFRAUJOCH_JFJOCHSTATEMACHINE_H
#define JUNGFRAUJOCH_JFJOCHSTATEMACHINE_H
#pragma once
#include <string>
#include <mutex>
#include <future>
#include <optional>
#include <exception>
#include "../common/DiffractionExperiment.h"
#include "../jungfrau/JFCalibration.h"
@@ -25,9 +25,9 @@ struct DetectorListElement {
int64_t nmodules;
int64_t width;
int64_t height;
std::chrono::microseconds readout_time;
std::chrono::microseconds min_frame_time;
std::chrono::microseconds min_count_time;
std::chrono::nanoseconds readout_time;
std::chrono::nanoseconds min_frame_time;
std::chrono::nanoseconds min_count_time;
DetectorType detector_type;
float pixel_size_mm;
};
@@ -100,6 +100,8 @@ class JFJochStateMachine {
PixelMask pixel_mask;
int64_t current_detector_setup; // Lock only on change
std::optional<ScanResult> scan_result;
// Set by MeasurementThread when a synchronous Start fails, so Start() can rethrow to the caller
std::exception_ptr start_exception;
mutable std::mutex calibration_statistics_mutex;
std::vector<JFCalibrationModuleStatistics> calibration_statistics;
@@ -127,14 +129,13 @@ class JFJochStateMachine {
const std::optional<std::string> &message = {},
BrokerStatus::MessageSeverity message_severity = BrokerStatus::MessageSeverity::Info);
void MeasurementThread();
void PedestalThread(std::unique_lock<std::mutex> ul);
void InitializeThread(std::unique_lock<std::mutex> ul);
bool ImportPedestalG1G2(const JFJochReceiverOutput &receiver_output, size_t gain_level, size_t storage_cell = 0);
bool ImportPedestalG0(const JFJochReceiverOutput &receiver_output);
bool IsRunning() const; // Is state Busy/Pedestal/Measure
void ResetError() noexcept;
void TakeDarkMaskInternal(std::unique_lock<std::mutex> &ul);
void CalibrateDetector(std::unique_lock<std::mutex> &ul);
void CalibrateDetector(std::unique_lock<std::mutex> ul);
void CalibrateJUNGFRAU(std::unique_lock<std::mutex> &ul);
void TakePedestalInternalG0(std::unique_lock<std::mutex> &ul);
void TakePedestalInternalG1(std::unique_lock<std::mutex> &ul, int32_t storage_cell = 0);
@@ -152,7 +153,9 @@ public:
void Initialize();
void Pedestal();
void Deactivate();
void Start(const DatasetSettings& settings);
void Start(const DatasetSettings& settings, bool async = false);
BrokerStatus WaitTillNotBusy(std::chrono::milliseconds timeout);
BrokerStatus WaitTillMeasurementDone();
BrokerStatus WaitTillMeasurementDone(std::chrono::milliseconds timeout);
void Trigger();
@@ -220,6 +223,7 @@ public:
std::vector<uint32_t> GetUserPixelMask() const;
void SetUserPixelMask(const std::vector<uint32_t> &v);
void SetUserPixelMask(const CompressedImage &image);
std::vector<DeviceStatus> GetDeviceStatus() const;
@@ -231,6 +235,9 @@ public:
void SetIndexingSettings(const IndexingSettings &input);
IndexingSettings GetIndexingSettings() const;
void SetBraggIntegrationSettings(const BraggIntegrationSettings &input);
BraggIntegrationSettings GetBraggIntegrationSettings() const;
PixelMaskStatistics GetPixelMaskStatistics() const;
void GetStartMessageFromBuffer(std::vector<uint8_t> &v);
@@ -246,6 +253,3 @@ public:
ImagePusherStatus GetImagePusherStatus() const;
};
#endif //JUNGFRAUJOCH_JFJOCHSTATEMACHINE_H
+109 -19
View File
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#include "../common/JFJochMath.h"
#include "OpenAPIConvert.h"
// From https://en.cppreference.com/w/cpp/string/byte/tolower
@@ -170,9 +171,12 @@ DetectorSettings Convert(const org::openapitools::server::model::Detector_settin
org::openapitools::server::model::Detector_settings Convert(const DetectorSettings &input) {
org::openapitools::server::model::Detector_settings ret{};
ret.setFrameTimeUs(input.GetFrameTime().count());
ret.setFrameTimeUs(std::chrono::round<std::chrono::microseconds>(
std::chrono::duration<float>(input.GetFrameTime())).count());
if (input.GetCountTime().has_value())
ret.setCountTimeUs(input.GetCountTime()->count());
ret.setCountTimeUs(std::chrono::round<std::chrono::microseconds>(
std::chrono::duration<float>(input.GetCountTime().value())
).count());
ret.setDetectorTriggerDelayNs(input.GetDetectorDelay().count());
ret.setInternalFrameGeneratorImages(input.GetInternalGeneratorImages());
ret.setInternalFrameGenerator(input.IsInternalGeneratorEnable());
@@ -370,9 +374,9 @@ org::openapitools::server::model::Detector_list Convert(const DetectorList &inpu
d.setSerialNumber(input.detector[i].serial_number);
d.setBaseIpv4Addr(input.detector[i].base_ipv4_addr);
d.setUdpInterfaceCount(input.detector[i].udp_interface_count);
d.setMinFrameTimeUs(input.detector[i].min_frame_time.count());
d.setMinCountTimeUs(input.detector[i].min_count_time.count());
d.setReadoutTimeUs(input.detector[i].readout_time.count());
d.setMinFrameTimeNs(input.detector[i].min_frame_time.count());
d.setMinCountTimeNs(input.detector[i].min_count_time.count());
d.setReadoutTimeNs(input.detector[i].readout_time.count());
d.setPixelSizeMm(input.detector[i].pixel_size_mm);
d.setType(Convert(input.detector[i].detector_type));
dets.emplace_back(std::move(d));
@@ -435,6 +439,7 @@ AzimuthalIntegrationSettings Convert(const org::openapitools::server::model::Azi
ret.QSpacing_recipA(input.getQSpacing());
ret.QRange_recipA(input.getLowQRecipA(), input.getHighQRecipA());
ret.AzimuthalBinCount(input.getAzimuthalBins());
ret.ForceCPUinFPGAWorkflow(input.isForceCpu());
return ret;
}
@@ -446,6 +451,7 @@ org::openapitools::server::model::Azim_int_settings Convert(const AzimuthalInteg
ret.setLowQRecipA(settings.GetLowQ_recipA());
ret.setQSpacing(settings.GetQSpacing_recipA());
ret.setAzimuthalBins(settings.GetAzimuthalBinCount());
ret.setForceCpu(settings.IsForceCPUinFPGAWorkflow());
return ret;
}
@@ -455,10 +461,18 @@ ROIDefinition Convert(const org::openapitools::server::model::Roi_definitions& i
output.boxes.emplace_back(ROIBox(i.getName(), i.getMinXPxl(), i.getMaxXPxl(), i.getMinYPxl(), i.getMaxYPxl()));
for (const auto &i: input.getCircle().getRois())
output.circles.emplace_back(ROICircle(i.getName(), i.getCenterXPxl(), i.getCenterYPxl(), i.getRadiusPxl()));
for (const auto &i: input.getAzim().getRois())
for (const auto &i: input.getAzim().getRois()) {
// A sector needs both bounds; if only one is given, treat it as a full ring.
float phi_min = 0, phi_max = 0;
if (i.phiMinDegIsSet() && i.phiMaxDegIsSet()) {
phi_min = i.getPhiMinDeg();
phi_max = i.getPhiMaxDeg();
}
output.azimuthal.emplace_back(ROIAzimuthal(i.getName(),
(i.getQMaxRecipA() == 0.0) ? 0.0 : 2.0f * M_PI / i.getQMaxRecipA(),
(i.getQMinRecipA() == 0.0) ? 0.0 : 2.0f * M_PI / i.getQMinRecipA()));
(i.getQMaxRecipA() == 0.0) ? 0.0 : 2.0f * PI / i.getQMaxRecipA(),
(i.getQMinRecipA() == 0.0) ? 0.0 : 2.0f * PI / i.getQMinRecipA(),
phi_min, phi_max));
}
return output;
}
@@ -485,6 +499,10 @@ org::openapitools::server::model::Roi_azim_list Convert(const std::vector<ROIAzi
elem.setName(i.GetName());
elem.setQMinRecipA(i.GetQMin_recipA());
elem.setQMaxRecipA(i.GetQMax_recipA());
if (i.HasPhi()) {
elem.setPhiMinDeg(i.GetPhiMin_deg());
elem.setPhiMaxDeg(i.GetPhiMax_deg());
}
tmp.emplace_back(elem);
}
ret.setRois(tmp);
@@ -607,6 +625,8 @@ DatasetSettings Convert(const org::openapitools::server::model::Dataset_settings
ret.Compression(CompressionAlgorithm::BSHUF_ZSTD);
else if (compr == "bszstd_rle")
ret.Compression(CompressionAlgorithm::BSHUF_ZSTD_RLE);
else if (compr == "bszstd_rlehuf")
ret.Compression(CompressionAlgorithm::BSHUF_ZSTD_RLE_HUFF);
else if (compr == "none")
ret.Compression(CompressionAlgorithm::NO_COMPRESSION);
else
@@ -674,6 +694,18 @@ DatasetSettings Convert(const org::openapitools::server::model::Dataset_settings
ret.FluorescenceSpectrum({fl.getEnergyEV(), fl.getData()});
}
if (input.smargonIsSet()) {
auto sm = input.getSmargon();
SmargonPosition smargon;
smargon.phi_deg = sm.getPhiDeg();
smargon.chi_deg = sm.getChiDeg();
if (sm.phiAxisIsSet())
smargon.phi_axis = ConvertOpenAPI(sm.getPhiAxis());
if (sm.chiAxisIsSet())
smargon.chi_axis = ConvertOpenAPI(sm.getChiAxis());
ret.Smargon(smargon);
}
return ret;
}
@@ -725,7 +757,7 @@ org::openapitools::server::model::Zeromq_preview_settings Convert(const ZMQPrevi
org::openapitools::server::model::Zeromq_preview_settings ret;
ret.setEnabled(settings.period.has_value());
if (settings.period.has_value())
ret.setPeriodMs(settings.period.value().count());
ret.setPeriodMs(std::chrono::round<std::chrono::milliseconds>(settings.period.value()).count());
ret.setSocketAddress(settings.address);
return ret;
}
@@ -734,7 +766,7 @@ org::openapitools::server::model::Zeromq_metadata_settings Convert(const ZMQMeta
org::openapitools::server::model::Zeromq_metadata_settings ret;
ret.setEnabled(settings.period.has_value());
if (settings.period.has_value())
ret.setPeriodMs(settings.period.value().count());
ret.setPeriodMs(std::chrono::round<std::chrono::milliseconds>(settings.period.value()).count());
ret.setSocketAddress(settings.address);
return ret;
}
@@ -806,12 +838,6 @@ org::openapitools::server::model::File_writer_format Convert(FileWriterFormat in
case FileWriterFormat::NXmxIntegrated:
ret.setValue(org::openapitools::server::model::File_writer_format::eFile_writer_format::NXMXINTEGRATED);
break;
case FileWriterFormat::CBF:
ret.setValue(org::openapitools::server::model::File_writer_format::eFile_writer_format::CBF);
break;
case FileWriterFormat::TIFF:
ret.setValue(org::openapitools::server::model::File_writer_format::eFile_writer_format::TIFF);
break;
case FileWriterFormat::NoFile:
ret.setValue(org::openapitools::server::model::File_writer_format::eFile_writer_format::NOFILEWRITTEN);
break;
@@ -832,9 +858,10 @@ FileWriterFormat Convert(const org::openapitools::server::model::File_writer_for
case org::openapitools::server::model::File_writer_format::eFile_writer_format::NXMXINTEGRATED:
return FileWriterFormat::NXmxIntegrated;
case org::openapitools::server::model::File_writer_format::eFile_writer_format::CBF:
return FileWriterFormat::CBF;
case org::openapitools::server::model::File_writer_format::eFile_writer_format::TIFF:
return FileWriterFormat::TIFF;
// Deprecated, kept in the OpenAPI enum for back compatibility only - only HDF5 is written now.
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"CBF and TIFF file formats are no longer supported");
case org::openapitools::server::model::File_writer_format::eFile_writer_format::NOFILEWRITTEN:
return FileWriterFormat::NoFile;
default:
@@ -848,6 +875,7 @@ PlotType ConvertPlotType(const std::optional<std::string>& input) {
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Plot type is compulsory paramater");
if (input == "bkg_estimate") return PlotType::BkgEstimate;
if (input == "ice_ring_score") return PlotType::IceRingScore;
if (input == "azint") return PlotType::AzInt;
if (input == "azint_1d") return PlotType::AzInt1D;
if (input == "spot_count") return PlotType::SpotCount;
@@ -879,6 +907,12 @@ PlotType ConvertPlotType(const std::optional<std::string>& input) {
if (input == "processing_time") return PlotType::ImageProcessingTime;
if (input == "beam_center_x") return PlotType::RefinementBeamX;
if (input == "beam_center_y") return PlotType::RefinementBeamY;
if (input == "integrated_reflections") return PlotType::IntegratedReflections;
if (input == "image_scale_factor") return PlotType::ImageScaleFactor;
if (input == "image_scale_cc") return PlotType::ImageScaleCC;
if (input == "image_scale_b") return PlotType::ImageScaleBFactor;
if (input == "compression_ratio") return PlotType::CompressionRatio;
if (input == "indexing_lattice_count") return PlotType::IndexingLatticeCount;
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
"Plot type not recognized");
}
@@ -935,6 +969,12 @@ IndexingSettings Convert(const org::openapitools::server::model::Indexing_settin
case org::openapitools::server::model::Geom_refinement_algorithm::eGeom_refinement_algorithm::BEAMCENTER:
ret.GeomRefinementAlgorithm(GeomRefinementAlgorithmEnum::BeamCenter);
break;
case org::openapitools::server::model::Geom_refinement_algorithm::eGeom_refinement_algorithm::ORIENTATIONONLY:
ret.GeomRefinementAlgorithm(GeomRefinementAlgorithmEnum::OrientationOnly);
break;
case org::openapitools::server::model::Geom_refinement_algorithm::eGeom_refinement_algorithm::FLEX:
ret.GeomRefinementAlgorithm(GeomRefinementAlgorithmEnum::Flex);
break;
case org::openapitools::server::model::Geom_refinement_algorithm::eGeom_refinement_algorithm::NONE:
ret.GeomRefinementAlgorithm(GeomRefinementAlgorithmEnum::None);
break;
@@ -981,6 +1021,12 @@ org::openapitools::server::model::Indexing_settings Convert(const IndexingSettin
case GeomRefinementAlgorithmEnum::BeamCenter:
refinement.setValue(org::openapitools::server::model::Geom_refinement_algorithm::eGeom_refinement_algorithm::BEAMCENTER);
break;
case GeomRefinementAlgorithmEnum::OrientationOnly:
refinement.setValue(org::openapitools::server::model::Geom_refinement_algorithm::eGeom_refinement_algorithm::ORIENTATIONONLY);
break;
case GeomRefinementAlgorithmEnum::Flex:
refinement.setValue(org::openapitools::server::model::Geom_refinement_algorithm::eGeom_refinement_algorithm::FLEX);
break;
}
ret.setGeomRefinementAlgorithm(refinement);
@@ -1008,6 +1054,42 @@ org::openapitools::server::model::Indexing_settings Convert(const IndexingSettin
return ret;
}
BraggIntegrationSettings Convert(const org::openapitools::server::model::Bragg_integration_settings &input) {
BraggIntegrationSettings ret;
switch (input.getIntegrationModel().getValue()) {
case org::openapitools::server::model::Integration_model::eIntegration_model::PROFILEGAUSSIAN:
ret.Integrator(IntegratorMode::ProfileGaussian);
break;
case org::openapitools::server::model::Integration_model::eIntegration_model::PROFILEEMPIRICAL:
ret.Integrator(IntegratorMode::ProfileEmpirical);
break;
case org::openapitools::server::model::Integration_model::eIntegration_model::BOXSUM:
ret.Integrator(IntegratorMode::BoxSum);
break;
default:
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "Unknown integration model");
}
return ret;
}
org::openapitools::server::model::Bragg_integration_settings Convert(const BraggIntegrationSettings &input) {
org::openapitools::server::model::Bragg_integration_settings ret;
org::openapitools::server::model::Integration_model tmp;
switch (input.GetIntegrator()) {
case IntegratorMode::ProfileGaussian:
tmp.setValue(org::openapitools::server::model::Integration_model::eIntegration_model::PROFILEGAUSSIAN);
break;
case IntegratorMode::ProfileEmpirical:
tmp.setValue(org::openapitools::server::model::Integration_model::eIntegration_model::PROFILEEMPIRICAL);
break;
case IntegratorMode::BoxSum:
tmp.setValue(org::openapitools::server::model::Integration_model::eIntegration_model::BOXSUM);
break;
}
ret.setIntegrationModel(tmp);
return ret;
}
org::openapitools::server::model::Scan_result Convert(const ScanResult& input) {
org::openapitools::server::model::Scan_result ret;
ret.setFilePrefix(input.file_prefix);
@@ -1036,6 +1118,8 @@ org::openapitools::server::model::Scan_result Convert(const ScanResult& input) {
tmp.setSpots(i.spot_count.value());
if (i.spot_count_ice.has_value())
tmp.setSpotsIce(i.spot_count_ice.value());
if (i.ice_ring_score.has_value())
tmp.setIce(i.ice_ring_score.value());
if (i.spot_count_low_res.has_value())
tmp.setSpotsLowRes(i.spot_count_low_res.value());
if (i.spot_count_indexed.has_value())
@@ -1056,6 +1140,8 @@ org::openapitools::server::model::Scan_result Convert(const ScanResult& input) {
uc.setGamma(i.uc->gamma);
tmp.setUc(uc);
}
if (i.indexed_lattice_count.has_value())
tmp.setLattCount(i.indexed_lattice_count.value());
if (i.xfel_pulse_id.has_value())
tmp.setXfelPulseid(i.xfel_pulse_id.value());
if (i.res.has_value())
@@ -1076,13 +1162,17 @@ org::openapitools::server::model::Scan_result Convert(const ScanResult& input) {
uc.setGamma(i_uc.gamma);
ret.setRotationUnitCell(uc);
}
if (input.rotation_crystal_system && input.rotation_centering)
ret.setRotationBravais(BravaisSymbol(*input.rotation_crystal_system, *input.rotation_centering));
return ret;
}
org::openapitools::server::model::Dark_mask_settings Convert(const DarkMaskSettings &input) {
org::openapitools::server::model::Dark_mask_settings ret{};
ret.setDetectorThresholdKeV(input.GetThreshold_keV());
ret.setFrameTimeUs(input.GetFrameTime().count());
ret.setFrameTimeUs(std::chrono::round<std::chrono::microseconds>(
std::chrono::duration<float>(input.GetFrameTime())
).count());
ret.setMaxFramesWithSignal(input.GetMaxFramesWithCounts());
ret.setMaxAllowedPixelCount(input.GetMaxCounts());
ret.setNumberOfFrames(input.GetNumberOfFrames());
+6 -3
View File
@@ -1,8 +1,7 @@
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#ifndef JFJOCH_OPENAPICONVERT_H
#define JFJOCH_OPENAPICONVERT_H
#pragma once
#include "Dark_mask_settings.h"
#include "Image_pusher_status.h"
@@ -29,6 +28,7 @@
#include "gen/model/Rotation_axis.h"
#include "gen/model/Grid_scan.h"
#include "gen/model/Indexing_settings.h"
#include "gen/model/Bragg_integration_settings.h"
#include "gen/model/Scan_result.h"
#include "../common/JFJochMessages.h"
@@ -48,6 +48,9 @@ org::openapitools::server::model::Spot_finding_settings Convert(const SpotFindin
IndexingSettings Convert(const org::openapitools::server::model::Indexing_settings &input);
org::openapitools::server::model::Indexing_settings Convert(const IndexingSettings &input);
BraggIntegrationSettings Convert(const org::openapitools::server::model::Bragg_integration_settings &input);
org::openapitools::server::model::Bragg_integration_settings Convert(const BraggIntegrationSettings &input);
org::openapitools::server::model::Measurement_statistics Convert(const MeasurementStatistics &input);
DetectorSettings Convert(const org::openapitools::server::model::Detector_settings &input);
@@ -96,4 +99,4 @@ org::openapitools::server::model::Dark_mask_settings Convert(const DarkMaskSetti
DarkMaskSettings Convert(const org::openapitools::server::model::Dark_mask_settings& input);
org::openapitools::server::model::Image_pusher_status Convert(const ImagePusherStatus& input);
#endif //JFJOCH_OPENAPICONVERT_H
+14
View File
@@ -0,0 +1,14 @@
# Generated OpenAPI cpp-pistache-server output.
#
# Only model/ is compiled (into the JFJochAPI library) and tracked. The REST
# server is hand-written on cpp-httplib (see broker/JFJochBrokerHttp.cpp), so the
# generated Pistache server stubs below are regeneration debris: never compiled,
# and they tend to carry a newer spec version than the committed models. Keep
# them out of git to avoid accidentally committing mismatched artefacts.
/api/
/impl/
/main-api-server.cpp
/CMakeLists.txt
/README.md
/.openapi-generator/
/.openapi-generator-ignore
+87 -6
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -28,6 +28,8 @@ Azim_int_settings::Azim_int_settings()
m_Q_spacing = 0.0f;
m_Azimuthal_bins = 1L;
m_Azimuthal_binsIsSet = false;
m_Force_cpu = false;
m_Force_cpuIsSet = false;
}
@@ -50,7 +52,59 @@ bool Azim_int_settings::validate(std::stringstream& msg, const std::string& path
bool success = true;
const std::string _pathPrefix = pathPrefix.empty() ? "Azim_int_settings" : pathPrefix;
/* High_q_recipA */ {
const float& value = m_High_q_recipA;
const std::string currentValuePath = _pathPrefix + ".highQRecipA";
if (value < static_cast<float>(0.000020))
{
success = false;
msg << currentValuePath << ": must be greater than or equal to 0.000020;";
}
if (value > static_cast<float>(10.0))
{
success = false;
msg << currentValuePath << ": must be less than or equal to 10.0;";
}
}
/* Low_q_recipA */ {
const float& value = m_Low_q_recipA;
const std::string currentValuePath = _pathPrefix + ".lowQRecipA";
if (value < static_cast<float>(0.000010))
{
success = false;
msg << currentValuePath << ": must be greater than or equal to 0.000010;";
}
if (value > static_cast<float>(10))
{
success = false;
msg << currentValuePath << ": must be less than or equal to 10;";
}
}
/* Q_spacing */ {
const float& value = m_Q_spacing;
const std::string currentValuePath = _pathPrefix + ".qSpacing";
if (value < static_cast<float>(0.000010))
{
success = false;
msg << currentValuePath << ": must be greater than or equal to 0.000010;";
}
}
if (azimuthalBinsIsSet())
{
const int64_t& value = m_Azimuthal_bins;
@@ -62,14 +116,14 @@ bool Azim_int_settings::validate(std::stringstream& msg, const std::string& path
success = false;
msg << currentValuePath << ": must be greater than or equal to 1;";
}
if (value > 256ll)
if (value > 512ll)
{
success = false;
msg << currentValuePath << ": must be less than or equal to 256;";
msg << currentValuePath << ": must be less than or equal to 512;";
}
}
return success;
}
@@ -94,7 +148,10 @@ bool Azim_int_settings::operator==(const Azim_int_settings& rhs) const
&&
((!azimuthalBinsIsSet() && !rhs.azimuthalBinsIsSet()) || (azimuthalBinsIsSet() && rhs.azimuthalBinsIsSet() && getAzimuthalBins() == rhs.getAzimuthalBins()))
((!azimuthalBinsIsSet() && !rhs.azimuthalBinsIsSet()) || (azimuthalBinsIsSet() && rhs.azimuthalBinsIsSet() && getAzimuthalBins() == rhs.getAzimuthalBins())) &&
((!forceCpuIsSet() && !rhs.forceCpuIsSet()) || (forceCpuIsSet() && rhs.forceCpuIsSet() && isForceCpu() == rhs.isForceCpu()))
;
}
@@ -114,6 +171,8 @@ void to_json(nlohmann::json& j, const Azim_int_settings& o)
j["q_spacing"] = o.m_Q_spacing;
if(o.azimuthalBinsIsSet())
j["azimuthal_bins"] = o.m_Azimuthal_bins;
if(o.forceCpuIsSet())
j["force_cpu"] = o.m_Force_cpu;
}
@@ -129,6 +188,11 @@ void from_json(const nlohmann::json& j, Azim_int_settings& o)
j.at("azimuthal_bins").get_to(o.m_Azimuthal_bins);
o.m_Azimuthal_binsIsSet = true;
}
if(j.find("force_cpu") != j.end())
{
j.at("force_cpu").get_to(o.m_Force_cpu);
o.m_Force_cpuIsSet = true;
}
}
@@ -189,6 +253,23 @@ void Azim_int_settings::unsetAzimuthal_bins()
{
m_Azimuthal_binsIsSet = false;
}
bool Azim_int_settings::isForceCpu() const
{
return m_Force_cpu;
}
void Azim_int_settings::setForceCpu(bool const value)
{
m_Force_cpu = value;
m_Force_cpuIsSet = true;
}
bool Azim_int_settings::forceCpuIsSet() const
{
return m_Force_cpuIsSet;
}
void Azim_int_settings::unsetForce_cpu()
{
m_Force_cpuIsSet = false;
}
} // namespace org::openapitools::server::model
+10 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -89,6 +89,13 @@ public:
void setAzimuthalBins(int64_t const value);
bool azimuthalBinsIsSet() const;
void unsetAzimuthal_bins();
/// <summary>
/// Force CPU processing of azimuthal integration in the FPGA data acquisition workflow. This allows to extend number of azimuthal integration bins, as well as to calculate standard deviation of the azimuthal integration results.
/// </summary>
bool isForceCpu() const;
void setForceCpu(bool const value);
bool forceCpuIsSet() const;
void unsetForce_cpu();
friend void to_json(nlohmann::json& j, const Azim_int_settings& o);
friend void from_json(const nlohmann::json& j, Azim_int_settings& o);
@@ -105,6 +112,8 @@ protected:
int64_t m_Azimuthal_bins;
bool m_Azimuthal_binsIsSet;
bool m_Force_cpu;
bool m_Force_cpuIsSet;
};
@@ -0,0 +1,90 @@
/**
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
#include "Bragg_integration_settings.h"
#include "Helpers.h"
#include <sstream>
namespace org::openapitools::server::model
{
Bragg_integration_settings::Bragg_integration_settings()
{
}
void Bragg_integration_settings::validate() const
{
std::stringstream msg;
if (!validate(msg))
{
throw org::openapitools::server::helpers::ValidationException(msg.str());
}
}
bool Bragg_integration_settings::validate(std::stringstream& msg) const
{
return validate(msg, "");
}
bool Bragg_integration_settings::validate(std::stringstream& msg, const std::string& pathPrefix) const
{
bool success = true;
const std::string _pathPrefix = pathPrefix.empty() ? "Bragg_integration_settings" : pathPrefix;
return success;
}
bool Bragg_integration_settings::operator==(const Bragg_integration_settings& rhs) const
{
return
(getIntegrationModel() == rhs.getIntegrationModel())
;
}
bool Bragg_integration_settings::operator!=(const Bragg_integration_settings& rhs) const
{
return !(*this == rhs);
}
void to_json(nlohmann::json& j, const Bragg_integration_settings& o)
{
j = nlohmann::json::object();
j["integration_model"] = o.m_Integration_model;
}
void from_json(const nlohmann::json& j, Bragg_integration_settings& o)
{
j.at("integration_model").get_to(o.m_Integration_model);
}
org::openapitools::server::model::Integration_model Bragg_integration_settings::getIntegrationModel() const
{
return m_Integration_model;
}
void Bragg_integration_settings::setIntegrationModel(org::openapitools::server::model::Integration_model const& value)
{
m_Integration_model = value;
}
} // namespace org::openapitools::server::model
@@ -0,0 +1,77 @@
/**
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
/*
* Bragg_integration_settings.h
*
* Settings for Bragg spot integration
*/
#ifndef Bragg_integration_settings_H_
#define Bragg_integration_settings_H_
#include "Integration_model.h"
#include <nlohmann/json.hpp>
namespace org::openapitools::server::model
{
/// <summary>
/// Settings for Bragg spot integration
/// </summary>
class Bragg_integration_settings
{
public:
Bragg_integration_settings();
virtual ~Bragg_integration_settings() = default;
/// <summary>
/// Validate the current data in the model. Throws a ValidationException on failure.
/// </summary>
void validate() const;
/// <summary>
/// Validate the current data in the model. Returns false on error and writes an error
/// message into the given stringstream.
/// </summary>
bool validate(std::stringstream& msg) const;
/// <summary>
/// Helper overload for validate. Used when one model stores another model and calls it's validate.
/// Not meant to be called outside that case.
/// </summary>
bool validate(std::stringstream& msg, const std::string& pathPrefix) const;
bool operator==(const Bragg_integration_settings& rhs) const;
bool operator!=(const Bragg_integration_settings& rhs) const;
/////////////////////////////////////////////
/// Bragg_integration_settings members
/// <summary>
///
/// </summary>
org::openapitools::server::model::Integration_model getIntegrationModel() const;
void setIntegrationModel(org::openapitools::server::model::Integration_model const& value);
friend void to_json(nlohmann::json& j, const Bragg_integration_settings& o);
friend void from_json(const nlohmann::json& j, Bragg_integration_settings& o);
protected:
org::openapitools::server::model::Integration_model m_Integration_model;
};
} // namespace org::openapitools::server::model
#endif /* Bragg_integration_settings_H_ */
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+60 -3
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -80,10 +80,13 @@ Dataset_settings::Dataset_settings()
m_Unit_cellIsSet = false;
m_Spot_finding = true;
m_Spot_findingIsSet = false;
m_SmargonIsSet = false;
m_Max_spot_count = 250;
m_Max_spot_countIsSet = false;
m_Detect_ice_rings = false;
m_Detect_ice_ringsIsSet = false;
m_Async_start = false;
m_Async_startIsSet = false;
m_Xray_fluorescence_spectrumIsSet = false;
}
@@ -404,7 +407,7 @@ bool Dataset_settings::validate(std::stringstream& msg, const std::string& pathP
}
}
if (maxSpotCountIsSet())
{
const int32_t& value = m_Max_spot_count;
@@ -423,7 +426,7 @@ bool Dataset_settings::validate(std::stringstream& msg, const std::string& pathP
}
}
return success;
}
@@ -535,12 +538,18 @@ bool Dataset_settings::operator==(const Dataset_settings& rhs) const
((!spotFindingIsSet() && !rhs.spotFindingIsSet()) || (spotFindingIsSet() && rhs.spotFindingIsSet() && isSpotFinding() == rhs.isSpotFinding())) &&
((!smargonIsSet() && !rhs.smargonIsSet()) || (smargonIsSet() && rhs.smargonIsSet() && getSmargon() == rhs.getSmargon())) &&
((!maxSpotCountIsSet() && !rhs.maxSpotCountIsSet()) || (maxSpotCountIsSet() && rhs.maxSpotCountIsSet() && getMaxSpotCount() == rhs.getMaxSpotCount())) &&
((!detectIceRingsIsSet() && !rhs.detectIceRingsIsSet()) || (detectIceRingsIsSet() && rhs.detectIceRingsIsSet() && isDetectIceRings() == rhs.isDetectIceRings())) &&
((!asyncStartIsSet() && !rhs.asyncStartIsSet()) || (asyncStartIsSet() && rhs.asyncStartIsSet() && isAsyncStart() == rhs.isAsyncStart())) &&
((!xrayFluorescenceSpectrumIsSet() && !rhs.xrayFluorescenceSpectrumIsSet()) || (xrayFluorescenceSpectrumIsSet() && rhs.xrayFluorescenceSpectrumIsSet() && getXrayFluorescenceSpectrum() == rhs.getXrayFluorescenceSpectrum()))
;
@@ -618,10 +627,14 @@ void to_json(nlohmann::json& j, const Dataset_settings& o)
j["unit_cell"] = o.m_Unit_cell;
if(o.spotFindingIsSet())
j["spot_finding"] = o.m_Spot_finding;
if(o.smargonIsSet())
j["smargon"] = o.m_Smargon;
if(o.maxSpotCountIsSet())
j["max_spot_count"] = o.m_Max_spot_count;
if(o.detectIceRingsIsSet())
j["detect_ice_rings"] = o.m_Detect_ice_rings;
if(o.asyncStartIsSet())
j["async_start"] = o.m_Async_start;
if(o.xrayFluorescenceSpectrumIsSet())
j["xray_fluorescence_spectrum"] = o.m_Xray_fluorescence_spectrum;
@@ -783,6 +796,11 @@ void from_json(const nlohmann::json& j, Dataset_settings& o)
j.at("spot_finding").get_to(o.m_Spot_finding);
o.m_Spot_findingIsSet = true;
}
if(j.find("smargon") != j.end())
{
j.at("smargon").get_to(o.m_Smargon);
o.m_SmargonIsSet = true;
}
if(j.find("max_spot_count") != j.end())
{
j.at("max_spot_count").get_to(o.m_Max_spot_count);
@@ -793,6 +811,11 @@ void from_json(const nlohmann::json& j, Dataset_settings& o)
j.at("detect_ice_rings").get_to(o.m_Detect_ice_rings);
o.m_Detect_ice_ringsIsSet = true;
}
if(j.find("async_start") != j.end())
{
j.at("async_start").get_to(o.m_Async_start);
o.m_Async_startIsSet = true;
}
if(j.find("xray_fluorescence_spectrum") != j.end())
{
j.at("xray_fluorescence_spectrum").get_to(o.m_Xray_fluorescence_spectrum);
@@ -1343,6 +1366,23 @@ void Dataset_settings::unsetSpot_finding()
{
m_Spot_findingIsSet = false;
}
org::openapitools::server::model::Dataset_settings_smargon Dataset_settings::getSmargon() const
{
return m_Smargon;
}
void Dataset_settings::setSmargon(org::openapitools::server::model::Dataset_settings_smargon const& value)
{
m_Smargon = value;
m_SmargonIsSet = true;
}
bool Dataset_settings::smargonIsSet() const
{
return m_SmargonIsSet;
}
void Dataset_settings::unsetSmargon()
{
m_SmargonIsSet = false;
}
int32_t Dataset_settings::getMaxSpotCount() const
{
return m_Max_spot_count;
@@ -1377,6 +1417,23 @@ void Dataset_settings::unsetDetect_ice_rings()
{
m_Detect_ice_ringsIsSet = false;
}
bool Dataset_settings::isAsyncStart() const
{
return m_Async_start;
}
void Dataset_settings::setAsyncStart(bool const value)
{
m_Async_start = value;
m_Async_startIsSet = true;
}
bool Dataset_settings::asyncStartIsSet() const
{
return m_Async_startIsSet;
}
void Dataset_settings::unsetAsync_start()
{
m_Async_startIsSet = false;
}
org::openapitools::server::model::Dataset_settings_xray_fluorescence_spectrum Dataset_settings::getXrayFluorescenceSpectrum() const
{
return m_Xray_fluorescence_spectrum;
+21 -2
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -21,6 +21,7 @@
#include "Grid_scan.h"
#include <nlohmann/json.hpp>
#include "Dataset_settings_smargon.h"
#include "Rotation_axis.h"
#include "Unit_cell.h"
#include <string>
@@ -168,7 +169,7 @@ public:
bool gridScanIsSet() const;
void unsetGrid_scan();
/// <summary>
/// Header appendix, added as user_data/user to start ZeroMQ message (can be any valid JSON) In general, it is not saved in HDF5 file. However, if values are placed in \&quot;hdf5\&quot; object, &#x60;jfjoch_writer&#x60; will write them in /entry/data of the HDF5 file. This applies solely to string and number (double floating-point). No arrays/sub-objects is allowed. For example {\&quot;hdf5\&quot;: {\&quot;val1\&quot;:1, \&quot;val2\&quot;:\&quot;xyz\&quot;}}, will write /entry/user/val1 and /entry/user/val2.
/// Header appendix, added as user_data/user to start ZeroMQ message (can be any valid JSON) In general, it is not saved in HDF5 file. However, if values are placed in \&quot;hdf5\&quot; object, &#x60;jfjoch_writer&#x60; will write them in /entry/user of the HDF5 file. This applies solely to string and number (double floating-point). No arrays/sub-objects is allowed. For example {\&quot;hdf5\&quot;: {\&quot;val1\&quot;:1, \&quot;val2\&quot;:\&quot;xyz\&quot;}}, will write /entry/user/val1 and /entry/user/val2.
/// </summary>
nlohmann::json getHeaderAppendix() const;
void setHeaderAppendix(nlohmann::json const& value);
@@ -294,6 +295,13 @@ public:
bool spotFindingIsSet() const;
void unsetSpot_finding();
/// <summary>
///
/// </summary>
org::openapitools::server::model::Dataset_settings_smargon getSmargon() const;
void setSmargon(org::openapitools::server::model::Dataset_settings_smargon const& value);
bool smargonIsSet() const;
void unsetSmargon();
/// <summary>
/// Maximum number of spots that are saved/used for indexing; spots with highest intensity are selected
/// </summary>
int32_t getMaxSpotCount() const;
@@ -308,6 +316,13 @@ public:
bool detectIceRingsIsSet() const;
void unsetDetect_ice_rings();
/// <summary>
/// When set to true, &#x60;/start&#x60; will not wait for detector and Jungfraujoch to be ready for the measurement.
/// </summary>
bool isAsyncStart() const;
void setAsyncStart(bool const value);
bool asyncStartIsSet() const;
void unsetAsync_start();
/// <summary>
///
/// </summary>
org::openapitools::server::model::Dataset_settings_xray_fluorescence_spectrum getXrayFluorescenceSpectrum() const;
@@ -386,10 +401,14 @@ protected:
bool m_Unit_cellIsSet;
bool m_Spot_finding;
bool m_Spot_findingIsSet;
org::openapitools::server::model::Dataset_settings_smargon m_Smargon;
bool m_SmargonIsSet;
int32_t m_Max_spot_count;
bool m_Max_spot_countIsSet;
bool m_Detect_ice_rings;
bool m_Detect_ice_ringsIsSet;
bool m_Async_start;
bool m_Async_startIsSet;
org::openapitools::server::model::Dataset_settings_xray_fluorescence_spectrum m_Xray_fluorescence_spectrum;
bool m_Xray_fluorescence_spectrumIsSet;
@@ -0,0 +1,242 @@
/**
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
#include "Dataset_settings_smargon.h"
#include "Helpers.h"
#include <sstream>
namespace org::openapitools::server::model
{
Dataset_settings_smargon::Dataset_settings_smargon()
{
m_Phi_deg = 0.0f;
m_Chi_deg = 0.0f;
m_Phi_axisIsSet = false;
m_Chi_axisIsSet = false;
}
void Dataset_settings_smargon::validate() const
{
std::stringstream msg;
if (!validate(msg))
{
throw org::openapitools::server::helpers::ValidationException(msg.str());
}
}
bool Dataset_settings_smargon::validate(std::stringstream& msg) const
{
return validate(msg, "");
}
bool Dataset_settings_smargon::validate(std::stringstream& msg, const std::string& pathPrefix) const
{
bool success = true;
const std::string _pathPrefix = pathPrefix.empty() ? "Dataset_settings_smargon" : pathPrefix;
/* Chi_deg */ {
const float& value = m_Chi_deg;
const std::string currentValuePath = _pathPrefix + ".chiDeg";
if (value < static_cast<float>(0.0))
{
success = false;
msg << currentValuePath << ": must be greater than or equal to 0.0;";
}
if (value > static_cast<float>(90.0))
{
success = false;
msg << currentValuePath << ": must be less than or equal to 90.0;";
}
}
if (phiAxisIsSet())
{
const std::vector<float>& value = m_Phi_axis;
const std::string currentValuePath = _pathPrefix + ".phiAxis";
if (value.size() < 3)
{
success = false;
msg << currentValuePath << ": must have at least 3 elements;";
}
if (value.size() > 3)
{
success = false;
msg << currentValuePath << ": must have at most 3 elements;";
}
{ // Recursive validation of array elements
const std::string oldValuePath = currentValuePath;
int i = 0;
for (const float& value : value)
{
const std::string currentValuePath = oldValuePath + "[" + std::to_string(i) + "]";
i++;
}
}
}
if (chiAxisIsSet())
{
const std::vector<float>& value = m_Chi_axis;
const std::string currentValuePath = _pathPrefix + ".chiAxis";
if (value.size() < 3)
{
success = false;
msg << currentValuePath << ": must have at least 3 elements;";
}
if (value.size() > 3)
{
success = false;
msg << currentValuePath << ": must have at most 3 elements;";
}
{ // Recursive validation of array elements
const std::string oldValuePath = currentValuePath;
int i = 0;
for (const float& value : value)
{
const std::string currentValuePath = oldValuePath + "[" + std::to_string(i) + "]";
i++;
}
}
}
return success;
}
bool Dataset_settings_smargon::operator==(const Dataset_settings_smargon& rhs) const
{
return
(getPhiDeg() == rhs.getPhiDeg())
&&
(getChiDeg() == rhs.getChiDeg())
&&
((!phiAxisIsSet() && !rhs.phiAxisIsSet()) || (phiAxisIsSet() && rhs.phiAxisIsSet() && getPhiAxis() == rhs.getPhiAxis())) &&
((!chiAxisIsSet() && !rhs.chiAxisIsSet()) || (chiAxisIsSet() && rhs.chiAxisIsSet() && getChiAxis() == rhs.getChiAxis()))
;
}
bool Dataset_settings_smargon::operator!=(const Dataset_settings_smargon& rhs) const
{
return !(*this == rhs);
}
void to_json(nlohmann::json& j, const Dataset_settings_smargon& o)
{
j = nlohmann::json::object();
j["phi_deg"] = o.m_Phi_deg;
j["chi_deg"] = o.m_Chi_deg;
if(o.phiAxisIsSet() || !o.m_Phi_axis.empty())
j["phi_axis"] = o.m_Phi_axis;
if(o.chiAxisIsSet() || !o.m_Chi_axis.empty())
j["chi_axis"] = o.m_Chi_axis;
}
void from_json(const nlohmann::json& j, Dataset_settings_smargon& o)
{
j.at("phi_deg").get_to(o.m_Phi_deg);
j.at("chi_deg").get_to(o.m_Chi_deg);
if(j.find("phi_axis") != j.end())
{
j.at("phi_axis").get_to(o.m_Phi_axis);
o.m_Phi_axisIsSet = true;
}
if(j.find("chi_axis") != j.end())
{
j.at("chi_axis").get_to(o.m_Chi_axis);
o.m_Chi_axisIsSet = true;
}
}
float Dataset_settings_smargon::getPhiDeg() const
{
return m_Phi_deg;
}
void Dataset_settings_smargon::setPhiDeg(float const value)
{
m_Phi_deg = value;
}
float Dataset_settings_smargon::getChiDeg() const
{
return m_Chi_deg;
}
void Dataset_settings_smargon::setChiDeg(float const value)
{
m_Chi_deg = value;
}
std::vector<float> Dataset_settings_smargon::getPhiAxis() const
{
return m_Phi_axis;
}
void Dataset_settings_smargon::setPhiAxis(std::vector<float> const value)
{
m_Phi_axis = value;
m_Phi_axisIsSet = true;
}
bool Dataset_settings_smargon::phiAxisIsSet() const
{
return m_Phi_axisIsSet;
}
void Dataset_settings_smargon::unsetPhi_axis()
{
m_Phi_axisIsSet = false;
}
std::vector<float> Dataset_settings_smargon::getChiAxis() const
{
return m_Chi_axis;
}
void Dataset_settings_smargon::setChiAxis(std::vector<float> const value)
{
m_Chi_axis = value;
m_Chi_axisIsSet = true;
}
bool Dataset_settings_smargon::chiAxisIsSet() const
{
return m_Chi_axisIsSet;
}
void Dataset_settings_smargon::unsetChi_axis()
{
m_Chi_axisIsSet = false;
}
} // namespace org::openapitools::server::model
+102
View File
@@ -0,0 +1,102 @@
/**
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
/*
* Dataset_settings_smargon.h
*
* Geometry of Smargon goniometer at SLS 2.0 / MX beamlines. Assuming that Smargon is used as static positioner and not moving during the scan, allowing to reconstruct geometry.
*/
#ifndef Dataset_settings_smargon_H_
#define Dataset_settings_smargon_H_
#include <vector>
#include <nlohmann/json.hpp>
namespace org::openapitools::server::model
{
/// <summary>
/// Geometry of Smargon goniometer at SLS 2.0 / MX beamlines. Assuming that Smargon is used as static positioner and not moving during the scan, allowing to reconstruct geometry.
/// </summary>
class Dataset_settings_smargon
{
public:
Dataset_settings_smargon();
virtual ~Dataset_settings_smargon() = default;
/// <summary>
/// Validate the current data in the model. Throws a ValidationException on failure.
/// </summary>
void validate() const;
/// <summary>
/// Validate the current data in the model. Returns false on error and writes an error
/// message into the given stringstream.
/// </summary>
bool validate(std::stringstream& msg) const;
/// <summary>
/// Helper overload for validate. Used when one model stores another model and calls it's validate.
/// Not meant to be called outside that case.
/// </summary>
bool validate(std::stringstream& msg, const std::string& pathPrefix) const;
bool operator==(const Dataset_settings_smargon& rhs) const;
bool operator!=(const Dataset_settings_smargon& rhs) const;
/////////////////////////////////////////////
/// Dataset_settings_smargon members
/// <summary>
/// Phi angle in degrees
/// </summary>
float getPhiDeg() const;
void setPhiDeg(float const value);
/// <summary>
/// Chi angle in degrees
/// </summary>
float getChiDeg() const;
void setChiDeg(float const value);
/// <summary>
/// Phi rotation axis
/// </summary>
std::vector<float> getPhiAxis() const;
void setPhiAxis(std::vector<float> const value);
bool phiAxisIsSet() const;
void unsetPhi_axis();
/// <summary>
/// Chi rotation axis
/// </summary>
std::vector<float> getChiAxis() const;
void setChiAxis(std::vector<float> const value);
bool chiAxisIsSet() const;
void unsetChi_axis();
friend void to_json(nlohmann::json& j, const Dataset_settings_smargon& o);
friend void from_json(const nlohmann::json& j, Dataset_settings_smargon& o);
protected:
float m_Phi_deg;
float m_Chi_deg;
std::vector<float> m_Phi_axis;
bool m_Phi_axisIsSet;
std::vector<float> m_Chi_axis;
bool m_Chi_axisIsSet;
};
} // namespace org::openapitools::server::model
#endif /* Dataset_settings_smargon_H_ */
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+115 -61
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -33,13 +33,14 @@ Detector::Detector()
m_Module_syncIsSet = false;
m_Sensor_thickness_um = 320.0f;
m_Sensor_thickness_umIsSet = false;
m_Readout_time_us = 0L;
m_Readout_time_usIsSet = false;
m_Minimum_count_time_us = 0L;
m_Minimum_count_time_usIsSet = false;
m_Minimum_frame_time_us = 0L;
m_Minimum_frame_time_usIsSet = false;
m_Readout_time_ns = 0L;
m_Readout_time_nsIsSet = false;
m_Min_count_time_ns = 0L;
m_Min_count_time_nsIsSet = false;
m_Min_frame_time_ns = 0L;
m_Min_frame_time_nsIsSet = false;
m_Calibration_fileIsSet = false;
m_Trim_energies_eVIsSet = false;
m_HostnameIsSet = false;
m_Sensor_material = "Si";
m_Sensor_materialIsSet = false;
@@ -158,10 +159,10 @@ bool Detector::validate(std::stringstream& msg, const std::string& pathPrefix) c
}
if (readoutTimeUsIsSet())
if (readoutTimeNsIsSet())
{
const int64_t& value = m_Readout_time_us;
const std::string currentValuePath = _pathPrefix + ".readoutTimeUs";
const int64_t& value = m_Readout_time_ns;
const std::string currentValuePath = _pathPrefix + ".readoutTimeNs";
if (value < 1ll)
@@ -172,10 +173,10 @@ bool Detector::validate(std::stringstream& msg, const std::string& pathPrefix) c
}
if (minimumCountTimeUsIsSet())
if (minCountTimeNsIsSet())
{
const int64_t& value = m_Minimum_count_time_us;
const std::string currentValuePath = _pathPrefix + ".minimumCountTimeUs";
const int64_t& value = m_Min_count_time_ns;
const std::string currentValuePath = _pathPrefix + ".minCountTimeNs";
if (value < 0ll)
@@ -186,10 +187,10 @@ bool Detector::validate(std::stringstream& msg, const std::string& pathPrefix) c
}
if (minimumFrameTimeUsIsSet())
if (minFrameTimeNsIsSet())
{
const int64_t& value = m_Minimum_frame_time_us;
const std::string currentValuePath = _pathPrefix + ".minimumFrameTimeUs";
const int64_t& value = m_Min_frame_time_ns;
const std::string currentValuePath = _pathPrefix + ".minFrameTimeNs";
if (value < 0ll)
@@ -221,6 +222,32 @@ bool Detector::validate(std::stringstream& msg, const std::string& pathPrefix) c
}
if (trimEnergiesEVIsSet())
{
const std::vector<int32_t>& value = m_Trim_energies_eV;
const std::string currentValuePath = _pathPrefix + ".trimEnergiesEV";
{ // Recursive validation of array elements
const std::string oldValuePath = currentValuePath;
int i = 0;
for (const int32_t& value : value)
{
const std::string currentValuePath = oldValuePath + "[" + std::to_string(i) + "]";
if (value < 100)
{
success = false;
msg << currentValuePath << ": must be greater than or equal to 100;";
}
i++;
}
}
}
if (hostnameIsSet())
{
const std::vector<std::string>& value = m_Hostname;
@@ -333,18 +360,21 @@ bool Detector::operator==(const Detector& rhs) const
((!sensorThicknessUmIsSet() && !rhs.sensorThicknessUmIsSet()) || (sensorThicknessUmIsSet() && rhs.sensorThicknessUmIsSet() && getSensorThicknessUm() == rhs.getSensorThicknessUm())) &&
((!readoutTimeUsIsSet() && !rhs.readoutTimeUsIsSet()) || (readoutTimeUsIsSet() && rhs.readoutTimeUsIsSet() && getReadoutTimeUs() == rhs.getReadoutTimeUs())) &&
((!readoutTimeNsIsSet() && !rhs.readoutTimeNsIsSet()) || (readoutTimeNsIsSet() && rhs.readoutTimeNsIsSet() && getReadoutTimeNs() == rhs.getReadoutTimeNs())) &&
((!minimumCountTimeUsIsSet() && !rhs.minimumCountTimeUsIsSet()) || (minimumCountTimeUsIsSet() && rhs.minimumCountTimeUsIsSet() && getMinimumCountTimeUs() == rhs.getMinimumCountTimeUs())) &&
((!minCountTimeNsIsSet() && !rhs.minCountTimeNsIsSet()) || (minCountTimeNsIsSet() && rhs.minCountTimeNsIsSet() && getMinCountTimeNs() == rhs.getMinCountTimeNs())) &&
((!minimumFrameTimeUsIsSet() && !rhs.minimumFrameTimeUsIsSet()) || (minimumFrameTimeUsIsSet() && rhs.minimumFrameTimeUsIsSet() && getMinimumFrameTimeUs() == rhs.getMinimumFrameTimeUs())) &&
((!minFrameTimeNsIsSet() && !rhs.minFrameTimeNsIsSet()) || (minFrameTimeNsIsSet() && rhs.minFrameTimeNsIsSet() && getMinFrameTimeNs() == rhs.getMinFrameTimeNs())) &&
((!calibrationFileIsSet() && !rhs.calibrationFileIsSet()) || (calibrationFileIsSet() && rhs.calibrationFileIsSet() && getCalibrationFile() == rhs.getCalibrationFile())) &&
((!trimEnergiesEVIsSet() && !rhs.trimEnergiesEVIsSet()) || (trimEnergiesEVIsSet() && rhs.trimEnergiesEVIsSet() && getTrimEnergiesEV() == rhs.getTrimEnergiesEV())) &&
((!hostnameIsSet() && !rhs.hostnameIsSet()) || (hostnameIsSet() && rhs.hostnameIsSet() && getHostname() == rhs.getHostname())) &&
@@ -398,14 +428,16 @@ void to_json(nlohmann::json& j, const Detector& o)
j["module_sync"] = o.m_Module_sync;
if(o.sensorThicknessUmIsSet())
j["sensor_thickness_um"] = o.m_Sensor_thickness_um;
if(o.readoutTimeUsIsSet())
j["readout_time_us"] = o.m_Readout_time_us;
if(o.minimumCountTimeUsIsSet())
j["minimum_count_time_us"] = o.m_Minimum_count_time_us;
if(o.minimumFrameTimeUsIsSet())
j["minimum_frame_time_us"] = o.m_Minimum_frame_time_us;
if(o.readoutTimeNsIsSet())
j["readout_time_ns"] = o.m_Readout_time_ns;
if(o.minCountTimeNsIsSet())
j["min_count_time_ns"] = o.m_Min_count_time_ns;
if(o.minFrameTimeNsIsSet())
j["min_frame_time_ns"] = o.m_Min_frame_time_ns;
if(o.calibrationFileIsSet() || !o.m_Calibration_file.empty())
j["calibration_file"] = o.m_Calibration_file;
if(o.trimEnergiesEVIsSet() || !o.m_Trim_energies_eV.empty())
j["trim_energies_eV"] = o.m_Trim_energies_eV;
if(o.hostnameIsSet() || !o.m_Hostname.empty())
j["hostname"] = o.m_Hostname;
if(o.sensorMaterialIsSet())
@@ -462,26 +494,31 @@ void from_json(const nlohmann::json& j, Detector& o)
j.at("sensor_thickness_um").get_to(o.m_Sensor_thickness_um);
o.m_Sensor_thickness_umIsSet = true;
}
if(j.find("readout_time_us") != j.end())
if(j.find("readout_time_ns") != j.end())
{
j.at("readout_time_us").get_to(o.m_Readout_time_us);
o.m_Readout_time_usIsSet = true;
j.at("readout_time_ns").get_to(o.m_Readout_time_ns);
o.m_Readout_time_nsIsSet = true;
}
if(j.find("minimum_count_time_us") != j.end())
if(j.find("min_count_time_ns") != j.end())
{
j.at("minimum_count_time_us").get_to(o.m_Minimum_count_time_us);
o.m_Minimum_count_time_usIsSet = true;
j.at("min_count_time_ns").get_to(o.m_Min_count_time_ns);
o.m_Min_count_time_nsIsSet = true;
}
if(j.find("minimum_frame_time_us") != j.end())
if(j.find("min_frame_time_ns") != j.end())
{
j.at("minimum_frame_time_us").get_to(o.m_Minimum_frame_time_us);
o.m_Minimum_frame_time_usIsSet = true;
j.at("min_frame_time_ns").get_to(o.m_Min_frame_time_ns);
o.m_Min_frame_time_nsIsSet = true;
}
if(j.find("calibration_file") != j.end())
{
j.at("calibration_file").get_to(o.m_Calibration_file);
o.m_Calibration_fileIsSet = true;
}
if(j.find("trim_energies_eV") != j.end())
{
j.at("trim_energies_eV").get_to(o.m_Trim_energies_eV);
o.m_Trim_energies_eVIsSet = true;
}
if(j.find("hostname") != j.end())
{
j.at("hostname").get_to(o.m_Hostname);
@@ -645,56 +682,56 @@ void Detector::unsetSensor_thickness_um()
{
m_Sensor_thickness_umIsSet = false;
}
int64_t Detector::getReadoutTimeUs() const
int64_t Detector::getReadoutTimeNs() const
{
return m_Readout_time_us;
return m_Readout_time_ns;
}
void Detector::setReadoutTimeUs(int64_t const value)
void Detector::setReadoutTimeNs(int64_t const value)
{
m_Readout_time_us = value;
m_Readout_time_usIsSet = true;
m_Readout_time_ns = value;
m_Readout_time_nsIsSet = true;
}
bool Detector::readoutTimeUsIsSet() const
bool Detector::readoutTimeNsIsSet() const
{
return m_Readout_time_usIsSet;
return m_Readout_time_nsIsSet;
}
void Detector::unsetReadout_time_us()
void Detector::unsetReadout_time_ns()
{
m_Readout_time_usIsSet = false;
m_Readout_time_nsIsSet = false;
}
int64_t Detector::getMinimumCountTimeUs() const
int64_t Detector::getMinCountTimeNs() const
{
return m_Minimum_count_time_us;
return m_Min_count_time_ns;
}
void Detector::setMinimumCountTimeUs(int64_t const value)
void Detector::setMinCountTimeNs(int64_t const value)
{
m_Minimum_count_time_us = value;
m_Minimum_count_time_usIsSet = true;
m_Min_count_time_ns = value;
m_Min_count_time_nsIsSet = true;
}
bool Detector::minimumCountTimeUsIsSet() const
bool Detector::minCountTimeNsIsSet() const
{
return m_Minimum_count_time_usIsSet;
return m_Min_count_time_nsIsSet;
}
void Detector::unsetMinimum_count_time_us()
void Detector::unsetMin_count_time_ns()
{
m_Minimum_count_time_usIsSet = false;
m_Min_count_time_nsIsSet = false;
}
int64_t Detector::getMinimumFrameTimeUs() const
int64_t Detector::getMinFrameTimeNs() const
{
return m_Minimum_frame_time_us;
return m_Min_frame_time_ns;
}
void Detector::setMinimumFrameTimeUs(int64_t const value)
void Detector::setMinFrameTimeNs(int64_t const value)
{
m_Minimum_frame_time_us = value;
m_Minimum_frame_time_usIsSet = true;
m_Min_frame_time_ns = value;
m_Min_frame_time_nsIsSet = true;
}
bool Detector::minimumFrameTimeUsIsSet() const
bool Detector::minFrameTimeNsIsSet() const
{
return m_Minimum_frame_time_usIsSet;
return m_Min_frame_time_nsIsSet;
}
void Detector::unsetMinimum_frame_time_us()
void Detector::unsetMin_frame_time_ns()
{
m_Minimum_frame_time_usIsSet = false;
m_Min_frame_time_nsIsSet = false;
}
std::vector<std::string> Detector::getCalibrationFile() const
{
@@ -713,6 +750,23 @@ void Detector::unsetCalibration_file()
{
m_Calibration_fileIsSet = false;
}
std::vector<int32_t> Detector::getTrimEnergiesEV() const
{
return m_Trim_energies_eV;
}
void Detector::setTrimEnergiesEV(std::vector<int32_t> const value)
{
m_Trim_energies_eV = value;
m_Trim_energies_eVIsSet = true;
}
bool Detector::trimEnergiesEVIsSet() const
{
return m_Trim_energies_eVIsSet;
}
void Detector::unsetTrim_energies_eV()
{
m_Trim_energies_eVIsSet = false;
}
std::vector<std::string> Detector::getHostname() const
{
return m_Hostname;
+29 -20
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -111,26 +111,26 @@ public:
bool sensorThicknessUmIsSet() const;
void unsetSensor_thickness_um();
/// <summary>
/// Minimum difference between frame time and count time in microseconds Defaults are 3 us for EIGER and 20 us for JUNGFRAU
/// Minimum difference between frame time and count time in microseconds Defaults are 3&#39;000 ns for EIGER and 20&#39;000 ns for JUNGFRAU
/// </summary>
int64_t getReadoutTimeUs() const;
void setReadoutTimeUs(int64_t const value);
bool readoutTimeUsIsSet() const;
void unsetReadout_time_us();
int64_t getReadoutTimeNs() const;
void setReadoutTimeNs(int64_t const value);
bool readoutTimeNsIsSet() const;
void unsetReadout_time_ns();
/// <summary>
/// Minimum count time available for the detector.
/// </summary>
int64_t getMinimumCountTimeUs() const;
void setMinimumCountTimeUs(int64_t const value);
bool minimumCountTimeUsIsSet() const;
void unsetMinimum_count_time_us();
int64_t getMinCountTimeNs() const;
void setMinCountTimeNs(int64_t const value);
bool minCountTimeNsIsSet() const;
void unsetMin_count_time_ns();
/// <summary>
/// Minimum frame time available for the detector.
/// </summary>
int64_t getMinimumFrameTimeUs() const;
void setMinimumFrameTimeUs(int64_t const value);
bool minimumFrameTimeUsIsSet() const;
void unsetMinimum_frame_time_us();
int64_t getMinFrameTimeNs() const;
void setMinFrameTimeNs(int64_t const value);
bool minFrameTimeNsIsSet() const;
void unsetMin_frame_time_ns();
/// <summary>
/// Can be empty for all detectors - default calibration used. For JUNGFRAU: list of gain files, one entry per module. For EIGER: one directory (with detector settings) or list of trim bit files, one entry per half-module.
/// </summary>
@@ -139,6 +139,13 @@ public:
bool calibrationFileIsSet() const;
void unsetCalibration_file();
/// <summary>
/// List of energies at which trimming calibration is provided. Only needed for PSI EIGER and compulsory in this case
/// </summary>
std::vector<int32_t> getTrimEnergiesEV() const;
void setTrimEnergiesEV(std::vector<int32_t> const value);
bool trimEnergiesEVIsSet() const;
void unsetTrim_energies_eV();
/// <summary>
/// Hostname for detector module. One entry per module One entry per module. Either empty or number of module entries.
/// </summary>
std::vector<std::string> getHostname() const;
@@ -226,14 +233,16 @@ protected:
bool m_Module_syncIsSet;
float m_Sensor_thickness_um;
bool m_Sensor_thickness_umIsSet;
int64_t m_Readout_time_us;
bool m_Readout_time_usIsSet;
int64_t m_Minimum_count_time_us;
bool m_Minimum_count_time_usIsSet;
int64_t m_Minimum_frame_time_us;
bool m_Minimum_frame_time_usIsSet;
int64_t m_Readout_time_ns;
bool m_Readout_time_nsIsSet;
int64_t m_Min_count_time_ns;
bool m_Min_count_time_nsIsSet;
int64_t m_Min_frame_time_ns;
bool m_Min_frame_time_nsIsSet;
std::vector<std::string> m_Calibration_file;
bool m_Calibration_fileIsSet;
std::vector<int32_t> m_Trim_energies_eV;
bool m_Trim_energies_eVIsSet;
std::vector<std::string> m_Hostname;
bool m_HostnameIsSet;
std::string m_Sensor_material;
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+25 -25
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -31,9 +31,9 @@ Detector_list_element::Detector_list_element()
m_Height = 0L;
m_Pixel_size_mm = 0.0f;
m_Pixel_size_mmIsSet = false;
m_Readout_time_us = 0L;
m_Min_frame_time_us = 0L;
m_Min_count_time_us = 0L;
m_Readout_time_ns = 0L;
m_Min_frame_time_ns = 0L;
m_Min_count_time_ns = 0L;
m_TypeIsSet = false;
}
@@ -107,13 +107,13 @@ bool Detector_list_element::operator==(const Detector_list_element& rhs) const
((!pixelSizeMmIsSet() && !rhs.pixelSizeMmIsSet()) || (pixelSizeMmIsSet() && rhs.pixelSizeMmIsSet() && getPixelSizeMm() == rhs.getPixelSizeMm())) &&
(getReadoutTimeUs() == rhs.getReadoutTimeUs())
(getReadoutTimeNs() == rhs.getReadoutTimeNs())
&&
(getMinFrameTimeUs() == rhs.getMinFrameTimeUs())
(getMinFrameTimeNs() == rhs.getMinFrameTimeNs())
&&
(getMinCountTimeUs() == rhs.getMinCountTimeUs())
(getMinCountTimeNs() == rhs.getMinCountTimeNs())
&&
@@ -140,9 +140,9 @@ void to_json(nlohmann::json& j, const Detector_list_element& o)
j["height"] = o.m_Height;
if(o.pixelSizeMmIsSet())
j["pixel_size_mm"] = o.m_Pixel_size_mm;
j["readout_time_us"] = o.m_Readout_time_us;
j["min_frame_time_us"] = o.m_Min_frame_time_us;
j["min_count_time_us"] = o.m_Min_count_time_us;
j["readout_time_ns"] = o.m_Readout_time_ns;
j["min_frame_time_ns"] = o.m_Min_frame_time_ns;
j["min_count_time_ns"] = o.m_Min_count_time_ns;
if(o.typeIsSet())
j["type"] = o.m_Type;
@@ -163,9 +163,9 @@ void from_json(const nlohmann::json& j, Detector_list_element& o)
j.at("pixel_size_mm").get_to(o.m_Pixel_size_mm);
o.m_Pixel_size_mmIsSet = true;
}
j.at("readout_time_us").get_to(o.m_Readout_time_us);
j.at("min_frame_time_us").get_to(o.m_Min_frame_time_us);
j.at("min_count_time_us").get_to(o.m_Min_count_time_us);
j.at("readout_time_ns").get_to(o.m_Readout_time_ns);
j.at("min_frame_time_ns").get_to(o.m_Min_frame_time_ns);
j.at("min_count_time_ns").get_to(o.m_Min_count_time_ns);
if(j.find("type") != j.end())
{
j.at("type").get_to(o.m_Type);
@@ -255,29 +255,29 @@ void Detector_list_element::unsetPixel_size_mm()
{
m_Pixel_size_mmIsSet = false;
}
int64_t Detector_list_element::getReadoutTimeUs() const
int64_t Detector_list_element::getReadoutTimeNs() const
{
return m_Readout_time_us;
return m_Readout_time_ns;
}
void Detector_list_element::setReadoutTimeUs(int64_t const value)
void Detector_list_element::setReadoutTimeNs(int64_t const value)
{
m_Readout_time_us = value;
m_Readout_time_ns = value;
}
int64_t Detector_list_element::getMinFrameTimeUs() const
int64_t Detector_list_element::getMinFrameTimeNs() const
{
return m_Min_frame_time_us;
return m_Min_frame_time_ns;
}
void Detector_list_element::setMinFrameTimeUs(int64_t const value)
void Detector_list_element::setMinFrameTimeNs(int64_t const value)
{
m_Min_frame_time_us = value;
m_Min_frame_time_ns = value;
}
int64_t Detector_list_element::getMinCountTimeUs() const
int64_t Detector_list_element::getMinCountTimeNs() const
{
return m_Min_count_time_us;
return m_Min_count_time_ns;
}
void Detector_list_element::setMinCountTimeUs(int64_t const value)
void Detector_list_element::setMinCountTimeNs(int64_t const value)
{
m_Min_count_time_us = value;
m_Min_count_time_ns = value;
}
org::openapitools::server::model::Detector_type Detector_list_element::getType() const
{
+10 -10
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -109,18 +109,18 @@ public:
/// <summary>
///
/// </summary>
int64_t getReadoutTimeUs() const;
void setReadoutTimeUs(int64_t const value);
int64_t getReadoutTimeNs() const;
void setReadoutTimeNs(int64_t const value);
/// <summary>
///
/// </summary>
int64_t getMinFrameTimeUs() const;
void setMinFrameTimeUs(int64_t const value);
int64_t getMinFrameTimeNs() const;
void setMinFrameTimeNs(int64_t const value);
/// <summary>
///
/// </summary>
int64_t getMinCountTimeUs() const;
void setMinCountTimeUs(int64_t const value);
int64_t getMinCountTimeNs() const;
void setMinCountTimeNs(int64_t const value);
/// <summary>
///
/// </summary>
@@ -150,11 +150,11 @@ protected:
float m_Pixel_size_mm;
bool m_Pixel_size_mmIsSet;
int64_t m_Readout_time_us;
int64_t m_Readout_time_ns;
int64_t m_Min_frame_time_us;
int64_t m_Min_frame_time_ns;
int64_t m_Min_count_time_us;
int64_t m_Min_count_time_ns;
org::openapitools::server::model::Detector_type m_Type;
bool m_TypeIsSet;
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+3 -3
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -12,7 +12,7 @@
/*
* File_writer_format.h
*
* NoFileWritten - no files are written at all NXmxOnlyData - only data files are written, no master file NXmxLegacy - legacy format with soft links to data files in the master file; necessary for DECTRIS Albula 4.0 and DECTRIS Neggia NXmxVDS - newer format with virtual dataset linking data files in the master file, also includes better metadata handling NXmxIntegrated - single HDF5 per dataset CBF - CBF format (limited metadata) TIFF - TIFF format (no metadata)
* NoFileWritten - no files are written at all NXmxOnlyData - only data files are written, no master file NXmxLegacy - legacy format with soft links to data files in the master file; necessary for DECTRIS Albula 4.0 and DECTRIS Neggia NXmxVDS - newer format with virtual dataset linking data files in the master file, also includes better metadata handling NXmxIntegrated - single HDF5 per dataset CBF - DEPRECATED, no longer supported; kept for back compatibility only. Requests using this value are rejected. Only HDF5 formats are written. TIFF - DEPRECATED, no longer supported; kept for back compatibility only. Requests using this value are rejected. Only HDF5 formats are written.
*/
#ifndef File_writer_format_H_
@@ -25,7 +25,7 @@ namespace org::openapitools::server::model
{
/// <summary>
/// NoFileWritten - no files are written at all NXmxOnlyData - only data files are written, no master file NXmxLegacy - legacy format with soft links to data files in the master file; necessary for DECTRIS Albula 4.0 and DECTRIS Neggia NXmxVDS - newer format with virtual dataset linking data files in the master file, also includes better metadata handling NXmxIntegrated - single HDF5 per dataset CBF - CBF format (limited metadata) TIFF - TIFF format (no metadata)
/// NoFileWritten - no files are written at all NXmxOnlyData - only data files are written, no master file NXmxLegacy - legacy format with soft links to data files in the master file; necessary for DECTRIS Albula 4.0 and DECTRIS Neggia NXmxVDS - newer format with virtual dataset linking data files in the master file, also includes better metadata handling NXmxIntegrated - single HDF5 per dataset CBF - DEPRECATED, no longer supported; kept for back compatibility only. Requests using this value are rejected. Only HDF5 formats are written. TIFF - DEPRECATED, no longer supported; kept for back compatibility only. Requests using this value are rejected. Only HDF5 formats are written.
/// </summary>
class File_writer_format
{
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+13 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -78,6 +78,12 @@ void to_json(nlohmann::json& j, const Geom_refinement_algorithm& o)
case Geom_refinement_algorithm::eGeom_refinement_algorithm::BEAMCENTER:
j = "BeamCenter";
break;
case Geom_refinement_algorithm::eGeom_refinement_algorithm::ORIENTATIONONLY:
j = "OrientationOnly";
break;
case Geom_refinement_algorithm::eGeom_refinement_algorithm::FLEX:
j = "Flex";
break;
case Geom_refinement_algorithm::eGeom_refinement_algorithm::NONE:
j = "None";
break;
@@ -91,6 +97,12 @@ void from_json(const nlohmann::json& j, Geom_refinement_algorithm& o)
if (s == "BeamCenter") {
o.setValue(Geom_refinement_algorithm::eGeom_refinement_algorithm::BEAMCENTER);
}
else if (s == "OrientationOnly") {
o.setValue(Geom_refinement_algorithm::eGeom_refinement_algorithm::ORIENTATIONONLY);
}
else if (s == "Flex") {
o.setValue(Geom_refinement_algorithm::eGeom_refinement_algorithm::FLEX);
}
else if (s == "None") {
o.setValue(Geom_refinement_algorithm::eGeom_refinement_algorithm::NONE);
} else {
+5 -3
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
@@ -12,7 +12,7 @@
/*
* Geom_refinement_algorithm.h
*
* Selection of an post-indexing detector geometry refinement algorithm used by Jungfraujoch. This option is using non-linear least squares optimization to find unit cell and beam center.
* Selection of an post-indexing least-square diffraction geometry refinement algorithm used by Jungfraujoch. BeamCenter - This option is refining both beam center and lattice (restricted to a chosen/detected Bravais lattice). OrientationOnly - This option is refining only orientation of the lattice. Flex - Tries all per-image refinements and keeps whichever indexes the most spots, letting the pipeline decide (the rugnux flex mode).
*/
#ifndef Geom_refinement_algorithm_H_
@@ -25,7 +25,7 @@ namespace org::openapitools::server::model
{
/// <summary>
/// Selection of an post-indexing detector geometry refinement algorithm used by Jungfraujoch. This option is using non-linear least squares optimization to find unit cell and beam center.
/// Selection of an post-indexing least-square diffraction geometry refinement algorithm used by Jungfraujoch. BeamCenter - This option is refining both beam center and lattice (restricted to a chosen/detected Bravais lattice). OrientationOnly - This option is refining only orientation of the lattice. Flex - Tries all per-image refinements and keeps whichever indexes the most spots, letting the pipeline decide (the rugnux flex mode).
/// </summary>
class Geom_refinement_algorithm
{
@@ -39,6 +39,8 @@ public:
// enum values
INVALID_VALUE_OPENAPI_GENERATED = 0,
BEAMCENTER,
ORIENTATIONONLY,
FLEX,
NONE
};
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+1 -1
View File
@@ -2,7 +2,7 @@
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.136
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+122
View File
@@ -0,0 +1,122 @@
/**
* Jungfraujoch
* API to control Jungfraujoch developed by the Paul Scherrer Institute (Switzerland). Jungfraujoch is a data acquisition and analysis system for pixel array detectors, primarly PSI JUNGFRAU. Jungfraujoch uses FPGA boards to acquire data at high data rates. # License Clarification While this API definition is licensed under GPL-3.0, **the GPL copyleft provisions do not apply** when this file is used solely to generate OpenAPI clients or when implementing applications that interact with the API. Generated client code and applications using this API definition are not subject to the GPL license requirements and may be distributed under terms of your choosing. This exception is similar in spirit to the Linux Kernel's approach to userspace API headers and the GCC Runtime Library Exception. The Linux Kernel developers have explicitly stated that user programs that merely use the kernel interfaces (syscalls, ioctl definitions, etc.) are not derivative works of the kernel and are not subject to the terms of the GPL. This exception is intended to allow wider use of this API specification without imposing GPL requirements on applications that merely interact with the API, regardless of whether they communicate through network calls or other mechanisms.
*
* The version of the OpenAPI document: 1.0.0-rc.160
* Contact: filip.leonarski@psi.ch
*
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
* https://openapi-generator.tech
* Do not edit the class manually.
*/
#include "Integration_model.h"
#include "Helpers.h"
#include <stdexcept>
#include <sstream>
namespace org::openapitools::server::model
{
Integration_model::Integration_model()
{
}
void Integration_model::validate() const
{
std::stringstream msg;
if (!validate(msg))
{
throw org::openapitools::server::helpers::ValidationException(msg.str());
}
}
bool Integration_model::validate(std::stringstream& msg) const
{
return validate(msg, "");
}
bool Integration_model::validate(std::stringstream& msg, const std::string& pathPrefix) const
{
bool success = true;
const std::string _pathPrefix = pathPrefix.empty() ? "Integration_model" : pathPrefix;
if (m_value == Integration_model::eIntegration_model::INVALID_VALUE_OPENAPI_GENERATED)
{
success = false;
msg << _pathPrefix << ": has no value;";
}
return success;
}
bool Integration_model::operator==(const Integration_model& rhs) const
{
return
getValue() == rhs.getValue()
;
}
bool Integration_model::operator!=(const Integration_model& rhs) const
{
return !(*this == rhs);
}
void to_json(nlohmann::json& j, const Integration_model& o)
{
j = nlohmann::json::object();
switch (o.getValue())
{
case Integration_model::eIntegration_model::INVALID_VALUE_OPENAPI_GENERATED:
j = "INVALID_VALUE_OPENAPI_GENERATED";
break;
case Integration_model::eIntegration_model::PROFILEGAUSSIAN:
j = "ProfileGaussian";
break;
case Integration_model::eIntegration_model::PROFILEEMPIRICAL:
j = "ProfileEmpirical";
break;
case Integration_model::eIntegration_model::BOXSUM:
j = "BoxSum";
break;
}
}
void from_json(const nlohmann::json& j, Integration_model& o)
{
auto s = j.get<std::string>();
if (s == "ProfileGaussian") {
o.setValue(Integration_model::eIntegration_model::PROFILEGAUSSIAN);
}
else if (s == "ProfileEmpirical") {
o.setValue(Integration_model::eIntegration_model::PROFILEEMPIRICAL);
}
else if (s == "BoxSum") {
o.setValue(Integration_model::eIntegration_model::BOXSUM);
} else {
std::stringstream ss;
ss << "Unexpected value " << s << " in json"
<< " cannot be converted to enum of type"
<< " Integration_model::eIntegration_model";
throw std::invalid_argument(ss.str());
}
}
Integration_model::eIntegration_model Integration_model::getValue() const
{
return m_value;
}
void Integration_model::setValue(Integration_model::eIntegration_model value)
{
m_value = value;
}
} // namespace org::openapitools::server::model

Some files were not shown because too many files have changed in this diff Show More