Commit Graph
1029 Commits
Author SHA1 Message Date
x01dcandClaude Sonnet 5 fa30e11b3c fix(lamni): tolerate transient GUI heartbeat race, fix sample-name prompt order
CI for csaxs_bec / test (pull_request) Successful in 1m46s
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 1s
CI for csaxs_bec / test (push) Successful in 1m46s
xrayeye_rotation_center_calibration_isolated/smear_experimental() reproducibly
crashed with "RuntimeError: GUI is not alive" when keep_shutter_open=True, right
after a long blocking device move (interferometer feedback reset, live rotation
sweep). Root cause: bec_widgets' GUI liveness check is a Redis heartbeat with a
10s TTL refreshed from the same Qt event loop that renders live-view frames;
with live view left on continuously, a long blocking move can starve that
heartbeat past its TTL even though the GUI process is still alive. Add
_gui_call_with_retry() and use it at the on_live_view_enabled(True) call sites
that follow these blocking waits, so the transient false negative is retried
instead of crashing the calibration.

Also reorder the sample-name prompt in find_rotation_center() and
find_rotation_center_smear_experimental() to run before the alignment GUI is
shown -- showing the GUI first steals OS focus, forcing the operator to click
back to the terminal to answer the prompt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 16:01:10 +02:00
x01dcandClaude Sonnet 5 fa322bfd43 fix(lamni): allow entering 0 to disable circular FOV in Tomo Params GUI
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 1m51s
The scan already treats fov_circular==0 as "disabled" and defaults to
it, but the GUI spinbox floor of 0.1 made 0 unreachable. Lower the
floor to 0.0 and label the field so the meaning is explicit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 15:28:48 +02:00
x01dcandClaude Sonnet 5 40cbb17746 docs(lamni): explain fov check axis mapping instead of FIXME
CI for csaxs_bec / test (push) Successful in 2m15s
The stage_x_rot/fovy and stage_y_rot/fovx comparisons look swapped,
but are correct: alpha bakes in a fixed ~90 deg mechanical offset
between the piezo axes and the angle=0 beam frame that fovx/fovy are
defined in, so stage_x_rot actually tracks the beam-frame y-extent.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 15:15:10 +02:00
x12saandClaude Sonnet 5 771ee01a57 feat: migrate optics-hutch SmarAct stages to MCS2, align cross-controller compat
CI for csaxs_bec / test (pull_request) Successful in 3m48s
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 2s
CI for csaxs_bec / test (push) Successful in 2m7s
- Switch xbpm2x/xbpm2y/polrot/poly/scinx in bl_optics_hutch.yaml from the
  legacy MCS1 controller to the new MCS2 controller (mcs2-00029056.psi.ch),
  re-enabling polrot/poly with corrected axis assignments from the updated
  wiring table to avoid colliding with xbpm2x/xbpm2y on the same channel.
- Remove mcs2_config_test.yaml now that MCS2 is live on real stages.
- Give Mcs2Controller.find_reference_mark an unused hold_time parameter so
  shared call sites (smaract.py, flomni.py, omny.py, lamni_optics_mixin.py)
  that pass MCS1-style (axis, direction, holdTime, autoZero) args work
  unchanged against MCS2 devices too.
- Rename smaract_show_all/mcs2_show_all to a common show_all on both
  controllers, and have each list describe() from every registered MCS1 and
  MCS2 controller instead of only its own type.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UfjGm8MQrhCV8VaC9Tf4qx
