Channel Filtering
A Filter object forwards only those Frame objects
whose metadata matches the configured selection rules.
You typically add a Filter when a stream carries multiple logical channels
but a downstream path only wants one of them. That situation commonly arises
when reading data from a file source, a channelized capture stream, or a
splitter that emits distinct channel numbers. A Filter can also be useful on
non-channelized data when the main need is to drop Frame objects whose error
field is non-zero.
At a high level, the Filter checks two pieces of Frame metadata:
channelselects the channel number that should be forwarded.dropErrorscontrols whetherFrameobjects with a non-zero error code are discarded.
Constructor
Python:
ris.Filter(dropErrors, channel)C++:
ris::Filter::create(dropErrors, channel)
Filtering Behavior
The forwarding logic is simple:
Drop
Frameobjects whosegetChannel()does not match the configured channel.If
dropErrors=True, dropFrameobjects whosegetError()is non-zero.Forward the remaining
Frameobjects unchanged.
Because the Filter operates on metadata rather than payload content, it is
often one of the cheapest ways to reduce traffic before it reaches more
expensive processing stages.
Python File Example
The most common example is reading one channel from a recorded file stream.
import rogue.interfaces.stream as ris
import pyrogue.utilities.fileio as puf
# File source
src = puf.StreamReader()
# Keep only channel 1 Frames and drop errored Frames
filt = ris.Filter(True, 1)
# Data destination
dst = MyCustomSlave()
# Connect the source to the Filter and then to the destination
src >> filt >> dst
src.open('MyDataFile.bin')
This arrangement is useful when a file contains multiple interleaved channels but the downstream analysis only needs one of them.
C++ File Example
#include "rogue/Helpers.h"
#include "rogue/interfaces/stream/Filter.h"
#include "rogue/utilities/fileio/StreamReader.h"
#include "MyCustomSlave.h"
namespace ris = rogue::interfaces::stream;
namespace ruf = rogue::utilities::fileio;
int main() {
// File source
auto src = ruf::StreamReader::create();
// Keep only channel 1 Frames and drop errored Frames
auto filt = ris::Filter::create(true, 1);
// Data destination
auto dst = MyCustomSlave::create();
// Connect the source to the Filter and then to the destination
rogueStreamConnect(src, filt);
rogueStreamConnect(filt, dst);
src->open("MyDataFile.bin");
return 0;
}
Python Diagnostic Example
Another useful pattern is to branch a diagnostic stream and keep only one channel for inspection.
import rogue.hardware.axi as rha
import rogue.interfaces.stream as ris
dma = rha.AxiStreamDma('/dev/datadev_0', 1, True)
# Keep only channel 3 Frames and drop errored Frames
filt = ris.Filter(True, 3)
mon = ris.Slave()
mon.setDebug(64, 'chan3')
dma >> filt >> mon
This is a common bring-up pattern when one logical stream is embedded in a larger channelized data source and you want quick visibility into just that substream.
Logging
Filter uses Rogue C++ logging with the static logger name
pyrogue.stream.Filter.
Enable that logger before constructing the object if you want implementation
messages from the Filter itself:
import rogue
import rogue.interfaces.stream as ris
rogue.Logging.setFilter('pyrogue.stream.Filter', rogue.Logging.Debug)
filt = ris.Filter(True, 3)
Filter does not provide a separate runtime setDebug(...) helper. If you
want to inspect the forwarded payload bytes, attach a debug Slave
downstream and use setDebug(maxBytes, name) there.
What To Explore Next
Connection topology rules: Connecting Streams
Fifousage: FIFO BufferingRateDropusage: Rate Limiting With RateDropReceive-side metadata handling: Receiving Frames