Commit Graph
1254 Commits
Author SHA1 Message Date
x01dcandClaude Sonnet 5 796b78e78f fix(lamni): zero manual_shift_x/y at the start of a fresh alignment run
CI for csaxs_bec / test (push) Successful in 3m6s
LamNI's alignment-start reset (_align_impl(), documented as "the actual
start of a fresh alignment run") already resets reset_correction()/
reset_xray_eye_correction() there, but never touched manual_shift_x/y --
unlike flomni's equivalent, which this session's work already fixed to
zero manual_shift_x/y at the same point. Same risk: a leftover manual
shift from a previous sample would otherwise bias the next sample's
alignment tomogram.

Found via an audit of whether this session's flomni-side changes (+ the
merged fixes/flomni4 branch) called for any analogous LamNI changes --
this was the one confirmed real gap; everything else either already
existed on LamNI, is generic/shared infrastructure that needed no
changes, or is structurally inapplicable (LamNI is 360-degree-only
laminography).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPZ9gzN2rt3wgiMnTKyrug
2026-10-01 16:32:16 +02:00
x01dc f08c3ef7b7 Merge remote-tracking branch 'origin/fixes/flomni4' into feat/flomni_tomo_from_angles_file
CI for csaxs_bec / test (push) Successful in 3m7s
# Conflicts:
#	csaxs_bec/bec_ipython_client/plugins/flomni/flomni.py
#	csaxs_bec/bec_widgets/widgets/tomo_params/tomo_params.py
2026-10-01 16:19:45 +02:00
x01dcandClaude Sonnet 5 8e2a320e58 feat(flomni): add "Edit command" for pending command jobs in the tomo queue
CI for csaxs_bec / test (push) Successful in 3m9s
The "Load into editor" button in the queue dialog is now dual-purpose:
for a single selected tomo job it behaves as before, but for a single
selected *pending* command job it relabels to "Edit command" and opens
CommandJobBuilderDialog pre-populated with that job's steps/label/
idempotent flag. On OK the job is replaced in place (same queue
position, same id/added_at); on Cancel the queued job is untouched.

Previously a command job could only be "edited" by deleting it and
rebuilding it from scratch via "Add command..." -- tedious for a
multi-step job and easy to get wrong.

Restricted to status == "pending" (reusing _MOVABLE_STATUSES, the same
set already used for "is this row safe to reorder") -- an "incomplete"
command job may have partially executed steps, a materially different
and riskier case than a never-started one.

Live-verified against the running simulated flomni session: button
correctly relabels per selection, editing a real queued command job
replaces it in place with the id/label preserved, and the session's
queue was left exactly as found afterward.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPZ9gzN2rt3wgiMnTKyrug
2026-10-01 16:04:22 +02:00
x01dcandClaude Sonnet 5 91eb55bf13 docs(flomni): "Compensating" -> "New" for move_foptz_with_shift's shift fields
CI for csaxs_bec / test (push) Successful in 3m15s
manual_shift_x/manual_shift_y are replaced outright by
move_foptz_with_shift (self.manual_shift_x = manual_shift_x), not adjusted
relative to the previous value -- "Compensating" wrongly implied the
latter. Wording-only change across the GUI field labels, the action's
help/docstring text, and the two AI_docs testing notes that describe them.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPZ9gzN2rt3wgiMnTKyrug
2026-10-01 15:52:26 +02:00
x01dcandClaude Sonnet 5 47cbb08c13 fix(flomni): check OSA collision warning against fosaz's defined IN position
The foptz-target OSA-collision warning was checking fosaz's current live
readback, but fosaz is normally parked safely OUT except when actually in
use -- so the warning would almost never fire in practice. Check against
fosaz's "in" user_parameter instead (the same nominal position
FlomniOpticsMixin.fosa_in() itself checks before refusing a fosaz move),
since that's the real question: would this foptz target collide with the
OSA if it were swapped in.

Live-verified against the running simulated flomni session: fosaz's
defined IN position is 13.1mm; the warning now correctly engages right at
the real physical crossover (foptz=19 -> +0.90mm clearance, safe;
foptz=20 -> -0.10mm, warns), matching compute_osa_remaining_space()
exactly through the real dialog/client/device-RPC code path.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPZ9gzN2rt3wgiMnTKyrug
2026-10-01 15:52:16 +02:00
x01dcandClaude Sonnet 5 a5fcc73049 feat(flomni): warn on OSA collision risk when picking a foptz target
CI for csaxs_bec / test (push) Successful in 2m58s
The tomo-queue "move_foptz_with_shift" dialog now shows a live warning
when the entered foptz target would leave <=0 mm OSA clearance against a
normal OMNY pin (same collision check fosa_in() already enforces for
fosaz moves, surfaced here at data-entry time instead). Advisory only --
the queued action itself stays a plain absolute move, not gated on this.