2026-07-30 12:04:10 +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
Mirko HollerandClaude Sonnet 5 53f246a8d3 fix: address v4 scan migration review findings for flomni/lamni/omny
CI for csaxs_bec / test (pull_request) Successful in 1m52s
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 2s
CI for csaxs_bec / test (push) Successful in 2m15s
- restore omny_fermat_scan scan_name (was broken by _v4 rename)
- restore missing settling delay after LamNI feedback_disable
- make LamNI drift-correction moves consistently concurrent
- use self.actions.set for flomni rtx/rtz moves
- cap flomni corridor_size (explicit and auto-estimated) at 3um

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-29 17:12:01 +02:00
wakonig_k b813b05bb1 chore: cleanup legacy scans
CI for csaxs_bec / test (pull_request) Successful in 1m48s
CI for csaxs_bec / test (push) Successful in 3m32s
2026-07-29 14:48:35 +02:00
appel_candwakonig_k f0f7a3249a refactor(falcon): Migrate falcon to ScanServer ScanInfo model 2026-07-29 14:48:35 +02:00
wakonig_k cd13e7ed9e feat: migrate to v4 scans 2026-07-29 14:48:35 +02:00
appel_c df92754024 fix: typo in eiger_1_5 config
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 1m50s
2026-07-28 14:32:09 +02:00
appel_c f7dd245559 fix: add saxs_scan_macro 2026-07-28 14:32:09 +02:00
appel_c 8b0a95133c test: fix eiger on_stage test 2026-07-28 14:32:09 +02:00
appel_c e32c959480 fix: fix formatting eiger 2026-07-28 14:32:09 +02:00
x12saandappel_c 56297c7928 fix(eiger): fix eiger check for IDLE in on_stage 2026-07-28 14:32:09 +02:00
appel_c d1c45a9081 add azimintsettings 2026-07-28 14:32:09 +02:00
x12saandappel_c 5fd4025e89 changes from the beamline 2026-07-28 14:32:09 +02:00
x12saandappel_c a68c29c03c scanning SAXS, e23738 2026-07-28 14:32:09 +02:00
appel_c 71ad9fc12d fix(mcs): initialize _num_lines in init
CI for csaxs_bec / test (pull_request) Successful in 1m48s
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 6s
CI for csaxs_bec / test (push) Successful in 1m55s
2026-07-28 13:48:30 +02:00
x01dcandholler 2aca187c86 fix(LamNI): skip 22.5 deg approach rotation when shutter is closed
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 2s
CI for csaxs_bec / test (push) Successful in 1m51s
The k=2..8 alignment steps always rotated via a halfway "approach"
angle before the 45 deg target, to let the operator watch the sample
sweep through in live view. That's only useful when keep_shutter_open
is True; with the shutter closed nobody sees the intermediate move, so
just rotate straight to the target angle in that case.

