Batcher Protocol
For unpacking or transforming records that firmware has combined into larger
super-frames, Rogue provides rogue.protocols.batcher. These classes are
used when batching is done in firmware to reduce transport and driver overhead
from sending many small frames individually.
In practice, the firmware side often batches records before they reach software. Rogue then handles one of two software-side tasks:
Split one super-frame into one Rogue frame per logical record.
Rewrite the framing in place so a downstream consumer sees the layout it expects without producing one output frame per record.
That makes batcher support most useful in two moments of a workflow:
Inline while receiving live stream data from firmware.
Later, while replaying or analyzing previously recorded batched files.
Rogue supports both wire formats:
Batcher v1 specification: https://confluence.slac.stanford.edu/x/th1SDg
Batcher v2 specification: https://confluence.slac.stanford.edu/x/L2VlK
How The Classes Fit Together
The classes in rogue.protocols.batcher are composable rather than
monolithic:
CoreV1andCoreV2parse one incoming super-frame and expose parsed record metadata.Datarepresents one parsed record payload plus its routing and user-field metadata.SplitterV1andSplitterV2use the parser output to emit one output frame per record.InverterV1andInverterV2use the same parser metadata to rewrite framing in place and emit one transformed frame.
Choose the v1 or v2 class family to match the firmware batcher format. Do not mix v1 and v2 parsing or transform stages in the same path.
Subtopics
Batcher Protocol Splitter Use this path when downstream software needs one frame per logical record.
Batcher Protocol Inverter Use this path when downstream software still expects one output frame per super-frame, but with transformed framing.
Splitter Vs Inverter
This is the main decision users usually need to make.
Use a splitter when downstream processing expects ordinary record-sized frames. That is the common choice for filters, routers, file capture, and analysis stages that should operate on one logical record at a time.
Use an inverter when the downstream stage still wants one frame per input super-frame, but needs the framing rewritten into the layout it understands. An inverter is not an unbatcher. It is a single-frame reformatting stage.
Usage Patterns
The most common software-side chains look like this:
import rogue.protocols.batcher
import rogue.interfaces.stream
# True unbatching: one output frame per logical record.
src = MyBatchedFrameSource()
split = rogue.protocols.batcher.SplitterV2()
filt = rogue.interfaces.stream.Filter(True, 3)
dst = MyRecordSink()
src >> split >> filt >> dst
or:
import rogue.protocols.batcher
# In-place framing transform: one output frame per input super-frame.
src = MyBatchedFrameSource()
inv = rogue.protocols.batcher.InverterV1()
dst = MyTransformedFrameSink()
src >> inv >> dst
Threading And Lifecycle
The batcher parser, splitter, and inverter classes do not start internal worker threads. Processing runs synchronously in the caller thread of the surrounding stream graph.
Logging
Batcher logging is emitted by the shared parser cores, so it applies to both splitter and inverter usage:
pyrogue.batcher.CoreV1pyrogue.batcher.CoreV2
Enable the logger for the batcher version you are debugging before processing frames:
import rogue
rogue.Logging.setFilter('pyrogue.batcher.CoreV2', rogue.Logging.Debug)
For byte-level inspection of split or transformed output frames, add a
downstream debug Slave tap and use
Debugging Streams.
API Reference
Python: SplitterV1 SplitterV2 InverterV1 InverterV2
Batcher Protocol