Extracted the clearance formula out of FlomniOpticsMixin._osa_remaining_space
into a module-level compute_osa_remaining_space(foptz_val, fosaz_val) so
the GUI (a separate process with only RPC device access, no Flomni
instance to call a bound method on) can reuse the exact same formula
instead of duplicating it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPZ9gzN2rt3wgiMnTKyrug
2026-10-01 15:38:56 +02:00
x01dcandClaude Sonnet 5 437d9e7559 feat(flomni): fix tomo-queue move allow-list, drop idgap stub, add foptz+shift action
CI for csaxs_bec / test (push) Successful in 3m10s
Queue-control "command job" changes:
- Remove the "optimize_idgap" stub action (not commissioned, always a
  no-op) from both Flomni's and LamNI's action registry, and delete the
  now-dead TomoQueueMixin.optimize_idgap() method.
- Fix the "move" action's device allow-list: "mokev" doesn't exist in the
  current device config at all -- the real energy device is "ccm_energy"
  (LamNI's copy already had this right). Also drop "ftray" (sample
  transfer tray), which was only ever there as a sim-testable move target.
- Add a new "move_foptz_with_shift" action: moves foptz (the FZP
  optics-Z stage) and sets the compensating manual_shift_x/manual_shift_y
  in one atomic step. foptz is deliberately NOT in the plain move
  allow-list -- moving it shifts the aligned scan center (interferometer
  mirrors aren't perfectly parallel to the beam), so this is the only way
  to queue a foptz move, specifically so the compensating shift can never
  be forgotten.
- The foptz target is validated against the device's real, live limits
  (not a hand-duplicated static number) both in the GUI spinbox's range
  and in the CLI's add-time validation, so a queued job can't raise when
  it executes unattended later; a defense-in-depth check also exists at
  execution time.

Retargeted the e2e command-job tests from ftray to foptz (now the only
sim-testable move-adjacent path) and updated the AI_docs testing/GUI-testing
notes to match the new action set.

Also fixes a pre-existing, unrelated broken import
(plugins.omny.omny_general_tools -> plugins.OMNY_shared.omny_general_tools,
already broken on main) in _bootstrap.py/test_tomo_queue.py/
test_tomo_queue_command_jobs.py that was blocking omny_e2e_tests collection
entirely, needed to actually verify this change's own test rewrites.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPZ9gzN2rt3wgiMnTKyrug
2026-10-01 15:11:49 +02:00
x01dcandClaude Sonnet 5 cf66e0d1ec feat(flomni): info popup for manual shift x in tomo parameters GUI
CI for csaxs_bec / test (push) Successful in 3m2s
Add a per-field "?" help button, same pattern already used for the
offsets section and Fermat asymmetry. Explains that manual_shift_x is
a constant, angle-independent offset applied on top of the alignment,
only needed in special cases (e.g. when the FZP-to-sample distance is
changed after alignment).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPZ9gzN2rt3wgiMnTKyrug
2026-10-01 13:11:15 +02:00
x01dcandClaude Sonnet 5 2a91f94c06 feat(flomni): add manual_shift_x fine-adjustment parameter
CI for csaxs_bec / test (push) Successful in 2m59s
Mirrors the existing manual_shift_y: a persistent, GUI/CLI-settable x
offset applied to the scan center in tomo_scan_projection() and
tomo_acquire_at_angle(), included in tomo-queue snapshots, and reset to
0 at the start of every x-ray-eye alignment run (and on account-change
defaults) so a leftover fine adjustment never biases the next sample's
alignment tomogram. Bounded to +/-10um in the GUI and CLI, narrower
than manual_shift_y's +/-50um range.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPZ9gzN2rt3wgiMnTKyrug
2026-10-01 12:58:34 +02:00
x12saandClaude Sonnet 5.5 b4cec42211 fix(tomo_params): enable 'run all sub-tomos forward' on entering edit mode
CI for csaxs_bec / test (push) Successful in 2m58s
_enter_edit_mode_with() called _set_fields_enabled(True) before setting
_edit_mode, so the always-forward checkbox was evaluated with
_edit_mode=False and stayed disabled until the angle range was toggled.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-01 12:54:28 +02:00
x12saandClaude Sonnet 5.5 b3830dc3e5 feat(flomni): option to run all type-1 sub-tomos forward (0->180)
CI for csaxs_bec / test (push) Successful in 3m5s
Add tomo_type1_always_forward (180 deg range only, default off). Every
sub-tomo sweeps 0->180 with an unchanged angle set, so the 0 deg
reference (zero_deg_reference_at_each_subtomo) is taken before all 8
sub-tomos instead of every second one.

Exposed in tomo_parameters(), queue params and the tomo params widget;
resume/reacquire use the same plan. Tests and docs updated.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-01 12:33:49 +02:00
x01dcandClaude Sonnet 5 c9bf65adda docs(flomni): state the angle-file column-1 range as 0-360
CI for csaxs_bec / test (push) Successful in 3m1s
Keep the user-facing docs at the simple, nominal 0-360 sweep rather
than advertising the stage's -2/362 physical overtravel margin that
_tomo_scan_at_angle()/angle_file.py actually tolerate -- that margin is
a safety/robustness allowance, not something to document as an
intended input range.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPZ9gzN2rt3wgiMnTKyrug
2026-10-01 12:06:25 +02:00
x01dcandClaude Sonnet 5 d119bd2ce8 fix(flomni): widen tomo_type-4 angle range to stage overtravel; fix GUI clipping
CI for csaxs_bec / test (push) Successful in 3m4s
Angle files now accept -2 to 362 degrees (the fsamroy rotation stage's
physical overtravel range) instead of the nominal 0-360 sweep. This
required widening both the parser's bounds (angle_file.py) and
_tomo_scan_at_angle()'s own gate (a new _min_scan_angle(), alongside the
existing _max_scan_angle()) -- without the latter, an angle just outside
[0, 360] would have parsed fine but then been silently skipped during
acquisition with no error, which is worse than rejecting it upfront.