Also bump the OMNY/FlOMNI post-fshopen() freeze-frame delay in
update_frame() from 0.5s to 1s to match LamNI's, for consistent
behavior between the two plugins.
2026-07-28 13:35:05 +02:00
x01dcandClaude Sonnet 5 89b185eae2 fix(deps): make pygobject an optional extra, not a hard dependency
CI for csaxs_bec / test (pull_request) Successful in 1m47s
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 2s
CI for csaxs_bec / test (push) Successful in 1m51s
pygobject ships no PyPI wheels, so pip install always compiles it from
source, which requires the OS gobject-introspection dev package at
install time. As a mandatory dependency this broke plain `pip install
csaxs_bec` on CI and on Read the Docs, neither of which has that
package installed. Move it to the `allied_vision` extra so only hosts
that actually run the camera (which already need Aravis + the OS
package present) opt in via `pip install csaxs_bec[allied_vision]`.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 13:25:25 +02:00
x01dcandholler 27a40518af fix(LamNI): revert xray eye IDS camera to default 5 Hz poll rate
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 2s
CI for csaxs_bec / test (push) Successful in 1m51s
The live_mode_poll_interval_s: 0.02 override (50 Hz) made the GUI
unusably laggy. Remove it so cam_xeye falls back to the class
default of 0.2 s (5 Hz).
2026-07-28 13:23:37 +02:00
x01dc 107981f392 fix(devices): remove deprecated XOMNYI-XEYE-ACQ:0 EPICS PV writes
CI for csaxs_bec / test (pull_request) Successful in 1m52s
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 1s
CI for csaxs_bec / test (push) Successful in 1m49s
This PV belonged to the old EPICS/LabView X-ray-eye acquisition system
that both LamNI and OMNY alignment have already replaced with the
BEC-native cam_xeye (IDSCamera) device and GUI-driven workflow. The PV
no longer has a listener, so the write only produced a "cannot connect"
warning at the start of LamNI's tomo_alignment_scan() (via leye_out())
and OMNY's oeye_out() -- remove both, plus the now-dead epics_put
imports left behind in lamni_optics_mixin.py, omny_optics_mixin.py, and
flomni_optics_mixin.py, and a leftover print() in flomni's
x_ray_eye_align.py that referenced the same PV without ever writing it.
2026-07-28 12:16:41 +02:00
654f8be4eb feat(devices): add FZP details user parameter to optics stages
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 2s
CI for csaxs_bec / test (push) Successful in 1m55s
Adds a free-text "fzp_details" userParameter (default "manufacturing
notes here") to the loptx/foptx/ofzpx optics-stage devices for LamNI,
flomni and OMNY, alongside the existing fzp_diameter/
fzp_outermost_zone_width parameters, and prints it in each beamline's
tomography-start PDF report.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 11:54:15 +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 c42595922d fix(devices): defer Aravis import-guard from Camera.__init__ to on_connect()
CI for csaxs_bec / test (pull_request) Successful in 1m59s
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 3s
CI for csaxs_bec / test (push) Successful in 2m0s
Camera.__init__ raised ImportError unconditionally whenever the Aravis
GObject-Introspection library wasn't importable, even with connect=False --
contradicting the module's own "lazy initialization" docstring and
breaking every unit test in CI, since Aravis is a system library (not
pip-installable) that CI never has installed. The test fixture builds a
real AlliedVisionAravisCamera(connect=False) and only mocks camera.cam
afterward, so the raise fired before mocking ever got a chance to run.

Move the guard into on_connect(), mirroring IDSCamera's working pattern
(its equivalent check lives in the object only built by on_connect(),
never at construction time). Construction is now independent of whether
Aravis is installed; on_connect() still raises the same clear error the
moment something actually tries to talk to hardware.
2026-07-28 10:46:50 +02:00
x01dc 2bd161cd63 config(devices): drop allied_vision_test.yaml, add commented example to ptycho_omny
allied_vision_test.yaml was only ever a scratch config for exercising the
camera during bring-up; the same commented allied_vision_cam example
already lives in bl_detectors.yaml, so keep that one and add the matching
commented block to ptycho_omny.yaml instead of a separate file.
2026-07-28 10:46:41 +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
x01dc a96d24a3cc fix(devices): use real camera_id, disable auto live-mode, pin pygobject
Update the placeholder camera_id in allied_vision_test.yaml/bl_detectors.yaml
to the Aravis device ID discovered on the actual Alvium G1-507m hardware,
and set live_mode back to False (explicit, not deleted) so the camera stays
idle until start_live_mode() is called -- matching every real IDS camera
config, instead of auto-starting its live-mode polling thread as soon as
the device connects.

Pin pygobject<3.52 in pyproject.toml: 3.52+ requires girepository-2.0
(GLib >=2.80/gobject-introspection >=1.80), which this RHEL9 host's system
packages don't provide (only the older girepository-1.0 via
gobject-introspection 1.68) -- unpinned pip install fails at build time.
Document both the camera_id lookup and the pin in the README.
2026-07-28 10:16:18 +02:00
x01dc 13e9cb21e4 fix(LamNI): update tests for prompts/kwargs added earlier this branch
CI for csaxs_bec / test (pull_request) Successful in 1m45s
Read the Docs Deploy Trigger / trigger-rtd-webhook (push) Successful in 2s
CI for csaxs_bec / test (push) Successful in 1m59s
Several tomo_scan()/tomo_alignment_scan()/find_rotation_center() tests
started failing (CI) after recent commits on this branch introduced new
input()-backed confirmation/sample-name prompts, an
alignment_scan_progress GUI proxy, and tomo_queue_execute()'s
interactive=False kwarg -- none of which the existing test fixtures or
assertions were updated for. Mock/bypass the new prompts and GUI calls,
add the missing _alignment_scan_progress_proxy to the bare-object test
fixture, and update two assertions (tomo_queue interactive kwarg,
account-less sample registration) to match the intended new behavior.
2026-07-28 09:53:59 +02:00
x01dc 56467682a9 config(LamNI,flomni): add FZP params to the simulated device configs too
CI for csaxs_bec / test (push) Failing after 4m6s
CI for csaxs_bec / test (pull_request) Failing after 2m3s
simulated_lamni.yaml/simulated_flomni.yaml define their own separate
loptx/foptx (not shared with ptycho_lamni.yaml/ptycho_flomni.yaml) --
missed these when adding fzp_diameter/fzp_outermost_zone_width/
detector_distance earlier, so a simulated-only session wouldn't have
had them. Same values (170 micron, 60 nm, -1).
2026-07-27 17:49:05 +02:00
x01dc 79f257f072 feat(LamNI,flomni): add PSI logo to every PDF report page footer
Downloaded from https://intranet.psi.ch/themes/custom/design/logo.svg
(no gradients/filters/embedded fonts -- confirmed fpdf2 renders it
directly, no PNG conversion needed) and stored as psi_logo.svg in
OMNY_shared. Added TomoQueueMixin._add_psi_footer(), which overrides
the fpdf instance's footer() callback (PDFWriter/BECPDF live in
bec_lib, a separate repo with no public API for this) so the logo
repeats on every page -- unlike the header logo, which is drawn once
inline, a report can span multiple pages (e.g. a long
at_each_angle_hook source dump). Also drops the microseconds from the
existing "BEC, <timestamp>" footer text while reimplementing it, per
request ("ms precision is not needed"). Verified end-to-end with
bec_lib's real PDFWriter: a 300-line hook source forced a 7-page
report, with the logo correctly repeating on every page.
2026-07-27 17:48:57 +02:00
x01dc 6c06b63ece fix(LamNI,flomni): FZP diameter/zone-width wrongly blanked to N/A
fzp_diameter_um/fzp_zone_width_nm were read inside the same try block
as the focal-distance calculation, which also needs energy_kev. When
the photon energy read fails (as it does in at least one simulated
session -- confirmed live: dev.ccm_energy unavailable), the exception
wiped out the diameter/zone-width display too, even though those come
from config (loptx/foptx userParameter) and were read just fine.
Split into two independent try blocks: diameter/zone-width no longer
depend on a working energy read, only the focal distance itself does.
2026-07-27 17:48:26 +02:00
x01dc 1b6b6a41a1 feat(LamNI,flomni): add FZP optics info to the PDF report
Adds FZP diameter, outermost zone width, focal distance,
focus-to-sample distance, and sample-to-detector distance to
write_pdf_report(). Diameter/zone-width/detector-distance come from
the userParameter entries just added to loptx/foptx; focal distance
is computed with the same formula lfzp_info()/ffzp_info() already use
(diameter * zone_width / wavelength); focus-to-sample distance reuses
their existing live z-stage-based calculation rather than storing a
separate value. Replaces this exact old SPEC workflow
(_tomo_other_parameters interactively asking for these same numbers
every time) with values read automatically from config + live
hardware.

