##// END OF EJS Templates
Updates AxisRenderingUtils to use variable's type instead of dataseries
Alexandre Leroux -
r1335:89a3f92d2fbb
parent child
Show More
@@ -1,37 +1,44
1 #ifndef SCIQLOP_AXISRENDERINGUTILS_H
1 #ifndef SCIQLOP_AXISRENDERINGUTILS_H
2 #define SCIQLOP_AXISRENDERINGUTILS_H
2 #define SCIQLOP_AXISRENDERINGUTILS_H
3
3
4 #include <memory>
4 #include <memory>
5
5
6 #include <QtCore/QLoggingCategory>
6 #include <QtCore/QLoggingCategory>
7 #include <QtCore/QString>
7 #include <QtCore/QString>
8
8
9 Q_DECLARE_LOGGING_CATEGORY(LOG_AxisRenderingUtils)
9 Q_DECLARE_LOGGING_CATEGORY(LOG_AxisRenderingUtils)
10
10
11 class IDataSeries;
11 class IDataSeries;
12 class QCPAxis;
12 class QCPAxis;
13 class QCustomPlot;
13 class QCustomPlot;
14 class SqpColorScale;
14 class SqpColorScale;
15 class Variable;
15
16
16 /// Formats a data value according to the axis on which it is present
17 /// Formats a data value according to the axis on which it is present
17 QString formatValue(double value, const QCPAxis &axis);
18 QString formatValue(double value, const QCPAxis &axis);
18
19
19 /**
20 /**
20 * Helper used to handle axes rendering
21 * Helper used to handle axes rendering
21 */
22 */
22 struct IAxisHelper {
23 struct IAxisHelper {
23 virtual ~IAxisHelper() noexcept = default;
24 virtual ~IAxisHelper() noexcept = default;
24
25
25 /// Set properties of the plot's axes and the color scale associated to plot passed as
26 /// Set properties of the plot's axes and the color scale associated to plot passed as
26 /// parameters
27 /// parameters
27 /// @param plot the plot for which to set axe properties
28 /// @param plot the plot for which to set axe properties
28 /// @param colorScale the color scale for which to set properties
29 /// @param colorScale the color scale for which to set properties
29 virtual void setProperties(QCustomPlot &plot, SqpColorScale &colorScale) = 0;
30 virtual void setProperties(QCustomPlot &plot, SqpColorScale &colorScale) = 0;
31
32 /// Set the units of the plot's axes and the color scale associated to plot passed as
33 /// parameters
34 /// @param plot the plot for which to set axe units
35 /// @param colorScale the color scale for which to set unit
36 virtual void setUnits(QCustomPlot &plot, SqpColorScale &colorScale) = 0;
30 };
37 };
31
38
32 struct IAxisHelperFactory {
39 struct IAxisHelperFactory {
33 /// Creates IAxisHelper according to a data series
40 /// Creates IPlottablesHelper according to the type of data series a variable holds
34 static std::unique_ptr<IAxisHelper> create(std::shared_ptr<IDataSeries> dataSeries) noexcept;
41 static std::unique_ptr<IAxisHelper> create(const Variable &variable) noexcept;
35 };
42 };
36
43
37 #endif // SCIQLOP_AXISRENDERINGUTILS_H
44 #endif // SCIQLOP_AXISRENDERINGUTILS_H
@@ -1,177 +1,207
1 #include "Visualization/AxisRenderingUtils.h"
1 #include "Visualization/AxisRenderingUtils.h"
2
2
3 #include <Data/ScalarSeries.h>
3 #include <Data/ScalarSeries.h>
4 #include <Data/SpectrogramSeries.h>
4 #include <Data/SpectrogramSeries.h>
5 #include <Data/VectorSeries.h>
5 #include <Data/VectorSeries.h>
6
6
7 #include <Variable/Variable.h>
8
7 #include <Visualization/SqpColorScale.h>
9 #include <Visualization/SqpColorScale.h>
8 #include <Visualization/qcustomplot.h>
10 #include <Visualization/qcustomplot.h>
9
11
10 Q_LOGGING_CATEGORY(LOG_AxisRenderingUtils, "AxisRenderingUtils")
12 Q_LOGGING_CATEGORY(LOG_AxisRenderingUtils, "AxisRenderingUtils")
11
13
12 namespace {
14 namespace {
13
15
14 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss:zzz");
16 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss:zzz");
15
17
16 /// Format for datetimes on a axis
18 /// Format for datetimes on a axis
17 const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
19 const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
18
20
19 const auto NUMBER_FORMAT = 'g';
21 const auto NUMBER_FORMAT = 'g';
20 const auto NUMBER_PRECISION = 9;
22 const auto NUMBER_PRECISION = 9;
21
23
22 /// Generates the appropriate ticker for an axis, depending on whether the axis displays time or
24 /// Generates the appropriate ticker for an axis, depending on whether the axis displays time or
23 /// non-time data
25 /// non-time data
24 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis, QCPAxis::ScaleType scaleType)
26 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis, QCPAxis::ScaleType scaleType)
25 {
27 {
26 if (isTimeAxis) {
28 if (isTimeAxis) {
27 auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
29 auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
28 dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
30 dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
29 dateTicker->setDateTimeSpec(Qt::UTC);
31 dateTicker->setDateTimeSpec(Qt::UTC);
30
32
31 return dateTicker;
33 return dateTicker;
32 }
34 }
33 else if (scaleType == QCPAxis::stLogarithmic) {
35 else if (scaleType == QCPAxis::stLogarithmic) {
34 return QSharedPointer<QCPAxisTickerLog>::create();
36 return QSharedPointer<QCPAxisTickerLog>::create();
35 }
37 }
36 else {
38 else {
37 // default ticker
39 // default ticker
38 return QSharedPointer<QCPAxisTicker>::create();
40 return QSharedPointer<QCPAxisTicker>::create();
39 }
41 }
40 }
42 }
41
43
42 /**
44 /**
43 * Sets properties of the axis passed as parameter
45 * Sets properties of the axis passed as parameter
44 * @param axis the axis to set
46 * @param axis the axis to set
45 * @param unit the unit to set for the axis
47 * @param unit the unit to set for the axis
46 * @param scaleType the scale type to set for the axis
48 * @param scaleType the scale type to set for the axis
47 */
49 */
48 void setAxisProperties(QCPAxis &axis, const Unit &unit,
50 void setAxisProperties(QCPAxis &axis, const Unit &unit,
49 QCPAxis::ScaleType scaleType = QCPAxis::stLinear)
51 QCPAxis::ScaleType scaleType = QCPAxis::stLinear)
50 {
52 {
51 // label (unit name)
53 // label (unit name)
52 axis.setLabel(unit.m_Name);
54 axis.setLabel(unit.m_Name);
53
55
54 // scale type
56 // scale type
55 axis.setScaleType(scaleType);
57 axis.setScaleType(scaleType);
56 if (scaleType == QCPAxis::stLogarithmic) {
58 if (scaleType == QCPAxis::stLogarithmic) {
57 // Scientific notation
59 // Scientific notation
58 axis.setNumberPrecision(0);
60 axis.setNumberPrecision(0);
59 axis.setNumberFormat("eb");
61 axis.setNumberFormat("eb");
60 }
62 }
61
63
62 // ticker (depending on the type of unit)
64 // ticker (depending on the type of unit)
63 axis.setTicker(axisTicker(unit.m_TimeUnit, scaleType));
65 axis.setTicker(axisTicker(unit.m_TimeUnit, scaleType));
64 }
66 }
65
67
66 /**
68 /**
67 * Delegate used to set axes properties
69 * Delegate used to set axes properties
68 */
70 */
69 template <typename T, typename Enabled = void>
71 template <typename T, typename Enabled = void>
70 struct AxisSetter {
72 struct AxisSetter {
71 static void setProperties(T &, QCustomPlot &, SqpColorScale &)
73 static void setProperties(QCustomPlot &, SqpColorScale &)
72 {
74 {
73 // Default implementation does nothing
75 // Default implementation does nothing
74 qCCritical(LOG_AxisRenderingUtils()) << "Can't set axis properties: unmanaged type of data";
76 qCCritical(LOG_AxisRenderingUtils()) << "Can't set axis properties: unmanaged type of data";
75 }
77 }
78
79 static void setUnits(T &, QCustomPlot &, SqpColorScale &)
80 {
81 // Default implementation does nothing
82 qCCritical(LOG_AxisRenderingUtils()) << "Can't set axis units: unmanaged type of data";
83 }
76 };
84 };
77
85
78 /**
86 /**
79 * Specialization of AxisSetter for scalars and vectors
87 * Specialization of AxisSetter for scalars and vectors
80 * @sa ScalarSeries
88 * @sa ScalarSeries
81 * @sa VectorSeries
89 * @sa VectorSeries
82 */
90 */
83 template <typename T>
91 template <typename T>
84 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
92 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
85 or std::is_base_of<VectorSeries, T>::value> > {
93 or std::is_base_of<VectorSeries, T>::value> > {
86 static void setProperties(T &dataSeries, QCustomPlot &plot, SqpColorScale &)
94 static void setProperties(QCustomPlot &, SqpColorScale &)
95 {
96 // Nothing to do
97 }
98
99 static void setUnits(T &dataSeries, QCustomPlot &plot, SqpColorScale &)
87 {
100 {
88 dataSeries.lockRead();
101 dataSeries.lockRead();
89 auto xAxisUnit = dataSeries.xAxisUnit();
102 auto xAxisUnit = dataSeries.xAxisUnit();
90 auto valuesUnit = dataSeries.valuesUnit();
103 auto valuesUnit = dataSeries.valuesUnit();
91 dataSeries.unlock();
104 dataSeries.unlock();
92
105
93 setAxisProperties(*plot.xAxis, xAxisUnit);
106 setAxisProperties(*plot.xAxis, xAxisUnit);
94 setAxisProperties(*plot.yAxis, valuesUnit);
107 setAxisProperties(*plot.yAxis, valuesUnit);
95 }
108 }
96 };
109 };
97
110
98 /**
111 /**
99 * Specialization of AxisSetter for spectrograms
112 * Specialization of AxisSetter for spectrograms
100 * @sa SpectrogramSeries
113 * @sa SpectrogramSeries
101 */
114 */
102 template <typename T>
115 template <typename T>
103 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
116 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
104 static void setProperties(T &dataSeries, QCustomPlot &plot, SqpColorScale &colorScale)
117 static void setProperties(QCustomPlot &plot, SqpColorScale &colorScale)
105 {
118 {
106 dataSeries.lockRead();
107 auto xAxisUnit = dataSeries.xAxisUnit();
108 auto yAxisUnit = dataSeries.yAxisUnit();
109 auto valuesUnit = dataSeries.valuesUnit();
110 dataSeries.unlock();
111
112 setAxisProperties(*plot.xAxis, xAxisUnit);
113 setAxisProperties(*plot.yAxis, yAxisUnit, QCPAxis::stLogarithmic);
114
115 // Displays color scale in plot
119 // Displays color scale in plot
116 plot.plotLayout()->insertRow(0);
120 plot.plotLayout()->insertRow(0);
117 plot.plotLayout()->addElement(0, 0, colorScale.m_Scale);
121 plot.plotLayout()->addElement(0, 0, colorScale.m_Scale);
118 colorScale.m_Scale->setType(QCPAxis::atTop);
122 colorScale.m_Scale->setType(QCPAxis::atTop);
119 colorScale.m_Scale->setMinimumMargins(QMargins{0, 0, 0, 0});
123 colorScale.m_Scale->setMinimumMargins(QMargins{0, 0, 0, 0});
120
124
121 // Aligns color scale with axes
125 // Aligns color scale with axes
122 auto marginGroups = plot.axisRect()->marginGroups();
126 auto marginGroups = plot.axisRect()->marginGroups();
123 for (auto it = marginGroups.begin(), end = marginGroups.end(); it != end; ++it) {
127 for (auto it = marginGroups.begin(), end = marginGroups.end(); it != end; ++it) {
124 colorScale.m_Scale->setMarginGroup(it.key(), it.value());
128 colorScale.m_Scale->setMarginGroup(it.key(), it.value());
125 }
129 }
126
130
127 // Set color scale properties
131 // Set color scale properties
128 setAxisProperties(*colorScale.m_Scale->axis(), valuesUnit, QCPAxis::stLogarithmic);
129 colorScale.m_AutomaticThreshold = true;
132 colorScale.m_AutomaticThreshold = true;
130 }
133 }
134
135 static void setUnits(T &dataSeries, QCustomPlot &plot, SqpColorScale &colorScale)
136 {
137 dataSeries.lockRead();
138 auto xAxisUnit = dataSeries.xAxisUnit();
139 auto yAxisUnit = dataSeries.yAxisUnit();
140 auto valuesUnit = dataSeries.valuesUnit();
141 dataSeries.unlock();
142
143 setAxisProperties(*plot.xAxis, xAxisUnit);
144 setAxisProperties(*plot.yAxis, yAxisUnit, QCPAxis::stLogarithmic);
145 setAxisProperties(*colorScale.m_Scale->axis(), valuesUnit, QCPAxis::stLogarithmic);
146 }
131 };
147 };
132
148
133 /**
149 /**
134 * Default implementation of IAxisHelper, which takes data series to set axes properties
150 * Default implementation of IAxisHelper, which takes data series to set axes properties
135 * @tparam T the data series' type
151 * @tparam T the data series' type
136 */
152 */
137 template <typename T>
153 template <typename T>
138 struct AxisHelper : public IAxisHelper {
154 struct AxisHelper : public IAxisHelper {
139 explicit AxisHelper(T &dataSeries) : m_DataSeries{dataSeries} {}
155 explicit AxisHelper(std::shared_ptr<T> dataSeries) : m_DataSeries{dataSeries} {}
140
156
141 void setProperties(QCustomPlot &plot, SqpColorScale &colorScale) override
157 void setProperties(QCustomPlot &plot, SqpColorScale &colorScale) override
142 {
158 {
143 AxisSetter<T>::setProperties(m_DataSeries, plot, colorScale);
159 AxisSetter<T>::setProperties(plot, colorScale);
160 }
161
162 void setUnits(QCustomPlot &plot, SqpColorScale &colorScale) override
163 {
164 if (m_DataSeries) {
165 AxisSetter<T>::setUnits(*m_DataSeries, plot, colorScale);
166 }
167 else {
168 qCCritical(LOG_AxisRenderingUtils()) << "Can't set units: inconsistency between the "
169 "type of data series and the type supposed";
170 }
144 }
171 }
145
172
146 T &m_DataSeries;
173 std::shared_ptr<T> m_DataSeries;
147 };
174 };
148
175
149 } // namespace
176 } // namespace
150
177
151 QString formatValue(double value, const QCPAxis &axis)
178 QString formatValue(double value, const QCPAxis &axis)
152 {
179 {
153 // If the axis is a time axis, formats the value as a date
180 // If the axis is a time axis, formats the value as a date
154 if (auto axisTicker = qSharedPointerDynamicCast<QCPAxisTickerDateTime>(axis.ticker())) {
181 if (auto axisTicker = qSharedPointerDynamicCast<QCPAxisTickerDateTime>(axis.ticker())) {
155 return DateUtils::dateTime(value, axisTicker->dateTimeSpec()).toString(DATETIME_FORMAT);
182 return DateUtils::dateTime(value, axisTicker->dateTimeSpec()).toString(DATETIME_FORMAT);
156 }
183 }
157 else {
184 else {
158 return QString::number(value, NUMBER_FORMAT, NUMBER_PRECISION);
185 return QString::number(value, NUMBER_FORMAT, NUMBER_PRECISION);
159 }
186 }
160 }
187 }
161
188
162 std::unique_ptr<IAxisHelper>
189 std::unique_ptr<IAxisHelper> IAxisHelperFactory::create(const Variable &variable) noexcept
163 IAxisHelperFactory::create(std::shared_ptr<IDataSeries> dataSeries) noexcept
164 {
190 {
165 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(dataSeries)) {
191 switch (variable.type()) {
166 return std::make_unique<AxisHelper<ScalarSeries> >(*scalarSeries);
192 case DataSeriesType::SCALAR:
167 }
193 return std::make_unique<AxisHelper<ScalarSeries> >(
168 else if (auto spectrogramSeries = std::dynamic_pointer_cast<SpectrogramSeries>(dataSeries)) {
194 std::dynamic_pointer_cast<ScalarSeries>(variable.dataSeries()));
169 return std::make_unique<AxisHelper<SpectrogramSeries> >(*spectrogramSeries);
195 case DataSeriesType::SPECTROGRAM:
170 }
196 return std::make_unique<AxisHelper<SpectrogramSeries> >(
171 else if (auto vectorSeries = std::dynamic_pointer_cast<VectorSeries>(dataSeries)) {
197 std::dynamic_pointer_cast<SpectrogramSeries>(variable.dataSeries()));
172 return std::make_unique<AxisHelper<VectorSeries> >(*vectorSeries);
198 case DataSeriesType::VECTOR:
173 }
199 return std::make_unique<AxisHelper<VectorSeries> >(
174 else {
200 std::dynamic_pointer_cast<VectorSeries>(variable.dataSeries()));
175 return std::make_unique<AxisHelper<IDataSeries> >(*dataSeries);
201 default:
176 }
202 // Creates default helper
203 break;
204 }
205
206 return std::make_unique<AxisHelper<IDataSeries> >(nullptr);
177 }
207 }
General Comments 0
You need to be logged in to leave comments. Login now