Also fixes the type-4 GUI section's "Content:" label clipping its second
wrapped line: QFormLayout sizes that row from the label's sizeHint() at
construction (holding the short "---" placeholder) and doesn't reliably
recompute it when setText() later swaps in longer, word-wrapped content.
_set_angle_file_summary() now recomputes the label's minimum height from
heightForWidth() after every update.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPZ9gzN2rt3wgiMnTKyrug
2026-10-01 11:49:49 +02:00
x01dcandClaude Sonnet 5 0332f1c681 fix(flomni): reset tomo progress before pre-flight gates, not after
CI for csaxs_bec / test (push) Successful in 3m18s
tomo_scan() only reset the progress dict (projection/subtomo/angle/
tomo_start_time/heartbeat/...) inside the "new scan" block, which runs
after the eye/optics-in and filter-out-of-beam gates. If either gate
declined (e.g. the setup isn't in measurement condition, which disabling
rt feedback can trigger) or the tomo_type-4 angle-file check raised,
tomo_scan() returned/raised having never touched progress, leaving the
GUI/webpage showing projection/angle/start-time from whatever scan last
completed -- arbitrarily old, and easy to mistake for a scan still
running.

Hoists the "is this a new scan" check to the top of tomo_scan() and
calls progress.reset() there, before any gate runs; the heavier new-scan
actions (sample DB registration, PDF report, collect_empty_frames(), the
0-deg reference shot) stay exactly where they were, after the gates.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPZ9gzN2rt3wgiMnTKyrug
2026-10-01 11:22:45 +02:00
x01dcandClaude Sonnet 5 67884c0c3f feat(flomni): tomo_type 4 -- live-appendable angle files, per-line overrides
CI for csaxs_bec / test (push) Successful in 2m59s
Angle files can now be grown while a scan is running: tomo_scan() polls
and re-reads the file whenever it catches up to the current end,
picking up newly appended lines automatically instead of requiring
tomo_scan_resume(). A file is "complete" only once it ends with an
explicit END sentinel line -- without one the scan waits indefinitely
at EOF rather than stopping, so a static/legacy angle file needs END
appended or a scan against it will hang at the end.

Each line may also carry optional step=/exptime=/frames= key=value
tokens overriding the Fermat step size, exposure time, and burst frame
count for that projection and (sticky) every one after it, falling
back to the live tomo_parameters() configuration whenever not set.
Threaded through as kwargs that default to None and are omitted when
empty, so every existing tomo_type 1/2/3 call site and test stub is
unaffected.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPZ9gzN2rt3wgiMnTKyrug
2026-10-01 11:01:16 +02:00
x01dcandClaude Opus 5.5 9373fe307a fix(flomni): no 0-deg damage-estimation shots for tomo_type 4
CI for csaxs_bec / test (push) Successful in 3m4s
Sub-tomogram numbers in a user angle file are just labels, so inserting
extra 0-deg projections at odd sub-tomogram transitions is surprising.
tomo_type 4 now ignores golden_projections_at_0_deg_for_damage_estimation;
the CLI no longer prompts for it and the widget hides it for type 4.
The unconditional 0-deg reference shot at the start of a new tomogram
is unchanged; further 0-deg shots can be put in the file directly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:57:11 +02:00
x01dcandClaude Opus 5.5 35ac94cfd5 feat(flomni): tomo_type 4 -- angles read from a file
CI for csaxs_bec / test (push) Successful in 3m7s
New angular sampling mode: tomo_angle_file points to a plain-text file
with one angle (0-360 deg) per line, optional 2nd column = sub-tomogram
number, '#' comments. Only the path is stored; the file is re-read at
every tomo_scan() start, resume and queued-job run, so an edited file
always takes effect on the next (re)start. The parsed angle list is
logged to scilog at scan start.

