Files
scanengine-3/KNOWN_ISSUES.md
T
Thomas Ales aa06fa1460 Per-angle background capture: v7/v11 .sras layout
A multi-angle scan runs for hours, but every angle was referenced against
one background captured before the first row of the first angle. That
reference has drifted by the last angle, and comparing angles — the whole
point of a multi-angle scan — was comparing each one against a noise floor
measured at whichever angle came first.

Every angle now captures its own. Before each angle's rows, the operator is
prompted to switch the Genesis laser off, the engine averages a fresh CH1
record, and the operator switches it back on. The data block therefore reads
[background][scan][background][scan] …, one pair per angle.

Format v7 (scan) and v11 (SAW check) carry the background inside the data
block, one length-prefixed block ahead of each angle's rows; the single
block that sat between the preambles and the data is gone. Per-angle offsets
now come from a walk of the data block at parse time rather than arithmetic
over the geometry table, and an angle whose background is not fully on disk
is the frontier — nothing of it was written yet.

v6/v10 files still read: SrasFile hands their one background to every angle,
so readers never branch on the version. Nothing writes them, and a resume
refuses them, since a re-acquired angle writes a block the old layout has no
room for. A resumed v7 angle rewrites its background in place, and the
engine checks the new block fits the room the file has before writing it —
anything else would shift every row behind it.

Two fixes made along the way:

  * QtScanController never accepted file_version, so every scan launched
    from the app raised TypeError at construction.
  * angle_status() left its cursor parked at the frontier, so every angle
    past it reported the frontier's own data_offset — which handed a resumed
    scan the same write position for several angles. Two recorded offsets in
    tests/golden/sras_expected.json are corrected accordingly.

The v6 goldens stay as parser fixtures; the writer is now locked against
bytes the test lays out from scan_format.md itself.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 12:44:25 -05:00

3.3 KiB

Known issues requiring on-rig verification

Questions that cannot be answered from the code alone. Check these the next time the hardware is available; each one gates a small code change.

uC480 camera: gain/exposure during active capture

The driver used to carry an (unused) _capture_paused context manager whose docstring claimed many IDS cameras return IS_CANT_COMMUNICATE_WITH_DRIVER (17) or IS_NO_SUCCESS (-1) when gain/exposure commands are issued during active capture. set_exposure() and set_gain() never used it, and the helper was deleted in the Phase-1 cleanup.

Bench check: with live streaming running, move the exposure and gain sliders in camera_test_app.py and watch the log for those error codes. If they appear, the setters need a stop-live/apply/restart sequence (re-create the helper around the two call sites in uc480_camera.py).

Helios: no output-power query

docs/hardware/HELIOS_DRIVER_README.md documents driver.get_power_mw(), but HeliosLaser has no such method and no output-power mnemonic appears anywhere in this repo's protocol notes. helios_test_app.py called it anyway and raised AttributeError into a popup; the button is now disabled and the handler reports the gap instead.

Bench check: find the power-read command in the Helios manual (the other reads are three-letter mnemonics like LDO, LDS, LTA). If one exists, add get_power_mw() to hardware/helios_laser.py using _query_int, then re-enable the button. If it doesn't, delete the Power Monitoring group from the test app and fix the README.

Genesis laser: forked protocol implementations disagree

hardware/genesis_core.py and the reference implementation tools/genesis_laser_gui.py disagree on ADC command bytes, LDD enable polarity, shutter semantics, filtering, and scaling. Do not modify either until the checklist in docs/genesis_verification.md has been run on the bench.

lib/ueye_loader.so — still needed?

lib/ueye_loader.c is an LD_PRELOAD shim that dlopens /usr/lib/libueye_api.so — yet nothing in the repo references it, and the vendored SDK copy is lib/libueye_api64.so.3.82 (a different file). On the rig, check whether the camera apps run without the shim; if they do, delete lib/ueye_loader.{c,so}. Either way, record in SETUP.md where libueye_api64.so.3.82 came from (IDS SDK version) and how the loader is meant to be used.

Per-angle background: trigger round trip mid-scan

Every angle now captures its own background, so the scope switches from the scan-time logic-AND trigger back to the single-record edge trigger and returns to it once per angle (core/scope_sras.py: configure_background_trigger → capture_background → configure_scan_trigger). Before this, that transition happened once per scan, with the stage idle and nothing depending on how long it took.

Bench check: run a multi-angle scan and watch the first row after each background. If frames go missing at the start of an angle, the 0.2 s settle in configure_scan_trigger is not enough for FastFrame to re-arm after an AVERAGE-mode sequence, and the row-packing warning ("N frames acquired, M expected") will say so in the log. Raise the settle rather than the ramp buffer — the stage geometry is not what changed.