##// END OF EJS Templates
Parser refactoring (1)...
Parser refactoring (1) Creates a helper that will be used to read the properties and values of an AMDA file, to generate the dataset. The helper is intended to replace the current implementation of the parser, to be more generic and thus manage the spectrograms more easily

File last commit:

r922:e65d7f08d776
r944:e1494a5194f1
Show More
VisualizationGraphHelper.cpp
345 lines | 11.7 KiB | text/x-c | CppLexer
/ gui / src / Visualization / VisualizationGraphHelper.cpp
Correction for pull request
r243 #include "Visualization/VisualizationGraphHelper.h"
Alexandre Leroux
Creates factory that is responsible of creation of QCustomPlot components relative to a variable
r181 #include "Visualization/qcustomplot.h"
Alexandre Leroux
Handles creations for scalar series
r182 #include <Data/ScalarSeries.h>
Alexandre Leroux
Implements spectrograms display (1)...
r902 #include <Data/SpectrogramSeries.h>
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 #include <Data/VectorSeries.h>
Alexandre Leroux
Handles creations for scalar series
r182
Alexandre Leroux
Creates factory that is responsible of creation of QCustomPlot components relative to a variable
r181 #include <Variable/Variable.h>
Correction for pull request
r243 Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper")
Alexandre Leroux
Creates factory that is responsible of creation of QCustomPlot components relative to a variable
r181
Alexandre Leroux
Handles creations for scalar series
r182 namespace {
Add current progression for thread fix
r364 class SqpDataContainer : public QCPGraphDataContainer {
public:
Alexandre Leroux
Updates UI to not call the sort method when update graphs, as data series are already sorted
r453 void appendGraphData(const QCPGraphData &data) { mData.append(data); }
Add current progression for thread fix
r364 };
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 /**
Add mofif for clang format
r591 * Struct used to create plottables, depending on the type of the data series from which to create
* them
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 * @tparam T the data series' type
* @remarks Default implementation can't create plottables
*/
template <typename T, typename Enabled = void>
struct PlottablesCreator {
static PlottablesMap createPlottables(T &, QCustomPlot &)
{
qCCritical(LOG_DataSeries())
<< QObject::tr("Can't create plottables: unmanaged data series type");
return {};
The mock plugin can now create data with view operation
r235 }
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 };
The mock plugin can now create data with view operation
r235
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 /**
* Specialization of PlottablesCreator for scalars and vectors
* @sa ScalarSeries
* @sa VectorSeries
*/
template <typename T>
struct PlottablesCreator<T,
typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
or std::is_base_of<VectorSeries, T>::value> > {
static PlottablesMap createPlottables(T &dataSeries, QCustomPlot &plot)
{
PlottablesMap result{};
// Gets the number of components of the data series
Add thread protection for DataSeries...
r636 dataSeries.lockRead();
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 auto componentCount = dataSeries.valuesData()->componentCount();
Add thread protection for DataSeries...
r636 dataSeries.unlock();
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583
// For each component of the data series, creates a QCPGraph to add to the plot
for (auto i = 0; i < componentCount; ++i) {
auto graph = plot.addGraph();
result.insert({i, graph});
}
Initialisation of the graph range at creation in a new graphe, or inside...
r548
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 plot.replot();
return result;
Initialisation of the graph range at creation in a new graphe, or inside...
r548 }
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 };
Initialisation of the graph range at creation in a new graphe, or inside...
r548
Alexandre Leroux
Implements spectrograms display (1)...
r902 /**
* Specialization of PlottablesCreator for spectrograms
* @sa SpectrogramSeries
*/
template <typename T>
struct PlottablesCreator<T,
typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
static PlottablesMap createPlottables(T &dataSeries, QCustomPlot &plot)
{
PlottablesMap result{};
result.insert({0, new QCPColorMap{plot.xAxis, plot.yAxis}});
plot.replot();
return result;
}
};
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 /**
Add mofif for clang format
r591 * Struct used to update plottables, depending on the type of the data series from which to update
* them
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 * @tparam T the data series' type
* @remarks Default implementation can't update plottables
*/
template <typename T, typename Enabled = void>
struct PlottablesUpdater {
Alexandre Leroux
Refactors VisualizationGraphWidget::setYRange()...
r900 static void setPlotYAxisRange(T &, const SqpRange &, QCustomPlot &)
{
Alexandre Leroux
(Minor) Removes obsolete code
r905 qCCritical(LOG_VisualizationGraphHelper())
Alexandre Leroux
Refactors VisualizationGraphWidget::setYRange()...
r900 << QObject::tr("Can't set plot y-axis range: unmanaged data series type");
}
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 static void updatePlottables(T &, PlottablesMap &, const SqpRange &, bool)
{
Alexandre Leroux
(Minor) Removes obsolete code
r905 qCCritical(LOG_VisualizationGraphHelper())
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 << QObject::tr("Can't update plottables: unmanaged data series type");
}
};
Alexandre Leroux
Handles creations for scalar series
r182
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 /**
* Specialization of PlottablesUpdater for scalars and vectors
* @sa ScalarSeries
* @sa VectorSeries
*/
template <typename T>
struct PlottablesUpdater<T,
typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
or std::is_base_of<VectorSeries, T>::value> > {
Alexandre Leroux
Refactors VisualizationGraphWidget::setYRange()...
r900 static void setPlotYAxisRange(T &dataSeries, const SqpRange &xAxisRange, QCustomPlot &plot)
{
auto minValue = 0., maxValue = 0.;
dataSeries.lockRead();
auto valuesBounds = dataSeries.valuesBounds(xAxisRange.m_TStart, xAxisRange.m_TEnd);
auto end = dataSeries.cend();
if (valuesBounds.first != end && valuesBounds.second != end) {
auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
minValue = rangeValue(valuesBounds.first->minValue());
maxValue = rangeValue(valuesBounds.second->maxValue());
}
dataSeries.unlock();
plot.yAxis->setRange(QCPRange{minValue, maxValue});
}
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 static void updatePlottables(T &dataSeries, PlottablesMap &plottables, const SqpRange &range,
bool rescaleAxes)
{
// For each plottable to update, resets its data
std::map<int, QSharedPointer<SqpDataContainer> > dataContainers{};
for (const auto &plottable : plottables) {
if (auto graph = dynamic_cast<QCPGraph *>(plottable.second)) {
auto dataContainer = QSharedPointer<SqpDataContainer>::create();
graph->setData(dataContainer);
dataContainers.insert({plottable.first, dataContainer});
}
}
Add thread protection for DataSeries...
r636 dataSeries.lockRead();
Alexandre Leroux
Handles creations for scalar series
r182
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 // - Gets the data of the series included in the current range
Add mofif for clang format
r591 // - Updates each plottable by adding, for each data item, a point that takes x-axis data
// and value data. The correct value is retrieved according to the index of the component
Alexandre Leroux
(Refactoring) Renames IDataSeries::subData()
r605 auto subDataIts = dataSeries.xAxisRange(range.m_TStart, range.m_TEnd);
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 for (auto it = subDataIts.first; it != subDataIts.second; ++it) {
for (const auto &dataContainer : dataContainers) {
auto componentIndex = dataContainer.first;
dataContainer.second->appendGraphData(
QCPGraphData(it->x(), it->value(componentIndex)));
}
}
The mock plugin can now create data with view operation
r235
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 dataSeries.unlock();
Alexandre Leroux
Handles axes properties
r183
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 if (!plottables.empty()) {
auto plot = plottables.begin()->second->parentPlot();
Alexandre Leroux
Handles axes properties
r183
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 if (rescaleAxes) {
plot->rescaleAxes();
}
Alexandre Leroux
Handles axes properties
r183
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 plot->replot();
}
Alexandre Leroux
Handles creations for scalar series
r182 }
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 };
Alexandre Leroux
Implements spectrograms display (2)...
r903 /**
* Specialization of PlottablesUpdater for spectrograms
* @sa SpectrogramSeries
*/
template <typename T>
struct PlottablesUpdater<T,
typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
Alexandre Leroux
Implements spectrograms display (3)...
r904 static void setPlotYAxisRange(T &dataSeries, const SqpRange &xAxisRange, QCustomPlot &plot)
{
double min, max;
/// @todo ALX: use iterators here
std::tie(min, max) = dataSeries.yAxis().bounds();
if (!std::isnan(min) && !std::isnan(max)) {
plot.yAxis->setRange(QCPRange{min, max});
}
}
Alexandre Leroux
Implements spectrograms display (2)...
r903 static void updatePlottables(T &dataSeries, PlottablesMap &plottables, const SqpRange &range,
bool rescaleAxes)
{
if (plottables.empty()) {
qCDebug(LOG_VisualizationGraphHelper())
<< QObject::tr("Can't update spectrogram: no colormap has been associated");
return;
}
// Gets the colormap to update (normally there is only one colormap)
Q_ASSERT(plottables.size() == 1);
auto colormap = dynamic_cast<QCPColorMap *>(plottables.at(0));
Q_ASSERT(colormap != nullptr);
dataSeries.lockRead();
auto its = dataSeries.xAxisRange(range.m_TStart, range.m_TEnd);
/// @todo ALX: use iterators here
auto yAxis = dataSeries.yAxis();
// Gets properties of x-axis and y-axis to set size and range of the colormap
auto nbX = std::distance(its.first, its.second);
auto xMin = nbX != 0 ? its.first->x() : 0.;
auto xMax = nbX != 0 ? (its.second - 1)->x() : 0.;
auto nbY = yAxis.size();
auto yMin = 0., yMax = 0.;
if (nbY != 0) {
std::tie(yMin, yMax) = yAxis.bounds();
}
colormap->data()->setSize(nbX, nbY);
colormap->data()->setRange(QCPRange{xMin, xMax}, QCPRange{yMin, yMax});
// Sets values
auto xIndex = 0;
for (auto it = its.first; it != its.second; ++it, ++xIndex) {
for (auto yIndex = 0; yIndex < nbY; ++yIndex) {
Alexandre Leroux
Introduces NaN and zero values in data of the mock spectrogram...
r922 auto value = it->value(yIndex);
colormap->data()->setCell(xIndex, yIndex, value);
// Processing spectrogram data for display in QCustomPlot
/// For the moment, we just make the NaN values to be transparent in the colormap
/// @todo ALX: complete treatments (mesh generation, etc.)
if (std::isnan(value)) {
colormap->data()->setAlpha(xIndex, yIndex, 0);
}
Alexandre Leroux
Implements spectrograms display (2)...
r903 }
}
dataSeries.unlock();
// Rescales axes
auto plot = colormap->parentPlot();
if (rescaleAxes) {
plot->rescaleAxes();
}
plot->replot();
}
};
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 /**
* Helper used to create/update plottables
*/
struct IPlottablesHelper {
virtual ~IPlottablesHelper() noexcept = default;
virtual PlottablesMap create(QCustomPlot &plot) const = 0;
Alexandre Leroux
Refactors VisualizationGraphWidget::setYRange()...
r900 virtual void setYAxisRange(const SqpRange &xAxisRange, QCustomPlot &plot) const = 0;
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 virtual void update(PlottablesMap &plottables, const SqpRange &range,
bool rescaleAxes = false) const = 0;
};
/**
* Default implementation of IPlottablesHelper, which takes data series to create/update plottables
* @tparam T the data series' type
*/
template <typename T>
struct PlottablesHelper : public IPlottablesHelper {
explicit PlottablesHelper(T &dataSeries) : m_DataSeries{dataSeries} {}
PlottablesMap create(QCustomPlot &plot) const override
{
return PlottablesCreator<T>::createPlottables(m_DataSeries, plot);
Alexandre Leroux
Handles creations for scalar series
r182 }
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 void update(PlottablesMap &plottables, const SqpRange &range, bool rescaleAxes) const override
{
PlottablesUpdater<T>::updatePlottables(m_DataSeries, plottables, range, rescaleAxes);
}
Alexandre Leroux
Handles creations for scalar series
r182
Alexandre Leroux
Refactors VisualizationGraphWidget::setYRange()...
r900 void setYAxisRange(const SqpRange &xAxisRange, QCustomPlot &plot) const override
{
return PlottablesUpdater<T>::setPlotYAxisRange(m_DataSeries, xAxisRange, plot);
}
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 T &m_DataSeries;
};
Alexandre Leroux
Handles creations for scalar series
r182
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 /// Creates IPlottablesHelper according to a data series
Alexandre Leroux
Uses std::shared_ptr
r587 std::unique_ptr<IPlottablesHelper> createHelper(std::shared_ptr<IDataSeries> dataSeries) noexcept
Initialisation of the graph range at creation in a new graphe, or inside...
r548 {
Alexandre Leroux
Uses std::shared_ptr
r587 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(dataSeries)) {
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 return std::make_unique<PlottablesHelper<ScalarSeries> >(*scalarSeries);
}
Alexandre Leroux
Implements spectrograms display (1)...
r902 else if (auto spectrogramSeries = std::dynamic_pointer_cast<SpectrogramSeries>(dataSeries)) {
return std::make_unique<PlottablesHelper<SpectrogramSeries> >(*spectrogramSeries);
}
Alexandre Leroux
Uses std::shared_ptr
r587 else if (auto vectorSeries = std::dynamic_pointer_cast<VectorSeries>(dataSeries)) {
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 return std::make_unique<PlottablesHelper<VectorSeries> >(*vectorSeries);
Initialisation of the graph range at creation in a new graphe, or inside...
r548 }
else {
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 return std::make_unique<PlottablesHelper<IDataSeries> >(*dataSeries);
Initialisation of the graph range at creation in a new graphe, or inside...
r548 }
}
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 } // namespace
Alexandre Leroux
Creates factory that is responsible of creation of QCustomPlot components relative to a variable
r181
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 PlottablesMap VisualizationGraphHelper::create(std::shared_ptr<Variable> variable,
QCustomPlot &plot) noexcept
{
Alexandre Leroux
Creates factory that is responsible of creation of QCustomPlot components relative to a variable
r181 if (variable) {
Alexandre Leroux
Uses std::shared_ptr
r587 auto helper = createHelper(variable->dataSeries());
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 auto plottables = helper->create(plot);
return plottables;
Alexandre Leroux
Creates factory that is responsible of creation of QCustomPlot components relative to a variable
r181 }
else {
Correction for pull request
r243 qCDebug(LOG_VisualizationGraphHelper())
Alexandre Leroux
Creates factory that is responsible of creation of QCustomPlot components relative to a variable
r181 << QObject::tr("Can't create graph plottables : the variable is null");
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 return PlottablesMap{};
Alexandre Leroux
Creates factory that is responsible of creation of QCustomPlot components relative to a variable
r181 }
}
The mock plugin can now create data with view operation
r235
Alexandre Leroux
Refactors VisualizationGraphWidget::setYRange()...
r900 void VisualizationGraphHelper::setYAxisRange(std::shared_ptr<Variable> variable,
QCustomPlot &plot) noexcept
{
if (variable) {
auto helper = createHelper(variable->dataSeries());
helper->setYAxisRange(variable->range(), plot);
}
else {
qCDebug(LOG_VisualizationGraphHelper())
<< QObject::tr("Can't set y-axis range of plot: the variable is null");
}
}
Alexandre Leroux
Uses std::shared_ptr
r587 void VisualizationGraphHelper::updateData(PlottablesMap &plottables,
std::shared_ptr<IDataSeries> dataSeries,
The dataSeries of a variable is now shared istead of uniq to avoid...
r542 const SqpRange &dateTime)
The mock plugin can now create data with view operation
r235 {
Alexandre Leroux
Updates VisualizationGraphHelper to handle vectors
r583 auto helper = createHelper(dataSeries);
helper->update(plottables, dateTime);
The mock plugin can now create data with view operation
r235 }