Writing Frames To A File
For file capture that should be controlled from a PyRogue tree, PyRogue
provides pyrogue.utilities.fileio.StreamWriter. It wraps
rogue.utilities.fileio.StreamWriter and exposes the usual file controls
through DataWriter.
The underlying rogue.utilities.fileio.StreamWriter is still the object that
does the capture work. It receives Rogue Frame traffic on one or more input
channels and writes those frames in the standard Rogue file format, preserving
payload bytes plus frame metadata.
For the on-disk format details (header words, channel/flags/error encoding, raw mode, and split-file behavior), see Rogue File Data Format.
When To Use Each Form
Use the PyRogue wrapper when operators or client code should be able to select the output file, open and close runs, and watch file counters through the tree. That is the pattern used in larger acquisition roots, where the writer becomes part of the operator-facing control surface.
Use the direct Rogue writer when a script already owns the stream graph and just needs a sink that writes files. That form is smaller and avoids the tree layer entirely.
Common Controls
At the wrapper level, most setups are shaped by a small set of controls:
DataFileOutput file selected through the inheritedpyrogue.DataWriterinterface.BufferSizeStaging buffer size before writes are flushed to the OS.MaxFileSizeNon-zero enables split-file capture.configStreamOptional mapping of channel index to a stream source that emits YAML or status snapshots at file open and close.rawModeWhenTrue, write payload bytes only instead of the normal Rogue framed record format.
The direct writer has the matching lower-level methods:
setBufferSize(bytes)setMaxSize(bytes)setDropErrors(bool)getChannel(index)open(path)close()
Channel Behavior
StreamWriter supports multiple incoming stream channels. That detail is
important because capture files often mix event data, metadata, debug streams,
or multiple firmware virtual channels in one recording.
getChannel(index) returns the sink for one capture path, but channel 0
has a special meaning. Data written through getChannel(0) preserves the
incoming frame’s own channel metadata. Data written through getChannel(N)
with N > 0 is forced to file channel N regardless of the frame’s
original channel field. That pattern is commonly used when a tree routes
distinct sources into fixed file channels.
Tree-Managed Writer Form
The wrapper inherits the standard file-control surface from
DataWriter, then adds the file I/O-specific behavior from
the underlying Rogue writer.
In practice, the wrapper is usually configured around configStream,
rawMode, and the inherited DataWriter controls such as DataFile,
BufferSize, and MaxFileSize.
In many systems, configStream is mapped to a reserved channel such as
255 so metadata stays separate from event/data channels.
Opening the wrapper does two things: it opens the file, then emits any configured YAML or status streams into their assigned channels. Closing does the same status dump again before the underlying writer shuts down. That is why the wrapper is a better fit when the file should carry both event traffic and the configuration context that surrounded the run.
Logging
The underlying C++ StreamWriter uses Rogue C++ logging.
Logger name:
pyrogue.fileio.StreamWriterConfiguration API:
rogue.Logging.setFilter('pyrogue.fileio.StreamWriter', rogue.Logging.Debug)Typical messages: file open/close flow, split-file rollover, and write-path operational diagnostics
Set the filter before constructing the writer object.
The PyRogue wrapper itself is primarily a control surface around that C++
writer, so the most useful logging usually comes from the underlying
StreamWriter logger.
Python Direct-Utility Example
import rogue.utilities.fileio as ruf
# Assume streamA and streamB are existing stream masters.
fwrite = ruf.StreamWriter()
# Buffer size controls staged write size before flushing to the OS.
fwrite.setBufferSize(10000)
# Split output file at 100 MB boundaries: myFile.dat.1, .2, ...
fwrite.setMaxSize(100000000)
# Drop incoming frames with non-zero frame error.
fwrite.setDropErrors(True)
# Map each source to a writer channel.
streamA >> fwrite.getChannel(0)
streamB >> fwrite.getChannel(1)
fwrite.open("myFile.dat")
# ... stream traffic is captured while file is open ...
fwrite.close()
Python Tree-Managed Example
import pyrogue as pr
import pyrogue.interfaces.stream as pis
import pyrogue.utilities.fileio as puf
import pyrogue.utilities.prbs as pup
class MyRoot(pr.Root):
def __init__(self, **kwargs):
super().__init__(**kwargs)
# Tree-managed writer with a reserved metadata channel.
status_stream = pis.Variable(root=self)
self.add(puf.StreamWriter(name='Writer', configStream={255: status_stream}))
# Real stream source feeding capture channel 0.
self.add(pup.PrbsTx(name='PrbsTx'))
self.PrbsTx >> self.Writer.getChannel(0)
root = MyRoot()
# File control can be performed through Device variables/commands.
root.Writer.DataFile.set("myFile.dat")
root.Writer.Open()
# ...
root.Writer.Close()
C++ StreamWriter Example
#include <rogue/utilities/fileio/StreamWriter.h>
#include <rogue/utilities/fileio/StreamWriterChannel.h>
namespace ruf = rogue::utilities::fileio;
// Assume streamA and streamB are existing stream masters.
auto fwrite = ruf::StreamWriter::create();
fwrite->setBufferSize(10000);
fwrite->setMaxSize(100000000);
fwrite->setDropErrors(true);
streamA >> fwrite->getChannel(0);
streamB >> fwrite->getChannel(1);
fwrite->open("myFile.dat");
// ... stream traffic is captured while file is open ...
fwrite->close();
API Reference
C++: StreamWriter
Python: StreamWriter