docs/document remaining flomni->lamni feature gaps for triage

Follow-up sweep after this session's ports (timing overview, scan
interruption handling, tooltip filtering, constant shift, hook
display, zero-deg reference). Found and verified 9 items: a missing
per-projection/tomogram timing log + scilog_last_ptycho_scans()
command, no reset-tomo-params-on-account-change offer, no
collect_empty_frames() flat-field acquisition, no skip-if-already-in
optimization on lfzp_in(), no hard-stop button wired into lamni's
GUI, tomo_alignment_scan() with no clear lamni equivalent (lamni has
a different lookup-table correction scheme instead -- needs
discussion, not necessarily a gap), no OSA-collision-clearance
warning in lfzp_info(), a large confirmed-hardware-specific block
(sample-transfer/gripper/laser-tracker methods, not portable), and a
webpage-display opportunity that's symmetric on both setups rather
than a one-sided gap. No code changes -- findings only, for review.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
x01dc
2026-07-21 04:33:29 +02:00
co-authored by Claude Sonnet 5
parent 8733b6cf91
commit 4f938fc543
@@ -0,0 +1,167 @@
# flomni → lamni feature gaps still open (2026-07 sweep)
Follow-up to `FLOMNI_TO_LAMNI_COMPARISON.md` (flomni's `AI_docs/`) and this
folder's `TOMO_QUEUE_PORT.md`/`TOMO_PARAMS_GUI_PORT.md` — those covered the
tomo-queue backend, the GUI, the webpage generator, and the angle-distribution
mapping, all since ported. This sweep looked for *further* flomni features
lamni still lacks, after the same session also ported: the end-of-scan timing
overview + `scan_repeat`/`scan_interlock` interruption handling, tomo-queue
tooltip filtering, the constant-shift print, `at_each_angle_hook` in
`tomo_parameters()`, and `zero_deg_reference_at_each_subtomo` for tomo_type 1.
Every item below was independently confirmed by direct grep/read against
both files, not just taken from the sweep — file:line citations are given so
you can jump straight to the code. Ordered roughly by how promising each is
to port, most-actionable first. This is a findings list for triage, not an
implementation plan — nothing here has been started.
## 1. Per-projection/tomogram timing log + `scilog_last_ptycho_scans()` — missing entirely
- flomni: `flomni.py:2945` (`_TIMING_LOG_DIR`), `_log_projection_timing()`
(`2971`), `_log_tomogram_timing()` (`3019`), `_read_last_timing_records()`
(`3056`), `scilog_last_ptycho_scans()` (`3082`).
- lamni: none of these exist anywhere in `lamni.py`.
- flomni appends a JSON-lines record per completed projection and per
completed tomogram (FOV, exposure, stitch, corridor, duration, scan-number
range) to `~/data/raw/logs/timing_statistics/*.jsonl`, feeding a future
scan-time-prediction model, and exposes `scilog_last_ptycho_scans(n)` — a
user command that writes a scilog entry summarizing the last *n*
projections (scan numbers/FOV/exposure/duration) with a free-text comment
prompt.
- **Portable**: the mechanism only needs `_TOMO_SCAN_PARAM_NAMES` (lamni
already has via `TomoQueueMixin`) and generic file I/O — nothing
flomni-hardware-specific.
- Size: medium — new logging infra, but the shape can be lifted close to
verbatim.
## 2. Tomo-parameter reset offer on experiment-account change — missing entirely
- flomni: `Flomni.__init__` calls `_maybe_reset_params_on_account_change()`
(`flomni.py:1656`, defined `1662`) — compares the live BEC account against
a persisted `defaults_applied_for_account` global var and, on a genuine
account change, offers to reset tomo params via `_set_default_tomo_params()`
(`1694`).
- lamni: `LamNI.__init__` has no such call, no `defaults_applied_for_account`
anywhere in `lamni.py`.
- Prevents a new user silently inheriting the previous experiment's tuned
FOV/stitch/etc.
- **Portable**: pure session-lifecycle/UX logic, no hardware dependency.
- Size: small.
## 3. `collect_empty_frames()` — flat-field acquisition at the start of a new tomo scan — missing entirely
- flomni: `collect_empty_frames()` (`flomni.py:2419`), called unconditionally
from the "new scan" branch of `tomo_scan()` (`2533`, right after
`write_pdf_report()`/progress reset — only on a genuinely new scan, not a
resume).
- lamni: zero occurrences of `collect_empty_frames`/"empty frame"/"flat
field" anywhere in `LamNI/*.py`.
- Acquires 10 flat-field images at angle 0 with the sample shifted out of the
beam by half the FOV, logged with `subtomo_number=0` but deliberately kept
out of `tomo_reconstruct()`'s queue.
- **Judgment call, not purely a software gap**: whether this is worth porting
depends on whether lamni's ptycho reconstruction pipeline actually
uses/needs flat fields the way flomni's does — worth confirming with Mirko
before implementing, not just a code-porting decision.
- Size: small-medium (geometry needs adapting to `tomo_circfov`/lamni's
offset properties, but the shape is a direct port).
## 4. `lfzp_in()` has no "skip the reset cycle if already in position" optimization
- flomni: `ffzp_in(force_feedback_reset=False)` (`flomni_optics_mixin.py:98`)
+ `_ffzp_is_in()` (`132`) — skips the expensive feedback-disable +
`feedback_enable_with_reset()` cycle when the FZP doesn't actually need to
move, avoiding an unnecessary interferometer re-zero/position shift during
repeated alignment scans.
- lamni: `lfzp_in()` (`lamni_optics_mixin.py:237`) always runs the full
cycle unconditionally — no `_lfzp_is_in()`-equivalent guard.
- **Portable**: identical underlying `dev.rtx.controller.feedback_disable()`/
`feedback_enable_with_reset()` API, used the same way by both setups.
- Size: trivial-to-small — add an `_lfzp_is_in()` check + a
`force_feedback_reset` kwarg, direct port of the pattern.
## 5. No hard-stop button wired into lamni's GUI
- flomni: `flomnigui_show_cameras()` (`flomni/gui_tools.py:143-150`) wires up
a `ConsoleButtonsWidget` (`hard_stop_device_name="ftransy"`,
`extra_hard_stop_device_name="foptx"`) calling the shared, generic
`GalilController.hard_abort_and_restore_positioning_mode()` — added
specifically to replace an older blind stop-all-devices broadcast that
could crash the scan worker thread.
- lamni: `LamNI/gui_tools.py` has no `ConsoleButtonsWidget`/hard-stop wiring
at all.
- The original commit message explicitly notes this was "scoped to flomni
only this session (OMNY/LamNI wiring deferred)" — a known, flagged to-do,
not an oversight.
- **Portable** (the widget + `GalilController` method are already
generic/shared), but needs a home in lamni's GUI first — lamni has no
gripper-camera dock to piggyback on the way flomni does, so this needs a
decision on where it lives and which lamni Galil device(s) it targets.
- Size: small-medium. Safety-relevant — worth prioritizing despite the extra
design step.
## 6. `tomo_alignment_scan()` — no lamni equivalent, but may be architecturally superseded
- flomni: `tomo_alignment_scan()` (`flomni.py:2037`) — dedicated 5-point
(0/45/90/135/180°) alignment tomogram, writes scan numbers to
`~/data/raw/logs/ptychotomoalign_scannum.txt` for an external MATLAB tool
(`BEC_ptycho_align`), loaded back via `get_alignment_offset()`/
`read_alignment_offset()` (`1439`, `1337`).
- lamni: no `tomo_alignment_scan`/`write_alignment_scan_numbers` anywhere.
Instead has a *different* mechanism: `read_additional_correction()`/
`read_additional_correction_2()` (`lamni_alignment_mixin.py:285,291`) — a
lookup-table correction (`corr_pos_x/y` vs `corr_angle` bins) from an
externally-produced file, consumed by `compute_additional_correction()`.
- **Needs discussion, not a clear-cut gap**: is lamni's lookup-table scheme a
deliberate replacement for flomni's 5-point/MATLAB-fit approach, or would
lamni users also want a quick dedicated alignment-tomogram command? Don't
assume either way — ask before scoping.
- Size: needs its own design discussion if pursued at all.
## 7. No OSA-collision-clearance warning in `lfzp_info()`
- flomni: `ffzp_info()` (`flomni_optics_mixin.py:256`) compares live `fosaz`
against the nominal `fosaz_in` position (10 µm tolerance) and warns if the
OSA is currently closer to a collision than its defined IN position.
- lamni: `lfzp_info()` (`lamni_optics_mixin.py:291`) only prints
sample-to-FZP distance and a diameter/focal-distance/beam-size table — no
collision-clearance section.
- **Needs lamni-specific input**: the concept (warn if a movable optic is
closer to a known collision point than nominal) is generic, but the exact
formula (`33 - foptz_val` in flomni) is specific to flomni's optics
geometry — porting correctly needs lamni's own collision-geometry
constants, not just a code copy.
- Size: small once the geometry constants are known.
## 8. Large block of flomni-only methods — confirmed hardware-specific, not portable
`FlomniSampleTransferMixin` (`flomni.py`, ~46 methods): `ftransfer_*`,
gripper open/close/move, `save_reference_image()`, `laser_tracker_show_all`/
`on`/`off`, `laser_parameters_*`, `laser_tweak`,
`umvr_fsamy_tracked`/`umv_fsamy_tracked` — all depend on flomni's automatic
gripper/tray sample changer and its `rtx`-integrated laser tracker, neither of
which lamni has (lamni samples are mounted manually — existing, known
constraint). Listed only so you can confirm none of these were expected to
have a lamni counterpart; not recommended for porting.
## 9. `zero_deg_reference_at_each_subtomo` not yet on either status webpage — shared opportunity, not a flomni-ahead-of-lamni gap
Neither `flomni_webpage_generator.py`'s `_CURRENT_PARAM_KEYS`
(`flomni_webpage_generator.py:62-76`) nor `LamNI_webpage_generator.py`'s
`TQ_PARAM_DISPLAY` (`LamNI_webpage_generator.py:71-86`) show
`zero_deg_reference_at_each_subtomo` (or, for lamni's tomo_type 2/3, its
`golden_projections_at_0_deg_for_damage_estimation` sibling). Since it's
missing symmetrically on both, there's no flomni feature to "port" here —
just a possible small addition to both webpages if useful, now that lamni's
tomo_type 1 property actually exists.
## Checked and already at parity (not gaps)
`write_to_scilog`/`_scilog_write` failure tolerance, `@scan_repeat`
retry-skip-on-definite-error, `frames_per_trigger` validation, `corridor_size`
conditional passing, `estimated_finish_time` progress field, measurement-ID
in the end-of-scan scilog summary, `at_each_angle_hook` name in that same
summary, x-ray-eye alignment image HDF5 saving, tomo-queue command-jobs/
move/reorder-floor semantics, and `tomo_params.py`'s `SETUP_PROFILES`
capability flags (including `has_zero_deg_reference`, now symmetric) — all
confirmed present and equivalent on both sides.