Commit Graph
92 Commits
Author SHA1 Message Date
x01dc badbb82ba4 fix(lamni,flomni,omny): re-issue rotation after an interrupted move instead of skipping
CI for csaxs_bec / test (push) Successful in 1m52s
A Ctrl+C during lsamrot/fsamroy/osamroy rotation leaves the cached
user_setpoint at the target even though the axis never finished moving
(stop() halts the motor mid-move). The next scan then wrongly concluded
"no rotation required" from setpoint equality alone, leaving LamNI's
air bearings unclamped (confirmed via galil show all) and the beamline
unable to scan until the setpoint was nudged manually.

lamni_rotation() now also requires
lgalil_is_air_off_and_orchestra_enabled() before skipping, since that
flag only goes true once the Galil #CENROT sequence (air-clamp plus
centering) has fully completed. flomni_rotation()/omny_rotation() use
a readback-vs-tolerance check instead, since those axes have no
air-bearing clamp step.

Along the way, fixed lgalil_is_air_off_and_orchestra_enabled() itself:
it did bool(socket_put_and_receive(...)) directly on the raw Galil
reply string, which is always truthy, so it could never report
anything but True. Confirmed via HW testing in LamNI.
2026-07-31 13:26:15 +02:00
Mirko HollerandClaude Sonnet 5 a65ab6cbdd feat: add SmarAct MCS2 device driver
CI for csaxs_bec / test (push) Successful in 1m54s
Adds a new driver for the SmarAct MCS2 controller (MCS2-C-0008, 9 channels),
parallel to the existing MCS1 (SCU) implementation. Uses the MCS2's raw
ASCII/SCPI interface over TCP (port 55551), which differs from MCS1 in units
(picometers), message termination (\r\n), and error handling (a polled error
queue instead of inline echoes).

- csaxs_bec/devices/mcs2: Mcs2Controller/Mcs2Motor and errors
- csaxs_bec/devices/sim/sim_mcs2.py: simulated backend for testing
- tests/tests_devices/test_mcs2.py: unit tests + sim end-to-end test
- device_configs: commented example stage in bl_optics_hutch.yaml, and a
  standalone single-axis mcs2_config_test.yaml

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-29 17:42:15 +02:00
appel_candwakonig_k f0f7a3249a refactor(falcon): Migrate falcon to ScanServer ScanInfo model 2026-07-29 14:48:35 +02:00
appel_c 8b0a95133c test: fix eiger on_stage test 2026-07-28 14:32:09 +02:00
x01dcandClaude Sonnet 5 89c5ed1c9e fix(LamNI): don't auto-retry lsamrot moves aborted by stop()
CI for csaxs_bec / test (pull_request) Successful in 1m50s
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 2s
CI for csaxs_bec / test (push) Successful in 1m57s
move_and_finish()'s spurious-trip retry (added in 1f85106) couldn't tell a
genuine Galil safety-thread trip apart from a user/scan-initiated stop()
(e.g. Ctrl+C): an aborted move looked like an incomplete move either way,
so the abort got silently undone by resetting the error latches and
re-issuing the original move to the same target.

Track stop() requests on a per-motor threading.Event, cleared at the start
of each move() and checked (twice, since reset_axis_errors() itself takes
a few round-trips) before the retry branch fires, so an aborted move is
now reported as a failure instead of being retried.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 11:37:23 +02:00
x01dc 285691b629 feat(devices): add live-mode FPS measurement to AlliedVisionAravisCamera
CI for csaxs_bec / test (push) Failing after 1m42s
CI for csaxs_bec / test (pull_request) Failing after 1m38s
Port get_live_fps()/live_mode_poll_interval_s from IDSCamera (added on
main): a rolling deque of the last 10 live-mode push timestamps, exposed
as a measured frame rate rather than assuming the nominal poll interval
is actually achieved -- verified against real hardware, where the
Alvium G1-507m's actual acquisition/readout time brings the achievable
rate to ~3 fps despite the 0.2s (5 Hz) nominal poll interval.

Mirrors the same three unit tests added for IDSCamera's version.
2026-07-28 10:26:40 +02:00
x01dc 13326c0985 Merge remote-tracking branch 'origin/main' into feat/allied_vision
# Conflicts:
#	csaxs_bec/device_configs/bl_detectors.yaml
2026-07-28 10:17:04 +02:00
1f8510636c feat(LamNI): auto-retry lsamrot moves after a Galil safety-thread trip
A safety thread on the LAMNI Galil controller supervises air pressure and
capacitive-sensor feedback for the rotation stage; a spurious trip drops
allaxref and sets allaxrer/caperr, failing every subsequent lsamrot move
until manually cleared with allaxrer=1/caperr=0/allaxref=1.

