Add a small ConsoleButtonsWidget (Yes/No/Abort + message label) as a
GUI alternative to console yesno() prompts during sample transfer,
docked below the live camera view.
- bec_widgets: new ConsoleButtonsWidget (csaxs_bec/bec_widgets/widgets/
console_buttons/). Yes/No write to a response property polled by the
caller; Abort sends a real SIGINT to the BEC client process (captured
via os.getppid() at construction), stopping any blocking call
(including an in-progress motor move) exactly like a console Ctrl+C.
- omny_general_tools: add OMNYTools.gui_yesno(), a GUI-backed
alternative to yesno() with the same message/default/autoconfirm
semantics, polling the widget's response instead of blocking on
input(). Not yet used as a general yesno() replacement.
- gui_tools: flomnigui_show_cameras() now also opens the console widget
docked below the two camera views (set_layout_ratios for relative
sizing, since dock_area.new() has no pixel width/height kwarg).
flomnigui_show_gui() now passes an explicit window geometry, right-
aligned on a 2560x1440 screen.
- flomni: add ftransfer_confirm_dialog(), which uses the GUI console
when available (falling back to the plain CLI yesno() otherwise) and
wire it into ftransfer_confirm()'s per-step "All OK? Continue?"
prompt during sample transfer. Other yesno() call sites (stage-in
flight-tube check, gripper-move stage-out check) intentionally left
on the CLI for now.
Known issue: requested window height in flomnigui_show_gui() is not
taking effect as expected at startup; needs follow-up.
Passing -1 stows the sample currently in the sample stage into a free
tray slot without mounting a replacement, matching the old control
system's sample_change(-1) behavior. Existing swap-path logic is
unchanged.
Add collect_empty_frames(), which acquires 10 flat-field frames at
angle 0 with fsamx shifted out of the beam by fovx/2 (opposite the
normal alignment x-offset). Called once at the start of a new
tomo_scan() (not on resume). Frames are excluded from the ptycho
reconstruction queue and logged to tomography_scannumbers.txt with
subtomo_number=0.
Expose the ConstEmitter runtime constants through the high-level flomni
interface, alongside the existing laser_tracker_* methods, and add an
interactive tweak tool for the two tracking target positions.
New methods on FlomniSampleTransferMixin (thin wrappers delegating to
dev.rtx.controller, same pattern as laser_tracker_show_all):
laser_parameters_show_all()
laser_parameters_set_targety(val)
laser_parameters_set_targetz(val)
laser_parameters_set_intensity_threshold_laser(val)
laser_parameters_set_psd_intensity_threshold_tracking_low(val)
laser_tweak(): interactive 2D raw-terminal loop for the two tracking targets,
modeled on OMNYTools.tweak_cursor.
left/right : target y -/+ (fixed 0.01 step, absolute set of current +/- step)
up/down : target z +/-
s : return both targets to their launch positions
q : quit (terminal state restored in finally)
On launch and after every change it prints the current y/z targets and the
fzp x interferometer signal (read_ssi_interferometer channel 1), so the signal
response can be watched while tweaking.
termios/tty/fcntl/sys are imported locally in laser_tweak to avoid touching
module-level imports. Additive change; no existing behaviour modified. Requires
the ConstEmitter emitter_* methods on RtFlomniController.
Replace ~44 per-slot blocking device reads per poll with a single bulk
flomni_samples.read(), and add change-detection so cells only repaint
when their state actually changes. The old per-slot accessors stalled
the GUI event loop every 2s; steady-state polling now does no UI work.
Writes invalidate the changed slot's cache so local edits still repaint
immediately.
GUI for ftransfer_show / ftransfer_modify. Displays the
sample stage (0), gripper (100) and magazine slots 1-20 in a 4x5 grid
matching the CLI layout. Right-click per slot corrects the records
(new / rename / clear), each action confirmed by its own dialog and
written immediately. Bookkeeping only: writes flomni_samples directly
(mirroring flomni_modify_storage_non_interactive), never moves hardware.
Guarded on fsamroy; OMNY shows a not-implemented placeholder.
Expose the flOMNI ConstEmitter runtime constants (served over the control-loop
TCP server, command letter 'e') to BEC users. These were previously baked into
Orchestra module parameter files; they can now be read and set live.
New RtFlomniController methods (all added to USER_ACCESS):
emitter_get() -> dict of the four values
emitter_show_all() -> PrettyTable printout
emitter_set_tracking_target_y(val) -> "ey<val>"
emitter_set_tracking_target_z(val) -> "ez<val>"
emitter_set_intensity_threshold_laser(val) -> "et<val>"
emitter_set_psd_intensity_threshold_tracking_low(val) -> "el<val>"
emitter_get issues "es" and parses the CSV reply
(targetpos_tracking_y, targetpos_tracking_z, intensity_threshold_laser,
PSD_intensity_threshold_tracking_low), same pattern as the Ts/sr readouts.
Setters use socket_put with a fixed %.4f value, same pattern as the pa
setpoint command; they are fire-and-forget (the server does not ack sets).
The rotation-loop laser threshold (intensity_threshold_rot_laser) is a startup
constant on the server side and is intentionally neither read back nor settable
here.
Named methods were chosen over a single opaque command to match the existing
laser_tracker_* / feedback_* convention and to self-document each value.
Requires the corresponding flOMNI control-loop change (ConstEmitter module +
'e' command in CommunicationServer). Additive change; no existing behaviour
modified.
Expose the ConstEmitter runtime constants through the high-level flomni
interface, alongside the existing laser_tracker_* methods, and add an
interactive tweak tool for the two tracking target positions.
New methods on FlomniSampleTransferMixin (thin wrappers delegating to
dev.rtx.controller, same pattern as laser_tracker_show_all):
laser_parameters_show_all()
laser_parameters_set_targety(val)
laser_parameters_set_targetz(val)
laser_parameters_set_intensity_threshold_laser(val)
laser_parameters_set_psd_intensity_threshold_tracking_low(val)
laser_tweak(): interactive 2D raw-terminal loop for the two tracking targets,
modeled on OMNYTools.tweak_cursor.
left/right : target y -/+ (fixed 0.01 step, absolute set of current +/- step)
up/down : target z +/-
s : return both targets to their launch positions
q : quit (terminal state restored in finally)
On launch and after every change it prints the current y/z targets and the
fzp x interferometer signal (read_ssi_interferometer channel 1), so the signal
response can be watched while tweaking.
termios/tty/fcntl/sys are imported locally in laser_tweak to avoid touching
module-level imports. Additive change; no existing behaviour modified. Requires
the ConstEmitter emitter_* methods on RtFlomniController.
A block is external and self-resolving, so the immediate "measurement stopped,
confirm" warning chime was misleading there - the user cannot act on it and
should just wait. Suppress startWarning when the destination status is blocked;
the blocked track still handles it (silent until the 60-min blockedChime, then
hourly). scanning->idle (success tone) and scanning->other (warning tone) are
unchanged. Help text updated.
- Audio: a normal finish (scanning -> idle) now plays a rising success
arpeggio (C5-E5-G5) instead of the falling warning chime, so a completed
measurement is audibly distinct from a stop to any other state (which keeps
the falling 660->440 warning). startWarning(finished) selects the chime for
both the initial tone and the 30s repeats; the Watch LED text reads
"Measurement finished" vs "Measurement stopped" accordingly. Help text
updated.
- Layout: body uses min-height:100dvh (with 100vh fallback) so the page no
longer extends below the visible viewport on mobile, where iOS 100vh counts
the retracted-toolbar height and leaves empty scroll room at the bottom.
The instrument-details pane showed only a hand-built 6-row settings summary,
far less than the tomo queue shows per job, and nothing useful for a tomo
started outside the queue.
- Flomni _collect_setup_data now returns current_params: the tomo parameters
read live from global vars, keyed by the same names the queue stores in
job.params (_CURRENT_PARAM_KEYS, matching TQ_PARAM_DISPLAY). Values left raw;
the page formats them. Replaces the old settings dict.
- Extract the queue's param-table builder into a shared buildParamRows() JS
helper (carries the computed Projections row), used by both the queue and the
new instrument 'Current measurement' section, so they can't drift.
- renderInstrument renders current_params via buildParamRows (Sample name row
first); card hides only when there are neither params nor temperatures.
- Base _collect_setup_data contract updated: settings -> current_params.
umvr_fsamy_tracked/umv_fsamy_tracked require feedback OFF but did not
enforce it. Add an _internal flag; for user/CLI calls, warn that feedback
must be off (active alignment may be lost), prompt (default yes), and
disable feedback on confirm. Internal callers pass _internal=True since
they already manage the feedback lifecycle (ftransfer_flomni_stage_out,
x_ray_eye_align height-centering and mvy jog).
Match the deleted-widget detection used by all other flomniGuiTools
methods. The previous _flomnigui_check_attribute_not_exists path relied
on hasattr(self.gui.flomni, "Image"/"Image_0"), which returns stale/
mismatched results when docks are recreated, leaving an empty window
after a user closed the GUI mid sample-transfer. _is_deleted() checks
registry membership and reliably triggers a rebuild.
renderTomoQueue auto-opened the running job whenever the open-state snapshot
was empty, so collapsing the only open job (the running one) made the snapshot
empty and re-opened it on the next refresh. Open-state was also keyed by
positional index, which mis-assigns the flag when jobs are added/removed/
reordered.
- Snapshot open jobs by stable key (added_at|label) via a data-key attribute
instead of positional index.
- Auto-open a running job only once, on first appearance, tracked in
window.__tqAutoOpened; afterwards honor the DOM snapshot so a manual collapse
sticks. Prune the set when jobs disappear.
A block interrupts the running scan, clearing active_request_block, so
the old _derive_status() (which only returned 'blocked' inside the
queue_has_active_scan branch) fell through to 'idle' with the blocked
LED off, despite watched beamline states being out of spec.
- _derive_status: return 'blocked' on beamline_blocking OR queue_locks,
independent of active scan; only fresh-heartbeat 'scanning' outranks it.
- _cycle: beamline_blocking = enabled is True AND any(state mismatched).
Gated on enabled so a disabled/unknown interlock with an out-of-spec
state does not raise BLOCKED. Also counted as activity so the idle
clock restarts once cleared.
- beamline-states card summary updated in lock-step: mismatched states are
only called "currently blocking" when enabled, else "out of spec
(interlock disabled/unknown, not blocking)", so pill and card can't
disagree.
- status-detail JS: describe blocking beamline states when no explicit
queue lock is present. Update help text.
webpage_generator: report blocked on interlock even when scan is interrupted
- Add HAS_TOMO_QUEUE and TOMO_TYPES capability flags to
WebpageGeneratorBase, defaulting to flomni's current behavior
(type1 grid-8, type2/3 golden-capped) so this is a no-op for flomni.
- Gate the tomo_queue global-var read in _cycle() behind
HAS_TOMO_QUEUE; unaffected: queue_status/queue_locks/beamline_states,
which come from BEC's own primary scan queue and stay common to
all setups.
- _render_html() now conditionally emits the 'Tomo queue' card and
its DEFAULT_ORDER slot, and drives the projection-count formula
from a TOMO_TYPES JSON blob (generic calcProjections()) instead of
a hardcoded per-instrument JS branch.
- LamniWebpageGenerator: HAS_TOMO_QUEUE=False, TOMO_TYPES with
2-subtomo and 8-subtomo equally_spaced_grid entries (placeholder
keys pending real tomo_type values from the LamNI producer side).
A block interrupts the running scan, clearing active_request_block, so
the old _derive_status() (which only returned 'blocked' inside the
queue_has_active_scan branch) fell through to 'idle' with the blocked
LED off, despite watched beamline states being out of spec.
- _derive_status: return 'blocked' on beamline_blocking OR queue_locks,
independent of active scan; only fresh-heartbeat 'scanning' outranks it.
- _cycle: compute beamline_blocking = any(state mismatched), defined
identically to the beamline-states card so pill and card can't disagree;
also count it as activity so the idle clock restarts once cleared.
- status-detail JS: describe blocking beamline states when no explicit
queue lock is present. Update help text."
fosaz_info previously only reported remaining collision clearance for the
live fosaz position, giving no indication of clearance once OSA is moved
back to its defined IN position if foptz has shifted while OSA was OUT.
Now compares live fosaz against fosaz_in (10 um tolerance):
- if live fosaz is further IN than nominal (closer to collision), warn and
show current remaining space (the number that matters right now)
- if OSA is OUT/away from IN, no warning, but also report remaining space
at the IN position using current foptz, as a heads-up before moving OSA in
- Add HAS_TOMO_QUEUE and TOMO_TYPES capability flags to
WebpageGeneratorBase, defaulting to flomni's current behavior
(type1 grid-8, type2/3 golden-capped) so this is a no-op for flomni.
- Gate the tomo_queue global-var read in _cycle() behind
HAS_TOMO_QUEUE; unaffected: queue_status/queue_locks/beamline_states,
which come from BEC's own primary scan queue and stay common to
all setups.
- _render_html() now conditionally emits the 'Tomo queue' card and
its DEFAULT_ORDER slot, and drives the projection-count formula
from a TOMO_TYPES JSON blob (generic calcProjections()) instead of
a hardcoded per-instrument JS branch.
- LamniWebpageGenerator: HAS_TOMO_QUEUE=False, TOMO_TYPES with
2-subtomo and 8-subtomo equally_spaced_grid entries (placeholder
keys pending real tomo_type values from the LamNI producer side).
Add JSONL timing logs under ~/data/raw/logs/timing_statistics/ for
building a scan-time prediction model. Times each projection in
_tomo_scan_at_angle (final successful attempt only, retries excluded)
and each tomogram in tomo_scan, capturing raw scan parameters plus
elapsed/idle/active durations.
tomo_scan_projection always runs a fermat scan; warn and confirm when
called directly with single_point_instead_of_fermat_scan set, pointing
to tomo_acquire_at_angle instead. Internal callers pass _internal=True
to skip the prompt.
Refresh the Safety at cSAXS checklist PDF (now cross-links back to the
published safety page) and reword the checklist intro to note the local
contact walks users through it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>