Programming Reference:VisualizationContainerDemo Signal Processing
Location
src/contrib/SignalProcessing/VisualizationContainerDemo
Synopsis
The VisualizationContainerDemo signal processing module demonstrates how to maintain a number of visualization displays within a container window. It is similar to Programming Reference:ComplexVisualizationDemo Signal Processing but does not render graphics itself; rather, it maintains a group of visualization windows within a container window, and sends data to these.
Inheritance
The VisualizationContainerDemo signal processing filter derives from GenericFilter.
Function
The VisualizationContainerDemo computes pairwise determination coefficients (squared correlation, values) between its input channels. Determination coefficients are sent to a group of visualizations in the Operator module.
Operator visualizations are contained in a parent window, and arranged in form of a triangular matrix, with each window appearing at the place of its associated correlation matrix element:
Implementation
Each visualization window is implemented as a VisualizationObject that contains a Visualization and a Computation object. Whenever a new block of data arrives, computation is done for the individual window's pair of channels in the main thread. Then, the result is sent to the Operator window inside a GenericSignal object. As both computation effort and the amount of data is limited, and to keep the example code simple, no multithreading is involved in this demo. (For an example that involves multithreading, see Programming Reference:ComplexVisualizationDemo Signal Processing.)
Declaration of internal variables
The code example uses a pointer to an internal private struct to hide implementation details from the outer header file of the filter class (PIMPL idiom).
A VisualizationObject class is declared that contains all members necessary to compute an value, and to send it to a visualization window.
struct VisualizationContainerDemoFilter::Private
{
GenericVisualization mContainerVis;
class VisualizationObject;
std::vector<VisualizationObject *> mVisualizations;
~Private()
{
destroyVisualizations();
}
// Creates visualization objects for pairs of channels.
void createVisualizations(const SignalProperties &);
// Destroys all visualization objects.
void destroyVisualizations();
// Sets visualizations to their initial state.
void resetVisualizations();
// Computes data values, and updates visualization windows.
void updateVisualizations(const GenericSignal &);
class VisualizationObject
{
public:
VisualizationObject(const std::string &visID);
~VisualizationObject();
void setTitle(const std::string &);
void configureSignal(const SignalProperties&);
void setPosition(int row, int col);
void reset();
void update(const GenericSignal &);
struct Computation
{
int inputCh1, inputCh2;
double result;
// run() is called whenever a new signal arrives.
void run(const GenericSignal &);
} mComputation;
private:
GenericVisualization mVis;
GenericSignal mSignal;
PhysicalUnit mSampleUnit, mValueUnit;
std::string mTitle;
int mRow, mCol;
};
};
VisualizationObject::update()
This function computes the correlation matrix element, and sends it to the visualization display wrapped into a GenericSignal object.
void
VisualizationContainerDemoFilter::Private::VisualizationObject::update(const GenericSignal& Input)
{
mComputation.run(Input);
mSignal(0, 0) = mComputation.result;
mVis.Send(mSignal);
}
VisualizationObject::reset()
This function resets the visualization window's position and size before sending an empty signal to the Operator (this will enforce creation of the visualization display on the Operator side).
void
VisualizationContainerDemoFilter::Private::VisualizationObject::reset()
{
// reset position and size
mVis.Send(CfgID::PlacementVis, "CNTR");
mVis.Send(CfgID::PlacementRow, mRow + 1); // rows are one-based
mVis.Send(CfgID::PlacementCol, mCol + 1); // columns are one-based
mVis.Send(CfgID::Visible, true);
mVis.Send(CfgID::FixedScale, true);
mVis.Send(CfgID::MinValue, mValueUnit.RawMin());
mVis.Send(CfgID::MaxValue, mValueUnit.RawMax() * 1.1);
mVis.Send(CfgID::ShowStatusBar, false);
mVis.Send(CfgID::SampleUnit, mSampleUnit.RawToPhysical(1));
mVis.Send(CfgID::ShowYTicks, false);
LabelList markers;
markers.push_back(Label(mValueUnit.PhysicalToRaw("1"), "1|red|-|0.5"));
markers.push_back(Label(mValueUnit.PhysicalToRaw("0.5"), "0.5|green|-.|0.5"));
mVis.Send(CfgID::YAxisMarkers, markers);
mVis.Send(CfgID::WindowTitle, mTitle);
mVis.Send(CfgID::WindowFrame, true);
mVis.Send(GenericSignal());
}
Process() function
The Process() function calls updateVisualizations(), which, in turn, will call VisualizationObject::update() for each visualization object contained in mVisualizations.
void VisualizationContainerDemoFilter::Process(
const GenericSignal& Input,
GenericSignal& Output)
{
Output = Input;
p->updateVisualizations(Input);
}
StartRun() and StopRun()
These reset all visualization objects.
void
VisualizationContainerDemoFilter::StartRun()
{
p->resetVisualizations();
}
void
VisualizationContainerDemoFilter::StopRun()
{
p->resetVisualizations();
}
See also
Programming Reference:GraphDisplay Class, Programming Reference:GenericVisualization Class, Programming Reference:VisualizationDemo Signal Processing, Programming Reference:ComplexVisualizationDemo Signal Processing, Technical Reference:Visualization Properties