- OMNY_shared/angle_file.py: shared pure parser + summary, incl.
  warning for 180-deg-opposite/duplicate angles
- flomni: tomo_type 4 branch in tomo_scan()/tomo_scan_resume(), bad
  file fails before any acquisition, angles >180 not gated by
  tomo_angle_range, CLI prompt/display, PDF report
- tomo queue: path snapshotted per job; setter does not validate so
  stale paths never break non-type-4 jobs; reacquire bounds by file
- TomoParams widget: type 4 (flomni only) with Browse... file dialog,
  live content preview, validation blocking Submit/Add to queue
- webpage: show angle file in param tables

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:46:56 +02:00
x12saandClaude Sonnet 5.5 b15b236673 revert(config): drop shutter_eh1 and restore shutter_es name
CI for csaxs_bec / test (push) Successful in 3m5s
Reverts 7ebc33c and c8f96d5.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-29 14:06:36 +02:00
x12saandClaude Sonnet 5.5 7ebc33c3e1 refactor(config): rename shutter_es to shutter_oh (optics hutch shutter)
CI for csaxs_bec / test (push) Successful in 3m0s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-29 14:04:34 +02:00
x12saandClaude Sonnet 5.5 c8f96d5942 feat(config): add EH1 endstation shutter A open status (shutter_eh1)
CI for csaxs_bec / test (push) Successful in 3m3s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-29 14:00:56 +02:00
x12saandClaude Sonnet 5.5 2e05d1e456 feat(webcam): add exposure, auto-exposure, gain and brightness control to WebcamViewer
CI for csaxs_bec / test (push) Successful in 2m58s
Settings are posted to the camera server's /camera/settings endpoint and read
back on startup in a background thread, so an unreachable server cannot block
device loading. set_exposure_time() disables auto exposure first.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-29 13:49:17 +02:00
x12saandClaude Sonnet 5.5 7cb553414a fix(tests): give leye_out shutter test a csaxs and client stub
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 2s
CI for csaxs_bec / test (push) Successful in 2m56s
leye_out() now reads self.csaxs and self.client (slit/filter handling), which
the bare LamNIOpticsMixin subclass in the test did not define.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-29 13:07:46 +02:00
hollerandClaude Sonnet 5 84586ec4bb feat(lamni): move slits and filters in leye_in/leye_out like flomni's feye
leye_in() now widens sl1xs/sl1ys by 0.3mm and narrows the exposure-box
filters to 5% transmission before moving the eye in, and leye_out()
restores the pre-eye slit size and fully opens the filters again, with
a manual-override prompt if the slits were hand-adjusted while the eye
was in. Mirrors flomni's feye_in()/feye_out() intent (which has this
logic only as dead/commented-out code); LamNI now takes an optional
csaxs reference so it can call csaxs.fil_trans() like Flomni does.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 13:07:46 +02:00
hollerandClaude Sonnet 5 b80c6417d2 fix(lamni): go-live audit tier 2 -- wrong numbers and missing flomni ports
- tomo_scan_projection() now adds the projection to the reconstruction queue
  itself (like flomni), so custom at_each_angle hooks and direct calls are
  reconstructed; _at_each_angle()/MagLamNI no longer do it (no double entry).
  tomo_alignment_scan() opts out (_reconstruct=False) to keep its previous
  behaviour -- flomni's alignment projections are queued, LamNI's never were.
- write_pdf_report(): branch on tomo_type (a golden-ratio scan reported a stale
  type-1 count and a hardcoded '8 sub-tomograms'), e-account from
  bec.active_account, tolerate a missing detector_distance.
- tomo_parameters_cli(): range guards (stitch 0-50, frames 1-100, >= 8
  projections, type-3 >= 1, golden max 0-1e6, bunch size 20-100).
- Webpage: projection count for tomo type 1 used flomni's 180-degree
  sub-tomograms (half the real count); TOMO_TYPES gets a base_angle. Also show
  the piezo range, manual shift and 0-degree reference rows.
- Tomo-params GUI: manual shift is mm end to end (label/range said um, +-1000);
  golden bunch size floor 20 for LamNI (setter/CLI already required it, so a
  smaller GUI value broke tomo_queue_execute). flomni fields untouched.
- lfzp_info() and the queue 'move Energy' entry used the legacy 'mokev' device
  (only in device_configs/legacy); now ccm_energy.