LamniGalilMotor.move() now resets those latches and retries once, scoped
to lsamrot only via LamniGalilController.reset_axis_errors() -- other
axes on the shared controller keep today's behavior unchanged, and a
persisting fault still surfaces as a failure after the single retry.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-27 12:35:35 +02:00
x01dcandClaude Sonnet 5 e299775c44 feat(LamNI): measure camera live-mode FPS and smear-sweep capture FPS
CI for csaxs_bec / test (pull_request) Successful in 3m42s
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 1s
CI for csaxs_bec / test (push) Successful in 2m31s
Neither rate was previously measured anywhere, making it hard to tell a
real acquisition bottleneck from a display/overhead one.

- IDSCamera.get_live_fps() (new USER_ACCESS entry): rolling-buffer
  measurement of the live-mode push rate in _live_mode_loop(), readable as
  dev.cam_xeye.get_live_fps(). SimIDSCamera inherits it unchanged, so it
  works against the simulated deployment too.
- XrayEyeAlign._smear_sweep() now tracks timestamps of the first and most
  recent distinct frame it captures, storing the computed rate as
  self.last_smear_fps and printing it in the sweep-done summary line.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-27 10:35:38 +02:00
x01dcandClaude Sonnet 5 207be425dc feat(sim): randomize rotation-axis offset, drop synthetic crosshair
The simulated speckle pattern rotated exactly around image center --
the same point the FZP crosshair sits at -- so the calibration was
trivially already correct in sim, never exercising the actual
find-and-correct-a-miscalibration path.

Add an opt-in axis_offset_range_px/axis_offset_seed: when set, the
"true" rotation axis the speckle field orbits is offset from image
center by a random amount (fresh each device construction unless a
seed is given, so each sim session gets a new miscalibration to find).
Wired into LamNI's cam_xeye sim config (sim_axis_offset_range_px: 40,
no seed -- random each session); default (0.0) preserves prior
behavior exactly for any other SimIDSCamera user.

Also drop the synthetic crosshair lines baked into
make_speckle_test_pattern's pixel data -- a real camera image has no
such marking; the GUI already draws its own crosshair overlay
(TargetCrosshair) on top of the live image.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-24 16:08:01 +02:00
x01dcandClaude Sonnet 5 bcdfc12a88 fix(LamNI): decouple smear composite display from live acquisition channel
The "camera running" toggle (IDSCamera.live_mode_enabled) was flapping
on/off during the smear sweep, and on real hardware that's genuinely
slow (starting/stopping the live acquisition thread has real driver
overhead, unlike the simulator). Root cause: composite pushes shared
the same device_preview channel the live thread continuously publishes
to, so live_mode_enabled had to be toggled off around every push to
keep the composite from being instantly overwritten.

Give the composite its own channel instead:
- IDSCamera gains a smear_preview PreviewSignal (no rotation_90/
  transpose configured -- composite data is already display-oriented)
  and push_smear_preview(), mirroring push_preview_image() but fully
  decoupled from the live channel.
- XRayEye gains set_live_view_signal() to switch which camera signal
  the live Image view displays, defaulting to the normal channel for
  every fresh GUI instance; on_live_view_enabled() now uses whichever
  signal is currently selected instead of a hardcoded constant.
- _smear_sweep() switches the GUI to "smear_preview" for the sweep and
  pushes composite updates there -- live_mode_enabled is never touched
  at all (just ensured on at the start, exactly like _live_sweep()).
  The GUI is deliberately left on the composite after a successful
  sweep until the caller has collected the operator's click, then
  switched back to "image"; on KeyboardInterrupt it's switched back
  immediately.

This removes the resume_live/hold_display_s toggle-avoidance mechanism
added in def9bf4, which is no longer needed with a dedicated channel.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-24 16:08:01 +02:00
x01dcandClaude Sonnet 5 81f6d0ff1e fix(LamNI): freeze composite display, undo double rotation, speckle sim pattern
Real-HW-adjacent (sim) testing surfaced three issues with the smear
calibration aid:

1. The composite reverted to the plain rotating live view right before
   the click prompt. find_rotation_center_smear_experimental() called
   update_frame() after _smear_sweep(), which grabs a fresh raw live
   frame -- overwriting the composite it just built. Also,
   _push_smear_composite always resumed live mode, so even without that
   bug the composite would only stay visible for hold_display_s.
   Fixed: _push_smear_composite gained resume_live=False for the final
   push; _smear_sweep now takes keep_shutter_open and closes the
   shutter itself at the end, so the composite (not a fresh grab) stays
   frozen on screen for the click. The stray update_frame() call is
   removed.