Also fixes FlOMNI's "Current photon energy: To be implemented"
placeholder (never wired up) -- needed a real value for the new focal
distance calculation anyway, and dev.ccm_energy is the same device
ffzp_info() already reads.
2026-07-27 17:43:53 +02:00
x01dc e7df1209d1 fix(LamNI): lfzp_info() printed focal distance in meters labeled as mm
focal_distance was computed in meters (consistent with the rest of the
function, e.g. beam_size's own internal *1000 conversions), but the
table row printed it directly as "X.XX mm" with no conversion -- off
by 1000x (e.g. showing "0.05 mm" instead of "51.34 mm"). FlOMNI's and
OMNY's equivalent ffzp_info()/ofzp_info() already convert correctly;
fix just the display here to match, without touching the
meters-based internal variable beam_size still depends on.
2026-07-27 17:35:33 +02:00
x01dc 8b3a65606c config(LamNI,flomni): add FZP diameter/zone-width/detector-distance params
Adds fzp_diameter (170 micron), fzp_outermost_zone_width (60 nm), and
detector_distance (-1, unknown for now) as userParameter entries on
loptx/foptx. LamNI's values match FlOMNI's already-documented active
FZP (per its "#170 micron, 60 nm" comment) -- confirmed with the user
that LamNI currently uses the same optic. Feeds the new PDF report
fields in the next commit.
2026-07-27 17:35:10 +02:00
x01dc 6954fbb7f4 refactor(OMNY): move omny_general_tools.py into OMNY_shared
CI for csaxs_bec / test (push) Failing after 2m27s
OMNYTools, PtychoReconstructor, and TomoIDManager were sitting under
the omny plugin's own directory, but are imported by LamNI, FlOMNI,
and cSAXS too -- none of the three classes reference anything
OMNY-specific (device names are always passed in as parameters).
OMNY_shared already exists for exactly this kind of cross-setup code
(tomo_queue_mixin.py, web_common.py, webpage_generator_base.py), so
move it there and update all five import sites. Pure relocation, no
behavior change.
2026-07-27 17:19:22 +02:00
x01dc 97ea67b01a fix(flomni): use the real setup logo in the PDF report, fix column gaps
CI for csaxs_bec / test (push) Failing after 11m52s
Mirrors LamNI.write_pdf_report()'s same fix: replace the ASCII-art
header with the actual flOMNI.png logo (already correctly resolved
for the scilog attachment, just never used in the PDF itself),
embedded via PDFWriter's underlying fpdf object. Also left-justify
values instead of right-justifying them in a wide fixed field, to
remove the big ragged gap after short labels. Drops a leftover debug
print(logo_file).
2026-07-27 17:13:57 +02:00
x01dc f8ced692d3 fix(LamNI): use the real setup logo in the PDF report, fix column gaps
Replace the ASCII-art header with the actual LamNI.png logo, embedded
via PDFWriter's underlying fpdf object (bec_lib's PDFWriter has no
public image API). Also fix the label/value formatting: values were
right-justified in a wide fixed field, leaving a big ragged gap after
short labels -- left-justify both instead for a clean, tight
"label: value" layout.

