Brings the LamNI beamtime-2 line (fixes/lamni_during_beamtime_2, contained in
this branch) and the Keithley 2400 work up to main so it can go in by
fast-forward. Conflicts resolved:
- omny_general_tools.py: keep stitch_tile_offsets/lamni_smallest_tile_position_count
(branch) and read_escape_suffix (main)
- flomni.py: import both helpers; state keeps recent_projection_gaps and tomo_completed
- tomo_params.py: _job_tooltip(job, registry=None, profile=None) combines the
branch's command-step formatting and main's per-profile field filtering;
call site passes both by keyword
- test_rt_flomni.py: keep both new tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Keithley moved from the flOMNI PC to the LamNI PC: serial bridge service
lamni-serial-keithley on mpc2680, TCP 3336.
- ptycho_lamni.yaml: new keithley device (host mpc2680.psi.ch, tags
ptycho_lamni + keithley); onFailure: buffer since the Keithley is not
always connected
- remove the stand-alone keithley_2400.yaml
- simulated_bl_simulated_lamni_keithley.yaml: keithley entry inlined
(the included file is gone)
- Keithley2400 default host mpc2844 -> mpc2680
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The names now say which half is simulated: the beamline (ddg1, fsh) is
simulated in all of them, LamNI is either real or simulated. Device tags,
the include key (was 'flomni'), the generator output name and docs follow.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M8zoDzDfsCTY2o5bT3J7Wv
Add a Keithley 2400 device, a positioner in mA over the TCP-serial bridge,
with voltage readback and output_on/output_off/status user commands. The
output and level are left alone on connect, stop and restart.
Add the LamNI tomo queue actions set_keithley_current and sleep, available
in the command job dialog, and a config with only the Keithley plus one
combining it with the simulated LamNI.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M8zoDzTXoPAqgdFjHUFFF8
Opens a BEC GUI window with waveform plots of the XBPM3 blade signals and
the XBIM signal by default. Further plots by name (xbpm3_position, xbpm2,
beamstop, polarization), or only the named ones with defaults=False.
Devices not in the config are skipped; calling it again rebuilds the plots
in the open window.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017NrH3poJsYBCTVq2Y9fuHZ
Galil readback and gain devices are now named after the beamline BPM
number, matching the stages (xbpm2x/y, xbpm3x/y) and xbpm1; the hutch and
XBox go into the description:
- bpm_xbox2_slowrb -> xbpm3_slowrb, gain_bpm_xbox2 -> xbpm3_gain
- bpm_xbox1_slowrb -> xbpm2_slowrb, gain_bpm_xbox1 -> xbpm2_gain (commented out)
- bim_xbox3_slowrb -> xbim_slowrb, gain_bim_xbox3 -> xbim_gain
- csaxs.diagnostics.bpm_xbox1/.bpm_xbox2/.bim -> .xbpm2/.xbpm3/.xbim
- bpm1 removed (duplicate of xbpm1); xbpm1c1-c4 kept
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017NrH3poJsYBCTVq2Y9fuHZ
The XBox2 BPM amplifier outputs a negative current, so more beam showed as
more negative blade values. invert: true in the device config negates the
input signals; the BPM position/diagonal ratios are unchanged and the
intensity becomes positive. Enabled for bpm_xbox2_slowrb.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017NrH3poJsYBCTVq2Y9fuHZ
Clicking into a spin box left the cursor at the end, so typed digits were
appended and silently rejected when above the maximum (e.g. golden-ratio
bunch size 100 + '5' -> 1005 > 200) or the decimal count, leaving only the
arrows to change the value. Applies to all spin boxes in the parameter panel.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017NrH3poJsYBCTVq2Y9fuHZ
With a circular FOV and stitching, corner tiles can hold far fewer Fermat
points than the center tile. A tile below the scan minimum aborts the
projection, and the retry then stops the tomogram. The point-count check
now uses the smallest tile (new lamni_smallest_tile_position_count()):
the GUI refuses submit / add-to-queue, and tomo_parameters on the command
line skips the confirm question and repeats the scan-geometry prompts
until the count is sufficient.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017NrH3poJsYBCTVq2Y9fuHZ
Stitch parameter n used to give 2n+1 tiles per direction (offsets -n..+n).
It now gives n+1 tiles placed symmetrically around the scan center
(offsets i - n/2), so stitch 1 is two tiles at +-half a step and stitch 2
is the old three-tile layout. Stored values change meaning.
- shared stitch_tile_offsets() helper in OMNY_shared
- LamNI alignment scan-number file steps by (sx+1)*(sy+1)
- tomo_parameters prompts/printout show the tile count
- tomo-params GUI lamni point estimate uses the outermost tile (n/2)
- user docs updated; omny port noted as TODO in omny/AI_docs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017NrH3poJsYBCTVq2Y9fuHZ
Rename xrayeye_rotation_center_calibration_smear_experimental() to
xrayeye_rotation_center_calibration_smear() and
find_rotation_center_smear_experimental() to find_rotation_center_smear(),
and drop the EXPERIMENTAL markers from code, tests and docs. The feature
has been tested and is in regular use.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017NrH3poJsYBCTVq2Y9fuHZ
EPICS slits sl1-3: userParameter epics_offset; SmarAct slits sl4-6:
virtual slit deviceConfig offset. From slits_calibration_report with all
slits centered and opened to 1 mm (2026-10-21).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- csaxs.slits_calibration_report(): with all slits centered at a known
opening, computes the offsets that make centers read 0 and sizes read
target_width (EPICS user_offset for sl1-3, virtual-slit config offset
for sl4-6); optional full dump of all machine/frontend/optics/endstation
devices (readings + config signals) and save to text file
- csaxs.slits_apply_epics_offsets(): writes userParameter 'epics_offset'
to the EPICS user_offset where configured and different; called at
cSAXS client startup since the IOC does not keep the offsets reliably
- slits_show_all() labels values with the motor names
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Optional, default 13 (every 30 deg, 0 and 360 inclusive). The angles
actually used are written to ptychotomoalign_scannum.txt. Values that
are not an integer >= 2 raise ValueError before anything moves.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- New loptz_shift_x/y (lamni, mm) and foptz_shift_x/y (flomni, um):
non-rotating shifts added next to manual_shift_x/y, but not snapshotted
by tomo queue jobs, so a queued optics-Z move's shift survives the
following scan jobs. Zeroed at x-ray eye alignment (flomni also on
sample change); the optics-Z position is stored as
<optz>_shift_reference for a future calibration.
- lamni: new tomo-queue action move_loptz_with_shift (limits checked,
refused on OSA collision at current losaz); flomni's
move_foptz_with_shift now sets foptz_shift_x/y.
- lamni RT controller no longer locks loptz read-only with feedback on.
- Tomo-queue GUI: live OSA-collision warning for the loptz target.
- Command-job summaries (tomo_queue_show, GUI table/tooltip/builder)
now show units via format_command_step(); shift prints carry units.
- Docs + omny TODO note.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017NrH3poJsYBCTVq2Y9fuHZ
The idle detection treated any gap between projections longer than
max(60 s, 5 x per-point exposure) as idle. A ptycho projection takes
minutes, so most of every projection was subtracted from the elapsed
time: a LamNI scan accumulated 6.8 h of "idle" in 9 h and showed an ETA
of 2 h 43 min instead of ~10.5 h.
New shared OMNY_shared/idle_time.account_projection_gap() learns the
typical gap from the scan itself (median of the last 10 normal gaps) and
only counts gaps beyond max(3 x typical, typical + 300 s) as idle.
recent_projection_gaps is reset with the other timing fields on every
fresh tomo scan (LamNI _reset_progress_for_new_scan, FlOMNI progress
defaults, queue reacquire) and kept on resume.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0129zz6QGiURiV2agXouBv4T
reset_correction() now also clears the iteration-2 lookup table (as on
FlOMNI), so it is reset at a new X-ray eye alignment and when a new
rotation center is applied. _existing_alignment() reports it too.
tomo_params: spin and combo boxes in the scrollable panel ignore the
mouse wheel and pass it to the scroll area, so scrolling cannot change
values unnoticed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0129zz6QGiURiV2agXouBv4T
laser_tracker_check_signalstrength() slept 1 s on a too-low signal and
then compared the same stale value again. Re-read it.
Add docs/plans/flomni-batched-single-point-tomo.md: one armed scan per
batch of angles for single-point tomography (not implemented).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ALDnH16dC6iyHjhe5Ey4w9
BEC_ptycho_align reads line 3 as scan_xpos and line 4 as scan_ypos (um).
lamni wrote the x correction twice, in mm (line 3 rounded to 10 um).
Write x and y X-ray-eye corrections in um instead.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ALDnH16dC6iyHjhe5Ey4w9
The alignment scan now measures 13 angles, 0 to 360 inclusive; 360 repeats
0 as a check that nothing drifted during the run. The angle list lives in
alignment_scan_angles(), shared with write_alignment_scan_numbers().
lsamrot soft limits set to -2/362 (were 0/0, i.e. none).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ALDnH16dC6iyHjhe5Ey4w9
omny.psi.ch/upload.php rejected the full-size probe/spectrum PNGs of
stitched reconstructions with HTTP 413. Full-size copies above 900 kB are
now saved as downscaled PNGs until they fit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ALDnH16dC6iyHjhe5Ey4w9
The file written before the alignment scan predicted first_scan + k per
angle, which is wrong with stitching ((2*sx+1)*(2*sy+1) scans per angle).
Predict with that stride, and rewrite the file after every angle so an
interrupted run still leaves correct numbers.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ALDnH16dC6iyHjhe5Ey4w9
Log analysis of the flOMNI beamtime 2026-10-07..12: time budget, per-point
dead time, step-by-step scan-to-scan timeline mapped to code, analysis
method/pitfalls, and ranked improvement ideas. Add TODO pointer.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Next to the X-ray eye correction and the constant shift, also print
the base shift (tomo_fovx/y_offset, from center finding / first X-ray
eye click) at 0 deg and rotated to the projection angle, as applied by
lamni_fermat_scan.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LJWYXx4SS8NgFWog81xjyf