##// END OF EJS Templates
Adds logs to axe and plottable rendering utils
Alexandre Leroux -
r927:c91efb7c50ed
parent child
Show More
@@ -1,34 +1,37
1 1 #ifndef SCIQLOP_AXISRENDERINGUTILS_H
2 2 #define SCIQLOP_AXISRENDERINGUTILS_H
3 3
4 4 #include <memory>
5 5
6 #include <QtCore/QLoggingCategory>
6 7 #include <QtCore/QString>
7 8
9 Q_DECLARE_LOGGING_CATEGORY(LOG_AxisRenderingUtils)
10
8 11 class IDataSeries;
9 12 class QCPAxis;
10 13 class QCPColorScale;
11 14 class QCustomPlot;
12 15
13 16 /// Formats a data value according to the axis on which it is present
14 17 QString formatValue(double value, const QCPAxis &axis);
15 18
16 19 /**
17 20 * Helper used to handle axes rendering
18 21 */
19 22 struct IAxisHelper {
20 23 virtual ~IAxisHelper() noexcept = default;
21 24
22 25 /// Set properties of the plot's axes and the color scale associated to plot passed as
23 26 /// parameters
24 27 /// @param plot the plot for which to set axe properties
25 28 /// @param colorScale the color scale for which to set properties
26 29 virtual void setProperties(QCustomPlot &plot, QCPColorScale &colorScale) = 0;
27 30 };
28 31
29 32 struct IAxisHelperFactory {
30 33 /// Creates IAxisHelper according to a data series
31 34 static std::unique_ptr<IAxisHelper> create(std::shared_ptr<IDataSeries> dataSeries) noexcept;
32 35 };
33 36
34 37 #endif // SCIQLOP_AXISRENDERINGUTILS_H
@@ -1,29 +1,33
1 1 #ifndef SCIQLOP_PLOTTABLESRENDERINGUTILS_H
2 2 #define SCIQLOP_PLOTTABLESRENDERINGUTILS_H
3 3
4 4 #include <Visualization/VisualizationDefs.h>
5 5
6 6 #include <memory>
7 7
8 #include <QtCore/QLoggingCategory>
9
10 Q_DECLARE_LOGGING_CATEGORY(LOG_PlottablesRenderingUtils)
11
8 12 class IDataSeries;
9 13 class QCPColorScale;
10 14 class QCustomPlot;
11 15
12 16 /**
13 17 * Helper used to handle plottables rendering
14 18 */
15 19 struct IPlottablesHelper {
16 20 virtual ~IPlottablesHelper() noexcept = default;
17 21
18 22 /// Set properties of the plottables passed as parameter
19 23 /// @param plottables the plottables for which to set properties
20 24 virtual void setProperties(PlottablesMap &plottables) = 0;
21 25 };
22 26
23 27 struct IPlottablesHelperFactory {
24 28 /// Creates IPlottablesHelper according to a data series
25 29 static std::unique_ptr<IPlottablesHelper>
26 30 create(std::shared_ptr<IDataSeries> dataSeries) noexcept;
27 31 };
28 32
29 33 #endif // SCIQLOP_PLOTTABLESRENDERINGUTILS_H
@@ -1,163 +1,166
1 1 #include "Visualization/AxisRenderingUtils.h"
2 2
3 3 #include <Data/ScalarSeries.h>
4 4 #include <Data/SpectrogramSeries.h>
5 5 #include <Data/VectorSeries.h>
6 6
7 7 #include <Visualization/qcustomplot.h>
8 8
9 Q_LOGGING_CATEGORY(LOG_AxisRenderingUtils, "AxisRenderingUtils")
10
9 11 namespace {
10 12
11 13 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss:zzz");
12 14
13 15 /// Format for datetimes on a axis
14 16 const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
15 17
16 18 /// Generates the appropriate ticker for an axis, depending on whether the axis displays time or
17 19 /// non-time data
18 20 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis)
19 21 {
20 22 if (isTimeAxis) {
21 23 auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
22 24 dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
23 25 dateTicker->setDateTimeSpec(Qt::UTC);
24 26
25 27 return dateTicker;
26 28 }
27 29 else {
28 30 // default ticker
29 31 return QSharedPointer<QCPAxisTicker>::create();
30 32 }
31 33 }
32 34
33 35 /**
34 36 * Sets properties of the axis passed as parameter
35 37 * @param axis the axis to set
36 38 * @param unit the unit to set for the axis
37 39 * @param scaleType the scale type to set for the axis
38 40 */
39 41 void setAxisProperties(QCPAxis &axis, const Unit &unit,
40 42 QCPAxis::ScaleType scaleType = QCPAxis::stLinear)
41 43 {
42 44 // label (unit name)
43 45 axis.setLabel(unit.m_Name);
44 46
45 47 // scale type
46 48 axis.setScaleType(scaleType);
47 49
48 50 // ticker (depending on the type of unit)
49 51 axis.setTicker(axisTicker(unit.m_TimeUnit));
50 52 }
51 53
52 54 /**
53 55 * Delegate used to set axes properties
54 56 */
55 57 template <typename T, typename Enabled = void>
56 58 struct AxisSetter {
57 59 static void setProperties(T &, QCustomPlot &, QCPColorScale &)
58 60 {
59 61 // Default implementation does nothing
62 qCCritical(LOG_AxisRenderingUtils()) << "Can't set axis properties: unmanaged type of data";
60 63 }
61 64 };
62 65
63 66 /**
64 67 * Specialization of AxisSetter for scalars and vectors
65 68 * @sa ScalarSeries
66 69 * @sa VectorSeries
67 70 */
68 71 template <typename T>
69 72 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
70 73 or std::is_base_of<VectorSeries, T>::value> > {
71 74 static void setProperties(T &dataSeries, QCustomPlot &plot, QCPColorScale &)
72 75 {
73 76 dataSeries.lockRead();
74 77 auto xAxisUnit = dataSeries.xAxisUnit();
75 78 auto valuesUnit = dataSeries.valuesUnit();
76 79 dataSeries.unlock();
77 80
78 81 setAxisProperties(*plot.xAxis, xAxisUnit);
79 82 setAxisProperties(*plot.yAxis, valuesUnit);
80 83 }
81 84 };
82 85
83 86 /**
84 87 * Specialization of AxisSetter for spectrograms
85 88 * @sa SpectrogramSeries
86 89 */
87 90 template <typename T>
88 91 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
89 92 static void setProperties(T &dataSeries, QCustomPlot &plot, QCPColorScale &colorScale)
90 93 {
91 94 dataSeries.lockRead();
92 95 auto xAxisUnit = dataSeries.xAxisUnit();
93 96 /// @todo ALX: use iterators here
94 97 auto yAxisUnit = dataSeries.yAxis().unit();
95 98 auto valuesUnit = dataSeries.valuesUnit();
96 99 dataSeries.unlock();
97 100
98 101 setAxisProperties(*plot.xAxis, xAxisUnit);
99 102 setAxisProperties(*plot.yAxis, yAxisUnit);
100 103
101 104 // Displays color scale in plot
102 105 plot.plotLayout()->insertRow(0);
103 106 plot.plotLayout()->addElement(0, 0, &colorScale);
104 107 colorScale.setType(QCPAxis::atTop);
105 108 colorScale.setMinimumMargins(QMargins{0, 0, 0, 0});
106 109
107 110 // Aligns color scale with axes
108 111 auto marginGroups = plot.axisRect()->marginGroups();
109 112 for (auto it = marginGroups.begin(), end = marginGroups.end(); it != end; ++it) {
110 113 colorScale.setMarginGroup(it.key(), it.value());
111 114 }
112 115
113 116 // Set color scale properties
114 117 colorScale.setLabel(valuesUnit.m_Name);
115 118 colorScale.setDataScaleType(QCPAxis::stLogarithmic); // Logarithmic scale
116 119 }
117 120 };
118 121
119 122 /**
120 123 * Default implementation of IAxisHelper, which takes data series to set axes properties
121 124 * @tparam T the data series' type
122 125 */
123 126 template <typename T>
124 127 struct AxisHelper : public IAxisHelper {
125 128 explicit AxisHelper(T &dataSeries) : m_DataSeries{dataSeries} {}
126 129
127 130 void setProperties(QCustomPlot &plot, QCPColorScale &colorScale) override
128 131 {
129 132 AxisSetter<T>::setProperties(m_DataSeries, plot, colorScale);
130 133 }
131 134
132 135 T &m_DataSeries;
133 136 };
134 137
135 138 } // namespace
136 139
137 140 QString formatValue(double value, const QCPAxis &axis)
138 141 {
139 142 // If the axis is a time axis, formats the value as a date
140 143 if (auto axisTicker = qSharedPointerDynamicCast<QCPAxisTickerDateTime>(axis.ticker())) {
141 144 return DateUtils::dateTime(value, axisTicker->dateTimeSpec()).toString(DATETIME_FORMAT);
142 145 }
143 146 else {
144 147 return QString::number(value);
145 148 }
146 149 }
147 150
148 151 std::unique_ptr<IAxisHelper>
149 152 IAxisHelperFactory::create(std::shared_ptr<IDataSeries> dataSeries) noexcept
150 153 {
151 154 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(dataSeries)) {
152 155 return std::make_unique<AxisHelper<ScalarSeries> >(*scalarSeries);
153 156 }
154 157 else if (auto spectrogramSeries = std::dynamic_pointer_cast<SpectrogramSeries>(dataSeries)) {
155 158 return std::make_unique<AxisHelper<SpectrogramSeries> >(*spectrogramSeries);
156 159 }
157 160 else if (auto vectorSeries = std::dynamic_pointer_cast<VectorSeries>(dataSeries)) {
158 161 return std::make_unique<AxisHelper<VectorSeries> >(*vectorSeries);
159 162 }
160 163 else {
161 164 return std::make_unique<AxisHelper<IDataSeries> >(*dataSeries);
162 165 }
163 166 }
@@ -1,120 +1,127
1 1 #include "Visualization/PlottablesRenderingUtils.h"
2 2
3 3 #include <Common/ColorUtils.h>
4 4
5 5 #include <Data/ScalarSeries.h>
6 6 #include <Data/SpectrogramSeries.h>
7 7 #include <Data/VectorSeries.h>
8 8
9 9 #include <Visualization/qcustomplot.h>
10 10
11 Q_LOGGING_CATEGORY(LOG_PlottablesRenderingUtils, "PlottablesRenderingUtils")
12
11 13 namespace {
12 14
13 15 /// Default gradient used for colormap
14 16 const auto DEFAULT_COLORMAP_GRADIENT = QCPColorGradient::gpJet;
15 17
16 18 /**
17 19 * Delegate used to set plottables properties
18 20 */
19 21 template <typename T, typename Enabled = void>
20 22 struct PlottablesSetter {
21 23 static void setProperties(T &, PlottablesMap &)
22 24 {
23 25 // Default implementation does nothing
26 qCCritical(LOG_PlottablesRenderingUtils())
27 << "Can't set plottables properties: unmanaged type of data";
24 28 }
25 29 };
26 30
27 31 /**
28 32 * Specialization of PlottablesSetter for scalars and vectors
29 33 * @sa ScalarSeries
30 34 * @sa VectorSeries
31 35 */
32 36 template <typename T>
33 37 struct PlottablesSetter<T, typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
34 38 or std::is_base_of<VectorSeries, T>::value> > {
35 39 static void setProperties(T &dataSeries, PlottablesMap &plottables)
36 40 {
37 41 // Gets the number of components of the data series
38 42 dataSeries.lockRead();
39 43 auto componentCount = dataSeries.valuesData()->componentCount();
40 44 dataSeries.unlock();
41 45
42 46 // Generates colors for each component
43 47 auto colors = ColorUtils::colors(Qt::blue, Qt::red, componentCount);
44 48
45 49 // For each component of the data series, creates a QCPGraph to add to the plot
46 50 for (auto i = 0; i < componentCount; ++i) {
47 51 auto graph = plottables.at(i);
48 52 graph->setPen(QPen{colors.at(i)});
49 53 }
50 54 }
51 55 };
52 56
53 57 /**
54 58 * Specialization of PlottablesSetter for spectrograms
55 59 * @sa SpectrogramSeries
56 60 */
57 61 template <typename T>
58 62 struct PlottablesSetter<T,
59 63 typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
60 64 static void setProperties(T &, PlottablesMap &plottables)
61 65 {
62 66 // Checks that for a spectrogram there is only one plottable, that is a colormap
63 67 if (plottables.size() != 1) {
64 68 return;
65 69 }
66 70
67 71 if (auto colormap = dynamic_cast<QCPColorMap *>(plottables.begin()->second)) {
68 72 colormap->setInterpolate(false); // No value interpolation
69 73 colormap->setTightBoundary(true);
70 74
71 75 // Finds color scale in the colormap's plot to associate with it
72 76 auto plot = colormap->parentPlot();
73 77 auto plotElements = plot->plotLayout()->elements(false);
74 78 for (auto plotElement : plotElements) {
75 79 if (auto colorScale = dynamic_cast<QCPColorScale *>(plotElement)) {
76 80 colormap->setColorScale(colorScale);
77 81 }
78 82 }
79 83
80 84 // Sets gradient used for color scale
81 85 colormap->setGradient(DEFAULT_COLORMAP_GRADIENT);
82 86 colormap->rescaleDataRange();
83 87 }
88 else {
89 qCCritical(LOG_PlottablesRenderingUtils()) << "Can't get colormap of the spectrogram";
90 }
84 91 }
85 92 };
86 93
87 94 /**
88 95 * Default implementation of IPlottablesHelper, which takes data series to set plottables properties
89 96 * @tparam T the data series' type
90 97 */
91 98 template <typename T>
92 99 struct PlottablesHelper : public IPlottablesHelper {
93 100 explicit PlottablesHelper(T &dataSeries) : m_DataSeries{dataSeries} {}
94 101
95 102 void setProperties(PlottablesMap &plottables) override
96 103 {
97 104 PlottablesSetter<T>::setProperties(m_DataSeries, plottables);
98 105 }
99 106
100 107 T &m_DataSeries;
101 108 };
102 109
103 110 } // namespace
104 111
105 112 std::unique_ptr<IPlottablesHelper>
106 113 IPlottablesHelperFactory::create(std::shared_ptr<IDataSeries> dataSeries) noexcept
107 114 {
108 115 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(dataSeries)) {
109 116 return std::make_unique<PlottablesHelper<ScalarSeries> >(*scalarSeries);
110 117 }
111 118 else if (auto spectrogramSeries = std::dynamic_pointer_cast<SpectrogramSeries>(dataSeries)) {
112 119 return std::make_unique<PlottablesHelper<SpectrogramSeries> >(*spectrogramSeries);
113 120 }
114 121 else if (auto vectorSeries = std::dynamic_pointer_cast<VectorSeries>(dataSeries)) {
115 122 return std::make_unique<PlottablesHelper<VectorSeries> >(*vectorSeries);
116 123 }
117 124 else {
118 125 return std::make_unique<PlottablesHelper<IDataSeries> >(*dataSeries);
119 126 }
120 127 }
General Comments 1
Under Review
author

Auto status change to "Under Review"

You need to be logged in to leave comments. Login now