Also fixes a real bug found along the way: the scilog attachment
referenced "LamNI_logo.png", a file that has never existed (the actual
file is LamNI.png) -- the resulting FileNotFoundError was swallowed by
write_pdf_report()'s generic try/except, so the scilog message has
been silently failing to send every time. Now uses the one correct,
shared logo_path for both the PDF and the scilog attachment.
2026-07-27 17:13:49 +02:00
x01dc eb61df1c93 fix(OMNY): use requests instead of shelling out to wget for tomo ID
CI for csaxs_bec / test (push) Failing after 11m43s
TomoIDManager.register() called wget via subprocess with shell=True,
interpolating sample_name/eaccount/etc. unescaped into the command
string -- broke outright wherever wget isn't installed (as hit while
testing: "wget: command not found", silently falling back to tomo ID
0), and was a latent shell-injection risk. Use requests.get() with a
params dict instead: no external binary dependency, proper URL
encoding, and the same self-signed-cert/SSRF handling already used by
the samples PDF upload. Drops the now-unused OMNYToolsError class and
TMP_FILE/subprocess, which only existed to support the wget call.
2026-07-27 17:06:10 +02:00
x01dc 3422eedcc1 fix(OMNY): call tomo_scan(interactive=False) from tomo_queue_execute()
CI for csaxs_bec / test (push) Failing after 5m0s
Wires the queue-safe fine-alignment warning (previous LamNI/Flomni
commits) into the actual queue dispatch path.
2026-07-27 17:02:17 +02:00
x01dc d97692e090 fix(flomni): always attempt tomo_id registration, accept interactive kwarg
Mirrors LamNI.tomo_scan()'s same fix: remove the outer
"bec.active_account != ''" short-circuit so an empty/test account still
goes through add_sample_database() -> TomoIDManager.register() (which
now handles test-host registration itself) instead of hard-coding
tomo_id=0. Also accept an unused interactive kwarg for signature
compatibility with LamNI.tomo_scan(), since tomo_queue_execute() (shared
between both setups) calls tomo_scan(interactive=False) uniformly.
2026-07-27 17:02:05 +02:00
x01dc 1159b018f0 fix(LamNI): don't block the tomo queue on the fine-alignment check
tomo_queue_execute() runs queued scans unattended, potentially for
hours -- tomo_scan()'s fine-alignment prompt would block forever there
with nobody watching. Add interactive: bool = True; when False (queue
use), the check no longer prompts or aborts -- it prints a bold red
warning, waits 10s, and always proceeds.