- Special-angle UnboundLocalError fixed in flomni too (list consumed only after
  a successful projection, so retries still see the special angle).
- Tomo type 3: exact integer sub-tomogram numbering (float truncation mislabelled
  the boundary projection for ~35 values of n < 400).
- XrayEyeAlign.align(): always reset the GUI (DAP forwarding, crosshair) on any
  failure; xrayeye_update_frame() warns when beamline states are invalid.
- Stale text / debug print; gap doc updated with the current status.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 13:07:46 +02:00
hollerandClaude Sonnet 5 657e192b8c fix(lamni): go-live audit tier 1 -- lost projections, shutter, endless-scan GUI, scilog
Found by auditing LamNI against the battle-tested flomni:

- _tomo_scan_at_angle swallowed TimeoutError alarms: the projection was never
  retried, its failed scan numbers were logged as a success and it never
  reached reconstruction. Now the queue is reset and the alarm re-raised so
  @scan_repeat re-acquires it. The special-angle list is consumed only after
  success (a retry must still see it) and num_repeats is always defined.
- tomo_alignment_scan had the same swallow; it now retries (bounded) and
  rewrites ptychotomoalign_scannum.txt with the scan numbers actually acquired.
- leye_out() opened the fast shutter instead of closing it (regression from
  4967474 'removed fsh commands').
- Progress GUI: an endless golden-ratio scan (golden_max_number_of_projections
  == 0) divided by zero on the first projection, and any GUI/RPC failure
  propagated into the scan (retried 10x by @scan_repeat, then aborted). Now
  guarded and wrapped like flomni's dea43ed.
- raise_window() disabled as in flomni (it can hide the GUI window).
- write_to_scilog and the PDF report entry used the removed bec.logbook API;
  they now use bec.messaging.scilog like flomni, never raise, and include the
  at-each-angle hook source in the end-of-scan/timing entries.
- extra_tomo: num_repeats unbound for non-special angles.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 13:07:46 +02:00
hollerandClaude Sonnet 5 27cdaa197c feat(lamni,flomni): tomo_parameters() opens the GUI window, CLI is tomo_parameters_cli()
- shared TomoQueueMixin.tomo_parameters() opens OMNY_TomoParams in its own
  window (lamni_tomo_params / flomni_tomo_params); repeat calls do not open
  a second one; a missing or failing GUI raises the setup's error and points
  to tomo_parameters_cli() instead of silently falling back
- rename the prompt-based versions to tomo_parameters_cli()
- docs: describe both, and use the CLI in the queue examples that rely on
  the command blocking until the values are entered
- add tests with a fake GUI

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gUjUT2xCNpnBQkThn3CqP
2026-09-29 13:07:46 +02:00
hollerandClaude Sonnet 5 0d42cb303b fix(lamni,flomni): create documentation folder before writing the tomo PDF report
PDFWriter does not create directories, so tomo_scan() failed with
FileNotFoundError when ~/data/raw/documentation did not exist. Also add an omny
TODO for porting the remaining ~/Data10 paths and the same folder fix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gUjUT2xCNpnBQkThn3CqP
2026-09-29 13:07:46 +02:00
hollerandClaude Sonnet 5 7753dfff38 fix(lamni): port flomni's tomo_reconstruct scan-list fallback and folder resync
- fall back to the last completed scan number when _current_scan_list is
  missing or stale (direct calls outside tomo_scan_projection)
- re-read ptycho_reconstruct_foldername on every write so changes from
  another client session are picked up
- add tests

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gUjUT2xCNpnBQkThn3CqP
2026-09-29 13:07:46 +02:00
hollerandClaude Sonnet 5 af7878988e feat(lamni): add lamni_move_to_scan_center wrapper, document shift computation
- LamNI.lamni_move_to_scan_center(shift_x, shift_y, angle): thin client
  wrapper around scans.lamni_move_to_scan_center with the same parameters
  and docstring
- user docs: describe how the per-projection shift is computed (base shift,
  x-ray eye fit, manual shift, correction tables) in the fine alignment
  section, and add a section on checking the x-ray eye correction with the
  eye still in

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gUjUT2xCNpnBQkThn3CqP
2026-09-29 13:07:46 +02:00
hollerandClaude Sonnet 5 b066b526c1 fix(lamni): scan defaults, sim feedback interlock, fttrz draft
- lamni/omny fermat scan: default exp_time 0.1, drop unused readout_time
  (devices already fall back to their own configured readout time)
- sim_lamni: refuse the sd scan start and abort a running scan while the
  interferometer feedback loop is off; add tests