2. The composite appeared rotated relative to the live view.
   get_last_image() frames already have num_rotation_90/transpose
   applied (PreviewSignal.put() applies it to whatever it stores), so
   composites built from those frames got the transform applied AGAIN
   by push_preview_image()'s own self.image.put() call. Fixed:
   push_preview_image() now undoes the transform first (reverse order,
   since transpose is applied last forward) so the net effect is a
   single transform, matching a live frame.

3. Feature request: the sim camera's rotation-coupled pattern was a
   single eccentric gaussian blob -- a better analog for the isolated/
   point-particle case than the extended/textured case this feature
   actually targets. Added generate_speckle_grains/
   make_speckle_test_pattern (sim_cameras.py): a fixed, seeded field of
   small gaussian "grains" at a range of radii, rotating rigidly
   together as the live angle changes -- producing several concentric
   arcs in the composite instead of one, much closer to a real textured
   sample. New sim_speckle_count/sim_speckle_seed config, defaults
   requiring no yaml changes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-24 16:08:01 +02:00
x01dcandClaude Sonnet 5 ea9f15cde1 feat(sim): rotating structured pattern for simulated X-ray-eye camera
The simulated cam_xeye (SimIDSCamera/_SimIDSBackend) served a single
static Gaussian blob, cached at construction -- rotating lsamrot in a
simulated session produced no visible motion, so the smear/composite
rotation-center calibration aid had nothing to smear into an arc.

Add an opt-in sim_rotation_coupling config (mirrors the existing
sim_coarse_coupling idiom in sim_lamni.py's measured_positions()): when
set, _SimIDSBackend regenerates a fresh frame on every get_image_data()
call with an eccentric blob (make_rotating_test_pattern) tracking the
coupled axis' live simulated Galil position instead of serving the
cached static frame. Wired into LamNI's cam_xeye sim config only
(host/port/axis matching lsamrot's own sim config); flomni's cam_xeye
and any other SimIDSCamera user are unaffected since the new params
default to None (byte-identical output to before, confirmed by test).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-24 16:08:01 +02:00
x01dcandClaude Sonnet 5 f4bd20e4e8 fix: include content changes for vmbpy->Aravis swap
CI for csaxs_bec / test (push) Failing after 2m21s
The prior commit only captured the file renames (a botched `git add`
dropped the actual edits). This commit carries the real diff: Aravis
GObject-introspection backend in base_integration/camera.py, renamed
class/config references, and the rewritten README.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 16:13:07 +02:00
x01dcandClaude Sonnet 5 b644cf786b refactor(devices): swap AlliedVision camera backend from vmbpy to Aravis
Replaces the vendor-SDK-based vmbpy backend with Aravis, an open-source
GenICam/GigE Vision library that implements the network protocol itself,
so no Allied Vision account/license/SDK download is needed - just
PyGObject plus the system-packaged Aravis library. Renames
AlliedVisionVmbCamera -> AlliedVisionAravisCamera (and matching
file/sim/test names) to reflect the new backend; low-level Camera
wrapper keeps the same public interface, only its internals changed.
README rewritten with Aravis install steps and camera-ID discovery via
arv-tool-0.8 / Aravis.get_device_id().

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 16:12:39 +02:00
x01dcandClaude Sonnet 5 f3148c897c feat(devices): add native vmbpy integration for Allied Vision Alvium camera
CI for csaxs_bec / test (push) Successful in 1m41s
Adds AlliedVisionVmbCamera, talking to the Alvium G1-507m directly over
GigE Vision via vmbpy (Vimba X SDK) instead of the existing dead EPICS
IOC-based AlliedVisionCamera, which is left in place for now. Includes
the low-level Camera wrapper, simulation backend, device config example,
tests, and a README covering setup/testing/vmbpy install steps.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 08:06:45 +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
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 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
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
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 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
appel_c 1a9a0beb86 fix(controller): Ensure wait_for_connection calls controller.on()
CI for csaxs_bec / test (push) Successful in 1m13s
CI for csaxs_bec / test (pull_request) Successful in 1m19s
2026-01-15 18:09:34 +01:00
appel_c 7326c471f8 test(falcon): fix test for improved patched_device method in ophyd_devices
CI for csaxs_bec / test (pull_request) Successful in 1m19s
CI for csaxs_bec / test (push) Successful in 1m18s
2026-01-07 11:17:50 +01:00