Also remove the outer "bec.active_account != ''" short-circuit that
hard-coded tomo_id=0 for an empty account without even attempting
registration -- always call add_sample_database() now and let
TomoIDManager.register() (test-host registration, previous commit)
decide the right outcome instead of pre-empting it here.
2026-07-27 17:01:52 +02:00
x01dc 64f5a57fa1 feat(OMNY): add OMNYTools.printredbold()
Mirrors the existing printgreenbold() -- needed for the tomo_scan()
unattended-queue warning (bold red instead of bold green).
2026-07-27 17:01:31 +02:00
x01dc fe47059f88 fix(OMNY): skip PDF upload without a real tomo_id, widen error logging
tomo_id == FALLBACK_TOMO_ID (0) means add_sample_database() never
actually registered a measurement server-side, so there's no reserved
"new.pdf" slot -- uploading anyway would silently claim whatever
number countersaver.txt currently holds, i.e. an unrelated real
measurement's slot. Skip with a clear message instead. Also widen the
truncated response text in the upload warning/log messages (120 -> 400
chars), which had cut off the file+line a real PHP error would show,
making a live parse-error response undiagnosable from the client log
alone (as happened while testing this).
2026-07-27 16:58:43 +02:00
x01dc b95c284de9 feat(OMNY): register test-account measurements against the test server
TomoIDManager.register() used to skip OMNY registration entirely for
any non-e-account (e.g. test accounts), always returning the tomo ID
0 fallback. Register against a new TEST_OMNY_URL (omny-test.psi.ch)
instead for those accounts, so testing still gets a real, incrementing
tomo ID matching the counter the samples-folder PDF upload reads from
on that same host -- accepting a mismatched eaccount in that test
database. FALLBACK_TOMO_ID is now reserved for genuine failures
(server unreachable), not merely a non-standard account name.
2026-07-27 16:58:33 +02:00
x01dc e911f8d5e3 feat(LamNI): warn (overridable) when alignment steps are stale or missing
Nothing previously enforced the intended sequence: rotation-center
calibration -> X-ray-eye alignment -> fine alignment scan -> real
tomogram. Add three soft gates -- xrayeye_alignment_start() (no center
found yet), tomo_alignment_scan() (X-ray-eye fit missing/invalidated,
softened from a hard abort), and tomo_scan() (no fine alignment
loaded) -- each printing a specific warning and prompting to continue,
via a new shared _confirm_sequence_override() helper. Not a hard
block: each method also gets force: bool = False to skip the check
entirely for cases that legitimately don't need it (e.g. a large FOV
that doesn't need fine alignment).
2026-07-27 16:58:21 +02:00
x01dc 9fc0770055 feat(LamNI): invalidate X-ray-eye/fine alignment on a new rotation centre
Re-running rotation-center calibration after X-ray-eye alignment (or
fine alignment) was already done left the stale fit/correction in
place, silently calibrated around the old center. Record
lamni_center_found_at and cascade-invalidate via the existing
reset_xray_eye_correction()/reset_correction() whenever a new center
is actually applied, in both find_rotation_center() and
find_rotation_center_smear_experimental().
2026-07-27 16:58:11 +02:00
x01dc 297b0dd7d3 fix(flomni): stop calling write_pdf_report() twice per scan start
CI for csaxs_bec / test (push) Failing after 4m28s
tomo_scan()'s new-scan branch called write_pdf_report() once inside
the "real e-account" if-branch and again unconditionally right after,
so every scan start under a real account wrote the PDF, sent the
scilog entry, and (as of the previous commit) uploaded to the samples
folder twice. Keep only the unconditional call, matching LamNI's
equivalent structure.
2026-07-27 16:15:15 +02:00
x01dc cdc20457f1 feat(OMNY): upload tomo PDF report to the samples web folder
Replaces the old, already-broken upload_last_pon.sh shell-out (and
assorted other dead/abandoned upload attempts left commented out in
flomni.py) with a direct HTTP upload: POSTs the just-written PDF,
base64-encoded, to omny-test.psi.ch/samples/upload.php with
filename="new.pdf" so the server assigns the number itself from its
own counter file -- the same counter newmeasurement.php
(TomoIDManager.register(), called via add_sample_database() just
before write_pdf_report()) already incremented and returned as
self.tomo_id. Runs in a background thread so a slow/unreachable host
never delays the calling tomo_scan(), and cross-checks the response
against the expected filename to flag a possible race with a
concurrent registration.

Added to TomoQueueMixin (OMNY_shared) rather than duplicated in both
LamNI and Flomni, following add_sample_database()'s existing pattern
of shared, setup-agnostic tomo-id/database logic.
2026-07-27 16:15:04 +02:00