- simulated_lamni.yaml: lsamrot sim_velocity 48 (4x hw)
- lamni_optics_mixin / ptycho_lamni.yaml: commented-out draft for moving the
  fttrz flight tube in leye_out/leye_in, pending commissioned positions

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016gUjUT2xCNpnBQkThn3CqP
2026-09-29 13:07:46 +02:00
hollerandClaude Sonnet 5 15c720e89e fix(lamni): fully reset tomo progress when a new tomo scan starts
tomo_scan() only reset the timing/ETA fields, so after a finished scan the
progress GUI kept showing the old subtomo, angle and projection == total
(rings at 100 %) while the initial 0-degree reference shot ran, with an ETA
computed from the old projection count against the new start time.

New _reset_progress_for_new_scan() resets every field (incl. the right
totals for the tomo type) in one global-var update and refreshes the GUI.
Resumes are unaffected.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 13:07:46 +02:00
hollerandClaude Sonnet 5 fd4e8a2de1 fix(lamni): tomo_scan_resume resumes at the interrupted angle, not a shifted sweep
_subtomo_angle_plan() used an explicit start_angle as the origin of a new
360-degree sweep. Resuming subtomo 2 at 85 deg generated 435..85; the >360
artifacts were silently skipped by _tomo_scan_at_angle's range gate, so the
resume began at 355 deg, re-measured done angles, never reached the rest and
reported wrong progress indices.

start_angle is now the literal resume point on the sub-tomogram's own grid:
the plan returns the remaining tail of the normal sweep plus a subtomo_offset
used for progress numbering (mirrors Flomni). Off-grid angles raise ValueError.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 13:07:46 +02:00
x12saandClaude Sonnet 5 00ddc5f560 fix(eiger): resolve live preview data channel per detector, not "default" only
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 2s
CI for csaxs_bec / test (push) Successful in 2m57s
The Eiger2 Si 500K's multi-threshold JFJ preview messages key the frame
under a threshold name (e.g. "threshold_1"), not "default" as eiger_1_5/
eiger_9 do -- confirmed by capturing the live JFJ ZMQ preview stream.
_preview_callback hardcoded "default", so it silently dropped every
frame for eiger2_si_500k (251+ "without data" errors in DeviceServer.log,
matching the empty BEC image widget). Now prefers "default" when present
and falls back to whichever single channel the broker actually sent.

