Files
csaxs_bec/docs/developer/panda_box_free_running_data_schema.md
x12saandClaude Sonnet 5 f93e591227
CI for csaxs_bec / test (push) Successful in 2m13s
feat(flomni): split omny_panda into two devices, fix free-running completion check
Mode A (per-gate aggregate) and Mode B (continuous raw-sample) need
different PandA hardware layouts and can't run simultaneously, so
omny_panda is now two device config entries in ptycho_flomni.yaml:
omny_panda (legacy, kept commented as the restore reference) and
omny_panda_continuous (raw_stream_mode: true, enabled).

Also fixes on_complete for the continuous case. PCAP.CAPTURED can't be
used to detect end-of-acquisition on this layout: CLOCK1 drives
PCAP.gate/trig continuously, so the captured count never naturally
stops increasing while armed -- the previous settle-based wait would
have just run out its timeout. COUNTER1 (frame_counter) instead counts
completed exposures directly (triggered on the detector-trigger's
falling edge), so PandaBoxOMNY now waits for it to reach the exact
expected num_points * frames_per_trigger, mirroring the legacy
exact-count check instead of guessing when capture has "settled".

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TsfqLcPWspjJ6vedMyCxco
2026-09-15 14:22:28 +02:00

4.5 KiB

PandABox free-running (raw_stream_mode) raw data schema

Status: schema for the acquisition side only. This document defines what raw data omny_panda writes to its HDF5 async dataset when raw_stream_mode: true (see docs/developer/panda_box_free_running_setup.md for the hardware/mode setup, confirmed against real PandA hardware 2026-09-15). Reconstructing the previous averaged/stdev-per-position view from this raw data (binning by the gate_detector_active transitions or timestamps) is a separate, not-yet-planned analysis task and is intentionally out of scope here.

Where this data lands

omny_panda is configured with readoutPriority: async (csaxs_bec/device_configs/ptycho_flomni.yaml). Its data signal is a DynamicSignal (ophyd_devices/devices/panda_box/panda_box.py) that BEC's async file writer appends to an HDF5 dataset per scan, under this device's async data group. In raw_stream_mode, each write corresponds to one coalesced flush (see the setup doc's mode-comparison table), not one raw PandA network frame — the row-level data below is still preserved exactly, just batched differently for publishing efficiency.

Per-row fields

Each row corresponds to one PCAP capture tick (one raw sample at the free-running capture rate — CLOCK1's configured rate, started at 100 Hz for initial testing on 2026-09-15, see the setup doc for the current rate):

Field (BEC signal name) Source PandA block Meaning
cap_voltage_fzp_y/cap_voltage_fzp_x etc. (raw analog/encoder value) FMC_IN.VAL1.Value / FMC_IN.VAL2.Value / INENC1-4.VAL.Value The instantaneous raw sample at this capture tick, replacing the Mode A aggregate (Mean/Min/Max). All six channels (both FMC analog inputs and all four encoders) are switched to raw capture together on this layout — not a subset.
gate_detector_active PCAP.BITS0.Value, bit 0 (TTLIN1.VAL), masked in software — see setup doc The detector-trigger signal, sampled at this same tick: 1 while a detector trigger is active, 0 otherwise. PCAP.BITS0 is a shared 32-bit word; PandaBoxOMNY masks it down to bit 0 before this reaches the HDF5 file (see _GATE_BIT_OFFSET in panda_box_omny.py) — the raw word itself is not a clean 0/1. This is what a future reconstruction step would use to delimit which raw samples belong to which detector-gate window.
frame_counter COUNTER1.OUT.Value, triggered off TTLIN1.VAL's falling edge (i.e. increments once per completed detector exposure, not once per PCAP capture tick as originally guessed here) Monotonically incrementing hardware counter. Doubles as the completion signal for on_complete (PandaBoxOMNY._on_complete_free_running, panda_box_omny.py) — waits for it to reach num_points * frames_per_trigger, since *PCAP.CAPTURED? free-runs continuously and never naturally stops while armed. Also the post-hoc data-completeness record: a gap-free, strictly increasing sequence means no detector exposures were missed between the PandA and the HDF5 file; a gap indicates lost data (e.g. from the Redis stream's MAXLEN trimming if the file writer fell behind — see the acquisition plan's data-path notes). Because it counts completed exposures rather than capture ticks, it verifies detector-frame completeness directly rather than raw-sample completeness.
PCAP.TS_TRIG.Value (existing) PCAP.TS_TRIG Absolute/relative timestamp already captured today; usable for time-alignment against other detectors' data during future reconstruction.
PCAP.GATE_DURATION.Value (existing, aliased as pcap_gate_duration_value) PCAP.GATE_DURATION Existing field, retained; less meaningful once the gate is held open continuously for the whole burst window rather than pulsed per point (see setup doc, Mode B gate/arm row) — re-evaluate whether this still needs to be captured now that real hardware testing has started.

All rows across a burst window share the same set of fields; there is no per-point boundary marker in this raw stream other than what can be derived from gate_detector_active transitions and/or absolute timestamps — no explicit "scan point index" field is captured by the PandA itself.

What this does not include

  • No on-the-fly or post-scan computation of Mean/Min/Max/stdev from the raw samples — the raw stream is the complete record; deriving the previous per-point statistics from it is a separate future task.
  • No changes to how Mode A (legacy) data is written — this schema only applies when raw_stream_mode: true.