Commit Graph
11 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
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
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 63ee870c89 fix(test-x-ray-eye): update DeviceBase inits with proper config as needed due to PR #506 in BEC 2025-06-11 16:26:52 +02:00
wakonig_k 447a9c3924 refactor: upgrade to copier version v1 2025-05-24 11:37:51 +02:00
appel_c c109abce12 feat: populated csaxs_bec from ophyd and bec 2024-04-19 17:48:30 +02:00