Also document the JFJoch Web UI (http://sls-jfjoch-001.psi.ch:8080) and
the Eiger 2 Si 500K detector server address (129.129.122.159) in
bl_detectors.yaml's Eiger section.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 12:44:42 +02:00
x12saandClaude Sonnet 5 80612865aa fix(flomni): adjust heater/X-ray-eye calibration and Galil limit message
Correct fttrx_in offset for feyex (-2.4 -> -2.3), disable fheater
(enabled: 0) pending further commissioning, and clarify the Galil
"Limit reached." console message to "Limit switch reached."

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 12:44:42 +02:00
x12saandClaude Sonnet 5 26da8ea66a feat(eiger): integrate Eiger 2 Si 500K and make NeXus writer detector-agnostic
Add the Eiger2Si500K device class (subclassing the shared JungfrauJoch Eiger
base) and make it the active detector in bl_detectors.yaml. The cSAXS NeXus
writer hardcoded "eiger_1_5" everywhere, so switching the active detector
silently dropped the frame-data links (entry_ptycho/data, data_soft, and the
NXdetector group) for any other Eiger model. Resolve the active detector via
a new "eiger" deviceTag instead, and look up per-model NXdetector metadata
(pixel size, sensor description/thickness, orientation) from a small table so
a future model can't reintroduce the same silent failure.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-29 12:44:42 +02:00
x12sa a9c2139bf8 docs(flomni): document that PandA stdev needs the analog cap-sensor term
Cross-checked PandA's raw within-point sample stdev against RT's own
per-point control-loop stdev on S06313. Confirmed the capacitive-sensor
subtraction from the position conversion formula isn't optional for a
noise estimate either: dropping it (interferometer counts alone) gives a
noise estimate ~10x too large and nearly uncorrelated with RT's (r~0.2),
because interf and cap are anti-correlated at r~-0.96 within a point. With
the full formula, PandA and RT's independent stdev estimates agree to
~8-14% and correlate at r~0.98-0.99. Also flags
average_stdeviations_x_st_fzp/_y as a cumulative-mean field, not a
per-point stdev, to avoid it being used by mistake in a future session.
2026-09-29 12:44:42 +02:00
wakonig_k 8740975b6f refactor(omny): fix import of MessageEndpoints
CI for csaxs_bec / test (pull_request) Successful in 2m52s
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 2s
CI for csaxs_bec / test (push) Successful in 3m1s
2026-09-28 10:41:53 +02:00
x12saandClaude Sonnet 5 bc094dd172 fix(tests): resolve flomni/lamni CLI source paths via module __file__
CI for csaxs_bec / test (pull_request) Successful in 2m57s
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 1s
CI for csaxs_bec / test (push) Successful in 2m56s
test_flomni_cli_fovy_bounds_within_scan_bounds and
test_lamni_cli_piezo_range_bounds_within_scan_bounds opened the CLI
source files using a path hardcoded relative to the repo root, which
only works if pytest's cwd happens to equal the repo root. In CI the
job's cwd is one level above the checkout, so the same relative path
raised FileNotFoundError. Resolve the path from the already-imported
module's __file__ instead, which is independent of cwd.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 16:19:45 +02:00
x12saandClaude Sonnet 5 aeefe5b2de docs(flomni): batch-validate S00391-399, resolve burst-grouping and reduced-data-mode open questions
CI for csaxs_bec / test (push) Failing after 2m54s
CI for csaxs_bec / test (pull_request) Failing after 2m52s
Validated nine flomni_fermat_scan runs (S00391-399: single-frame,
frames_per_trigger=3 burst, and reduced-data-mode groups, two aborted
mid-scan) against rt_positions ground truth. All nine reproduce positions
with R^2 >= 0.9999999 on both axes and no anomalous residuals.

Resolves two open questions from sec 6:
- Burst-mode grouping: frame_counter increments once per sub-frame
  trigger, not once per point -- point index is
  frame_counter // frames_per_trigger, confirmed at R^2 = 1.0000000
  against S00395/396/398.
- Reduced data mode: characterized empirically via S00399 -- keeps only
  gate_detector_active==1 rows (~99.5% vs ~39% of rows in normal
  continuous mode), roughly halving row count with no accuracy loss.

Also nails down the abort-into-restage stale frame_counter mechanism more
precisely: S00393 aborted with exactly 29 points recorded -> S00394
inherits a stale-29 prefix; S00397 (burst) aborted at 17 points x 3
sub-frames=51 -> S00398 inherits a stale-51 prefix. Both harmless
(gate_detector_active==0 throughout the stale rows in both cases), and
both an exact match between the aborted scan's last count and the next
scan's stale value.

Note: this batch does not exercise the arm_scan_allowlist fix (5590633)
-- the running device-server process predates that commit -- though it
wouldn't have changed anything here anyway since every scan in this batch
is flomni_fermat_scan.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 16:13:06 +02:00
x12saandClaude Sonnet 5 55906334fc feat(panda): only arm PandA for flomni_fermat_scan
CI for csaxs_bec / test (push) Failing after 2m51s
Generic BEC staging (stage_all_devices/pre_scan_all_devices) has no
per-scan device opt-in -- every enabled device is staged/pre_scanned for
every scan type (grid_scan, line_scan, alignment moves, ...), not just the
ones that consume its data. deviceTags (ptycho_flomni) are never consulted
by that code path, they're purely a client-side grouping convenience. So
omny_panda_continuous was being Arm()ed and disarmed for every scan in a
session even though only flomni_fermat_scan reads its data -- unnecessary
hardware arm/disarm cycling, and it directly compounds the stale
frame_counter carryover bug documented in PANDA_POSITION_VALIDATION.md
sec 7 (more arm cycles means more abort->restage windows where that bug
can be triggered).

PandaBoxOMNY now takes an arm_scan_allowlist constructor kwarg (None by
default, arms for every scan -- unchanged behavior). When set, on_stage()
computes _should_arm_panda from scan_parameters.scan_name against the
list; on_pre_scan() skips sending Arm() entirely when it's False, and
on_complete() skips the wait-for-frame-count poll loop the same way, both
resolving immediately instead. The data-readout thread/TCP connection
startup in on_stage() is untouched, since it doesn't touch PandA's
hardware register state (COUNTER1) the way Arm() does.

ptycho_flomni.yaml's omny_panda_continuous now sets
arm_scan_allowlist: [flomni_fermat_scan].

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 16:00:20 +02:00
x12saandClaude Sonnet 5 c3c1b10d7e feat(flomni): commission heater down/up sequencing and OSA safety checks
CI for csaxs_bec / test (push) Failing after 2m55s
- Add fheater userParameter (in: -11.5, enabled) and drive it to that
  position at the end of ftransfer_flomni_stage_in(), gated on "enabled"
- fosa_in()/fosa_out() now refuse to move the OSA unless fheater is
  verified fully up or fully down, instead of fosa_out() silently
  forcing the heater up
- ensure_fheater_up() reuses the new _fheater_is_up() helper
- Reorder ftransfer_flomni_stage_out() to bring the eye in and optics
  out before disabling feedback
- Tighten fosaz "out" clearance (6 -> 4mm)
- Re-enable omny_panda_continuous device config
- Update PandA position-validation doc with post-fix scan confirmation
  and updated venv path notes

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 15:41:08 +02:00
x01dcandClaude Sonnet 5 9cdc7dcc3f docs(flomni): document PandA Mode B recovered-position validation method
CI for csaxs_bec / test (push) Failing after 2m50s
Write-up for continuing this testing in a future session without needing to
re-derive it: the required gate_detector_active/frame_counter grouping
(and why naive per-row comparison can't be fixed by any scale/offset
correction), the exact interferometer + capacitive-sensor conversion
formula, the stale-frame_counter carryover bug and its fix (3eb6e03), and
the validation method (R²/residuals against rt_positions' trusted
average_x_st_fzp/_y). Also records the two agreed next steps: burst
acquisition testing and reduced data mode (the latter still undefined,
to be scoped in that session).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPZ9gzN2rt3wgiMnTKyrug
2026-09-21 20:27:15 +02:00
x01dcandClaude Sonnet 5 3eb6e0355f fix(panda): drop stale frame_counter carryover in Mode B raw stream
CI for csaxs_bec / test (push) Failing after 2m51s
Diagnosed against a real scan (S06313): grouping raw interf_st_fzp_x/_y
samples by frame_counter + gate_detector_active reproduces rt_positions'
trusted average_x_st_fzp/_y to R² > 0.9999, confirming that method -- but one
point (167) was off by ~116 nm because PandA's COUNTER1.OUT is not cleared by
Arm(). The first raw samples of an acquisition can briefly carry a stale
frame_counter value left over from the previous acquisition's tail (observed:
36 samples reading a stale 167 before dropping to 0), which silently
contaminates whichever real point later in the same scan happens to share
that counter value.

