Commit Graph
97 Commits
Author SHA1 Message Date
x01dcandClaude Sonnet 5 aebfccc5f3 fix(flomni): clear busy heartbeat on scan end, fix duplicated tomo math
Two independent fixes:

- GUI "beamline busy" indicators (TomoParamsWidget's banner,
  FlomniWebpageGenerator's status page) purely wait for
  progress["heartbeat"] to go stale (120s / 90s respectively) - there was
  no explicit "scan finished" signal to react to instead, since
  tomo_scan() wrote a heartbeat at the start of every projection but
  never cleared it on exit. Wrapped the scan loop in try/finally so
  heartbeat is cleared on every exit path (normal completion, exception,
  or interrupt/abort), not just at the next scan's start - both
  busy-detectors now see this on their very next poll instead of waiting
  out the timeout. Live-verified: heartbeat is None immediately after
  tomo_scan() returns.

- Found while investigating a related report ("angular step of the final
  combined tomogram shown different between 180 and 360 mode, although
  it has to be identical" + "GUI shows projection count doubling when
  switching 180->360"): TomoParamsWidget's _compute_type1()/
  _requested_to_stepsize() (tomo_params.py) and the generated status
  webpage's calcProjections() JS (flomni_webpage_generator.py) are both
  independent, un-synced duplicates of the exact old N=int(angle_range/
  stepsize) formula fixed in flomni.py's own _tomo_type1_actual_grid()
  two commits ago - they were never updated when that fix landed, so the
  GUI and webpage kept reporting double the projection count for 360
  mode. Fixed both to match flomni.py: N/step/total are always computed
  against a fixed 180 degrees, independent of angle_range. Also fixed
  the "angular step of the final (combined) tomogram" CLI/wizard lines
  in flomni.py itself, which used tomo_angle_range/total_projections
  (correct for 180 mode by coincidence, wrong for 360 mode - the true
  combined resolution is always 180/total_projections, identical
  between modes). Added a regression test asserting the widget's
  formulas match flomni.py's for both modes, to catch this exact kind of
  drift if it recurs. Live-verified against the running sim: both modes
  now report identical total_projections and combined-tomogram step for
  the same stepsize.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 10:18:38 +02:00
x01dcandClaude Sonnet 5 900c810111 fix(flomni): use complementary phases for 360deg tomo, not adjacent pairs
The previous commit's 360-degree phase assignment gave the low and high
halves the SAME phase per pair (1,2)/(3,4)/(5,6)/(7,8), so each pair
concatenated into one continuous evenly-spaced range -- but that means
every low-half angle is exactly 180deg from a high-half angle, which is
exactly the redundant-measurement bug this was supposed to fix, just
reintroduced between subtomos instead of within one.

Corrected: the low half (subtomos 1,4,5,8) now uses the even eighths of
the original 8-way phase_eighths table, and the high half (2,3,6,7) uses
the odd eighths -- complementary, not shared. Folded mod 180, the two
halves interleave into exactly the same 8-way, step/8 grid that 180-mode
itself produces: every position is measured exactly once, using its full
0-360 physical range, with zero redundant measurements anywhere. Total
projection count is unchanged (still identical to 180 mode for a given
tomo_angle_stepsize).

Verified: pure-math unit tests confirm the 360-mode combined set, folded
mod 180, is an exact set match (same count, no repeated residue) against
180-mode's own set. Live-verified against the running flomni sim: real
motor motion for both modes, folding the observed 360-mode angles mod
180 exactly reproduces the observed 180-mode angles.

Also updated the two "angular step of the final combined tomogram"
CLI/parameter-wizard print statements to additionally report the
effective mod-180 reconstruction resolution for 360 mode, since it's
now finer than the raw per-half spacing they already printed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 07:28:24 +02:00
x01dcandClaude Sonnet 5 7e8e807adc fix(flomni): stop duplicate 360deg tomo angles, add sample owner, fix abort crash
Three independent fixes:

- sub_tomo_scan(): in 360-degree tomo_type-1 mode, every sub-tomogram used
  to sweep the full 0-360 range, so each one's own fine grid contained
  angle pairs exactly 180deg apart -- redundant tomographic information.
  Sub-tomograms now each cover a 180deg span, split into low/high halves
  by subtomo_number % 4 with a bit-reversal-of-4 phase table, so adjacent
  pairs (1,2)/(3,4)/(5,6)/(7,8), either quartet, and all 8 combined each
  independently form a complete, evenly-spaced 360deg tomogram at
  successively finer spacing. Total projection count for a given
  tomo_angle_stepsize is now identical between 180 and 360 mode (same N,
  no longer doubled). Updated the 4 other consumers of the old N/step
  formula (zero-deg reference gating, _tomo_type1_actual_grid, the
  parameter wizard, the PDF report) to match. 180-degree mode is
  unchanged. Live-verified against the running flomni sim: real motor
  motion traces the expected boustrophedon path with no duplicate or
  180deg-apart angles.

- Sample storage: added an owner field, packed into the same EPICS DESC
  field as the sample name ("name | owner", via new sample_desc_codec.py)
  since there's no separate PV for it. Wired through
  FlomniSampleStorage, the CLI (flomni_modify_storage_non_interactive,
  ftransfer_modify_storage), the two transfer routines that forward a
  raw DESC value across a gripper move (now unpacked/repacked so owner
  survives the move instead of being dropped or double-packed), and
  SampleStorageWidget. Scoped to flomni only this session; OMNY's
  storage/transfer mixin is unchanged.

- ConsoleButtonsWidget's ABORT button used to send SIGINT then, 500ms
  later, a stop_devices() broadcast to ALL devices with no stop_id --
  an un-suppressed error from that broadcast landing on a queue-tracked
  instruction could kill the scan worker thread outright, requiring a
  full BEC restart. Replaced with: queue.request_scan_abortion() (safe
  no-op if idle, but registers a stop_id so expected errors are
  suppressed), then SIGINT, then a direct, immediate Galil hard stop via
  new GalilController.hard_abort_and_restore_positioning_mode() -- the
  same method ftransfer_abort() now delegates to, so the CLI and GUI
  paths can't drift apart again. SIGINT is sent before the hard stop:
  live testing showed that if the hard stop's mntprgs-clearing side
  effect lands first, a same-session polling loop can mistake it for
  normal completion and fall through into ensure_gripper_up(), which
  must not happen mid-transfer -- sending SIGINT first (near-instant)
  gives that loop's own KeyboardInterrupt handler a head start before
  the hard stop's own multi-step sequence completes. The button is
  labeled per beamline (e.g. "Flomni Motion Stop") and disabled rather
  than silently inert when no hard-stop device is configured/enabled.
  Scoped to flomni only this session (OMNY/LamNI wiring deferred).
  Live-verified against the running sim, including the exact
  stop-lands-mid-queued-instruction scenario that previously crashed
  the scan worker.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 07:09:40 +02:00
Mirko Holler 30b5119a2f feat(flomni): add command jobs to the tomo queue
Type-tags queue jobs with a "kind" field (back-compat: missing kind
defaults to "tomo"), and adds "command" jobs that reconfigure the
beamline (currently: absolute moves on an allow-listed device, plus an
optimize_idgap stub) between tomograms instead of running a scan.

Command jobs are added via tomo_queue_add_command() against a curated
named-action registry (_TOMO_QUEUE_ACTIONS) - not arbitrary code - so
every queued action is auditable and safe to persist across a kernel
restart. Validation is two-layer: schema checks at add time, and each
action re-checks its own arguments against live hardware at execution
time, which is the actual safety boundary. Crash-resume for a command
job re-runs the whole step sequence from the top if every step is
idempotent, or prompts the operator otherwise.

flomni_webpage_generator.py is guarded against command jobs, which
have no "params" key.

See AI_docs/TOMO_QUEUE_COMMAND_JOBS_PLAN.md for the full design.
2026-07-13 09:05:29 +02:00
Mirko HollerandClaude Sonnet 5 ff50711dc9 test(flomni): add tomo-queue e2e harness against the simulated flOMNI
Sections A-C of TOMO_QUEUE_TESTING.md's checklist, run against a live sim
session: params-restored-per-job, legacy queue migration, empty/all-done
no-ops, start_index semantics, exception/SIGKILL crash-resume, resume-
before-fresh ordering, and concurrent queue edits from a second client.
All 10 tests pass together with no cross-test interference.

The flomni_sim fixture and _bootstrap.py factor out what it takes to
construct a live Flomni against the sim (builtins/reload bootstrap,
side-effect neutralization, RT-feedback/fsamx setup) for reuse by both
in-process tests and the SIGKILL-based subprocess tests.

Also adds the AI_docs/ handoff docs (testing checklist results, command-
jobs plan with the action-registry decisions) that this work updated.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-12 23:25:33 +02:00
x01dc 3dbd9313ed test(lamni): stub xeyegui instead of the read-only gui property
CI for csaxs_bec / test (pull_request) Successful in 1m31s
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 2s
CI for csaxs_bec / test (push) Successful in 1m32s
XrayEyeAlign.gui is a property delegating to lamni.xeyegui and has no
setter. Mock lamni.xeyegui in the update_frame tests; drop the redundant
alignment_images reset, which __init__ already handles.
2026-07-12 18:38:44 +02:00
x01dc 69b89fcd85 test(lamni): update x-ray eye align tests to post-EPICS interface
CI for csaxs_bec / test (push) Failing after 1m26s
CI for csaxs_bec / test (pull_request) Failing after 1m24s
Drop test_save_frame (method no longer exists). Rewrite test_update_frame
against dev.fsh/dev.cam_xeye instead of the removed LamNI.alignment module.
Patch the module-level umv in test_tomo_rotate rather than builtins.
2026-07-12 18:33:13 +02:00
appel_candx01dc dbad0d00b8 wip for tests 2026-07-12 08:07:50 +02:00
x01dc 680a7c5813 fix test 2026-07-12 08:07:50 +02:00
x01dcandholler 6533226924 sim next version, including lamni and omny 2026-07-12 07:52:37 +02:00
x01dcandholler bcedf794a5 fixes/version2 sim devices
s Please enter the commit message for your changes. Lines starting
2026-07-12 07:52:37 +02:00
appel_c 46a05b48e0 fix(cont-grid): add extra point in lines to include endpoint 2026-07-10 16:53:14 +02:00
wakonig_k d949797eb1 fix: reorder positions in lamni fermat scan test to comply with ascending default
CI for csaxs_bec / test (pull_request) Successful in 1m31s
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 2s
CI for csaxs_bec / test (push) Successful in 1m30s
2026-07-01 19:34:40 +02:00
appel_candholler 7937b328f9 fix(bpm-control): fix coupling input arg for BPMControl 2026-06-30 14:31:36 +02:00
appel_candholler b6131b1b36 fix(bpm): fix input device config for bpm.BPM 2026-06-30 14:31:36 +02:00
wakonig_k 69e7b28e5c test: add cont grid scan tests
CI for csaxs_bec / test (pull_request) Successful in 1m35s
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 3s
CI for csaxs_bec / test (push) Failing after 1m29s
2026-06-24 12:55:32 +02:00
appel_c f003390bdc test: fix ddg and mcs tests 2026-06-23 13:04:33 +02:00
appel_c cb0d4cf999 test(eiger): skip on_connected du to change of config to 8_5M from 9M
CI for csaxs_bec / test (pull_request) Successful in 1m31s
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 2s
CI for csaxs_bec / test (push) Successful in 1m34s
2026-06-16 16:22:20 +02:00
appel_c 93d7e1662a refactor: migrate devices to new scan_info from scan_server
CI for csaxs_bec / test (push) Successful in 1m30s
CI for csaxs_bec / test (pull_request) Successful in 1m30s
2026-06-15 15:52:11 +02:00
appel_c f964a3ee7b test: skip test_on_complete_error_message
CI for csaxs_bec / test (pull_request) Successful in 1m33s
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 2s
CI for csaxs_bec / test (push) Successful in 1m31s
2026-06-15 15:49:28 +02:00
x12sa 8ebf81f06b fix(eiger): migrate eiger integration to jfjoch-client.rc148
CI for csaxs_bec / test (push) Failing after 1m27s
2026-06-15 10:48:08 +02:00
appel_c a3b1a4eb2f test(eiger): fix test with broker
CI for csaxs_bec / test (pull_request) Successful in 1m31s
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 2s
CI for csaxs_bec / test (push) Successful in 1m34s
2026-05-18 09:13:56 +02:00
wakonig_kandappel_c f388d038db fix: initialize setpoint to 0.0 and update from readback after connection
CI for csaxs_bec / test (pull_request) Successful in 2m9s
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 2s
CI for csaxs_bec / test (push) Successful in 2m0s
2026-04-22 17:24:08 +02:00
appel_c 5917cc2b1d test: fix instruction message for lamni scan 2026-04-21 16:11:48 +02:00
wakonig_k 31d9ba3c69 chore: remove deprecated scan motors from test
CI for csaxs_bec / test (pull_request) Successful in 2m7s
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 2s
CI for csaxs_bec / test (push) Successful in 2m1s
2026-04-21 13:39:58 +02:00
wakonig_k fc11a6067b fix(smaract): ensure setpoint is in sync after restart
CI for csaxs_bec / test (push) Successful in 1m59s
CI for csaxs_bec / test (pull_request) Successful in 2m0s
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 2s
2026-04-09 13:55:25 +02:00
appel_candx12sa 6a704c6dd0 test: add tests for bpm and bpm_control
CI for csaxs_bec / test (pull_request) Successful in 2m0s
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 1s
CI for csaxs_bec / test (push) Failing after 1m25s
2026-03-31 14:25:16 +02:00
wyzula_jandappel_c 6d404cad12 fix(omny/shutter): MonitorSignal wrapper with auto_monitor
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 1s
CI for csaxs_bec / test (push) Successful in 1m57s
2026-03-27 22:41:57 +01:00
appel_c 6d4c9d90fc fix(mcs): omit_mca_callbacks if stop is called. 2026-03-19 11:11:54 +01:00
appel_c 7c89086ba2 fix(ddg): Fix tests
CI for csaxs_bec / test (pull_request) Successful in 1m56s
CI for csaxs_bec / test (push) Successful in 1m57s
2026-03-13 14:19:41 +01:00
wyzula_j be9938ddb7 fix(camera): unify the live mode on cameras 2026-03-11 16:09:39 +01:00
wakonig_k 6873ef8287 test: fix lamni test
CI for csaxs_bec / test (pull_request) Successful in 1m56s
CI for csaxs_bec / test (push) Successful in 1m58s
2026-03-06 15:11:28 +01:00
appel_c 0f072a786e test: add tests for panda, fix tests for fermat scan
CI for csaxs_bec / test (pull_request) Successful in 1m56s
CI for csaxs_bec / test (push) Successful in 1m55s
2026-03-02 13:15:53 +01:00
wyzula_j bc31c00e1f fix(tests): x_ray_eye_align correct imports fixed after refactor of LamNI
CI for csaxs_bec / test (pull_request) Successful in 1m36s
CI for csaxs_bec / test (push) Successful in 1m37s
2026-02-23 13:25:09 +01:00
appel_c 93384b87e0 fix(readback-timeout): fix monkeypatch for readback timeout; closes #140
CI for csaxs_bec / test (push) Failing after 1m29s
CI for csaxs_bec / test (pull_request) Failing after 1m29s
2026-02-16 17:38:10 +01:00
appel_c 9a249363fd refactor(galil-rio): fix socket-signal cached readings 2026-02-16 17:38:10 +01:00
appel_c 5811e445fe tests: fix tests after refactoring 2026-02-16 14:57:02 +01:00
appel_c 16ea7f410e feat(galil-rio): Add di_out channels to GalilRIO 2026-02-16 14:57:02 +01:00
appel_c 9db56f5273 refactor: Eiger refactoring, fix test and add docs.
CI for csaxs_bec / test (pull_request) Successful in 1m34s
CI for csaxs_bec / test (push) Successful in 1m33s
2026-02-16 14:13:55 +01:00
appel_candgitadmin 501bc52867 fix(eps): Fix tests and eps integration 2026-02-16 12:33:15 +01:00
appel_candgitadmin f35c51efa7 test(eps): Add tests for EPS device 2026-02-16 12:33:15 +01:00
appel_c 5784331073 test(conftest): Add monkey patch for SocketSignal Readback_Timeout
CI for csaxs_bec / test (push) Successful in 1m35s
2026-02-16 11:10:47 +01:00
appel_c 75cc672f08 tests: fix tests for ddg1
CI for csaxs_bec / test (push) Successful in 1m32s
CI for csaxs_bec / test (pull_request) Successful in 1m31s
2026-02-11 11:50:22 +01:00
appel_c 6fad4f2034 fix(fast-shutter): Fix cSAXS fast shutter device
CI for csaxs_bec / test (push) Failing after 1m30s
CI for csaxs_bec / test (pull_request) Failing after 1m30s
2026-02-09 08:29:08 +01:00
appel_c 82d47c7511 feat(galil-rio): Add GalilRIO device with 8 analog channels
CI for csaxs_bec / test (pull_request) Successful in 1m28s
CI for csaxs_bec / test (push) Successful in 1m30s
2026-01-29 08:20:38 +01:00
appel_c 153e6a89a4 test: add test for controller to call destroy controller.off
CI for csaxs_bec / test (push) Successful in 1m32s
2026-01-26 07:45:01 +01:00
appel_c 11c887b078 feat(debug-tools): add debug tools and adjust logic from beamline tests
CI for csaxs_bec / test (pull_request) Successful in 1m27s
CI for csaxs_bec / test (push) Successful in 1m30s
2026-01-23 15:00:35 +01:00
appel_c 146b10eb85 tests: fix tests for ddg and mcs integrations 2026-01-23 13:29:43 +01:00
appel_c 188e23df48 fix: Fix MCS card and DDG implementation after testing with hardware at cSAXS 2026-01-23 13:29:43 +01:00
appel_c 2cf2f4b4e4 test(controller): Fix test for controller wait_for_connection
CI for csaxs_bec / test (pull_request) Successful in 1m16s
CI for csaxs_bec / test (push) Successful in 1m26s
2026-01-16 10:52:24 +01:00