PandaBoxOMNY now drops raw rows captured before it observes frame_counter ==
0 for the first time in each acquisition -- on every arm, including
on_pre_scan retries, since each Arm() reopens the same stale-value window --
and drops leftover buffered rows from an abandoned attempt at the same point.
Verified against S06313: point 167's residual drops from ~116 nm to ~0.1 nm
after the fix, in line with the rest of the scan.

Write-up, including the diagnostic method and a possible PandA-layout-level
alternative fix, in docs/developer/panda_box_free_running_setup.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPZ9gzN2rt3wgiMnTKyrug
2026-09-21 20:21:23 +02:00
x12saandClaude Sonnet 5 7fe20ea3d1 docs: add note-location rule and OMNY tomo_alignment_fit TODO to AGENTS_mirko
CI for csaxs_bec / test (push) Failing after 2m55s
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 16:22:54 +02:00
x01dcandClaude Sonnet 5 527113340e docs(flomni): xrayeye skip button tested in the flomni simulator
CI for csaxs_bec / test (push) Failing after 2m53s
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 16:20:48 +02:00
x01dcandClaude Sonnet 5 337cdc45e9 fix(xrayeye): hide the Skip button until a client script opts in
CI for csaxs_bec / test (push) Failing after 2m57s
LamNI/omny never call enable_skip_button, so they only had a greyed-out
Skip button. Keep it hidden; the first enable_skip_button() call (flomni
does this at the start of the alignment) shows it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 16:10:09 +02:00
x12sa 7695a6293a remove the optics before rotating to 90, in case of close situation with OSA and 2d sample pins
CI for csaxs_bec / test (push) Failing after 13m23s
2026-09-21 15:58:37 +02:00
x01dcandClaude Sonnet 5 0ad6c5014d feat(flomni): Skip button on the xrayeye alignment to leave out one angle
CI for csaxs_bec / test (push) Failing after 2m12s
Flat samples are edge-on at 90 deg and cannot be centered there. The
XRayEye widget gets a Skip button (disabled unless the client enables it,
so LamNI/omny are unaffected) that signals omny_xray_gui.submit = -1.

XrayEyeAlign._align_impl leaves that step out of the fit: one of the five
angles may be skipped, at least 4 are needed. Skips of the FZP center, the
height marking, or a second angle are refused with a message and the run
continues. write_output() builds angles/offsets from the remaining steps
and raises if fewer than 4 are left; the h5 records the skipped angles.

Not yet tried on real hardware.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 15:56:10 +02:00
x12saandClaude Sonnet 5 0ebe55f31c docs(flomni): plan for a Skip button on the xrayeye alignment widget
CI for csaxs_bec / test (push) Failing after 2m12s
Idea only, not implemented. Includes the 4-point DAP sine-fit stability
study and the decision to send submit=-1 as the skip signal.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 15:43:56 +02:00
x12saandClaude Sonnet 5 e802d55112 docs(omny): TODO to port always-defined tomo_alignment_fit from flomni
CI for csaxs_bec / test (push) Failing after 2m23s
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 15:03:44 +02:00