##// END OF EJS Templates
Minor fix...
Alexandre Leroux -
r1110:0e96e473601d
parent child
Show More
@@ -1,176 +1,177
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 <Visualization/SqpColorScale.h>
7 #include <Visualization/SqpColorScale.h>
8 #include <Visualization/qcustomplot.h>
8 #include <Visualization/qcustomplot.h>
9
9
10 Q_LOGGING_CATEGORY(LOG_AxisRenderingUtils, "AxisRenderingUtils")
10 Q_LOGGING_CATEGORY(LOG_AxisRenderingUtils, "AxisRenderingUtils")
11
11
12 namespace {
12 namespace {
13
13
14 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss:zzz");
14 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss:zzz");
15
15
16 /// Format for datetimes on a axis
16 /// Format for datetimes on a axis
17 const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
17 const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
18
18
19 const auto NUMBER_FORMAT = 'g';
19 const auto NUMBER_FORMAT = 'g';
20 const auto NUMBER_PRECISION = 9;
20 const auto NUMBER_PRECISION = 9;
21
21
22 /// Generates the appropriate ticker for an axis, depending on whether the axis displays time or
22 /// Generates the appropriate ticker for an axis, depending on whether the axis displays time or
23 /// non-time data
23 /// non-time data
24 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis, QCPAxis::ScaleType scaleType)
24 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis, QCPAxis::ScaleType scaleType)
25 {
25 {
26 if (isTimeAxis) {
26 if (isTimeAxis) {
27 auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
27 auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
28 dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
28 dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
29 dateTicker->setDateTimeSpec(Qt::UTC);
29 dateTicker->setDateTimeSpec(Qt::UTC);
30
30
31 return dateTicker;
31 return dateTicker;
32 }
32 }
33 else if (scaleType == QCPAxis::stLogarithmic) {
33 else if (scaleType == QCPAxis::stLogarithmic) {
34 return QSharedPointer<QCPAxisTickerLog>::create();
34 return QSharedPointer<QCPAxisTickerLog>::create();
35 }
35 }
36 else {
36 else {
37 // default ticker
37 // default ticker
38 return QSharedPointer<QCPAxisTicker>::create();
38 return QSharedPointer<QCPAxisTicker>::create();
39 }
39 }
40 }
40 }
41
41
42 /**
42 /**
43 * Sets properties of the axis passed as parameter
43 * Sets properties of the axis passed as parameter
44 * @param axis the axis to set
44 * @param axis the axis to set
45 * @param unit the unit to set for the axis
45 * @param unit the unit to set for the axis
46 * @param scaleType the scale type to set for the axis
46 * @param scaleType the scale type to set for the axis
47 */
47 */
48 void setAxisProperties(QCPAxis &axis, const Unit &unit,
48 void setAxisProperties(QCPAxis &axis, const Unit &unit,
49 QCPAxis::ScaleType scaleType = QCPAxis::stLinear)
49 QCPAxis::ScaleType scaleType = QCPAxis::stLinear)
50 {
50 {
51 // label (unit name)
51 // label (unit name)
52 axis.setLabel(unit.m_Name);
52 axis.setLabel(unit.m_Name);
53
53
54 // scale type
54 // scale type
55 axis.setScaleType(scaleType);
55 axis.setScaleType(scaleType);
56 if (scaleType == QCPAxis::stLogarithmic) {
56 if (scaleType == QCPAxis::stLogarithmic) {
57 // Scientific notation
57 // Scientific notation
58 axis.setNumberPrecision(0);
58 axis.setNumberPrecision(0);
59 axis.setNumberFormat("eb");
59 axis.setNumberFormat("eb");
60 }
60 }
61
61
62 // ticker (depending on the type of unit)
62 // ticker (depending on the type of unit)
63 axis.setTicker(axisTicker(unit.m_TimeUnit, scaleType));
63 axis.setTicker(axisTicker(unit.m_TimeUnit, scaleType));
64 }
64 }
65
65
66 /**
66 /**
67 * Delegate used to set axes properties
67 * Delegate used to set axes properties
68 */
68 */
69 template <typename T, typename Enabled = void>
69 template <typename T, typename Enabled = void>
70 struct AxisSetter {
70 struct AxisSetter {
71 static void setProperties(T &, QCustomPlot &, SqpColorScale &)
71 static void setProperties(T &, QCustomPlot &, SqpColorScale &)
72 {
72 {
73 // Default implementation does nothing
73 // Default implementation does nothing
74 qCCritical(LOG_AxisRenderingUtils()) << "Can't set axis properties: unmanaged type of data";
74 qCCritical(LOG_AxisRenderingUtils()) << "Can't set axis properties: unmanaged type of data";
75 }
75 }
76 };
76 };
77
77
78 /**
78 /**
79 * Specialization of AxisSetter for scalars and vectors
79 * Specialization of AxisSetter for scalars and vectors
80 * @sa ScalarSeries
80 * @sa ScalarSeries
81 * @sa VectorSeries
81 * @sa VectorSeries
82 */
82 */
83 template <typename T>
83 template <typename T>
84 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
84 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
85 or std::is_base_of<VectorSeries, T>::value> > {
85 or std::is_base_of<VectorSeries, T>::value> > {
86 static void setProperties(T &dataSeries, QCustomPlot &plot, SqpColorScale &)
86 static void setProperties(T &dataSeries, QCustomPlot &plot, SqpColorScale &)
87 {
87 {
88 dataSeries.lockRead();
88 dataSeries.lockRead();
89 auto xAxisUnit = dataSeries.xAxisUnit();
89 auto xAxisUnit = dataSeries.xAxisUnit();
90 auto valuesUnit = dataSeries.valuesUnit();
90 auto valuesUnit = dataSeries.valuesUnit();
91 dataSeries.unlock();
91 dataSeries.unlock();
92
92
93 setAxisProperties(*plot.xAxis, xAxisUnit);
93 setAxisProperties(*plot.xAxis, xAxisUnit);
94 setAxisProperties(*plot.yAxis, valuesUnit);
94 setAxisProperties(*plot.yAxis, valuesUnit);
95 }
95 }
96 };
96 };
97
97
98 /**
98 /**
99 * Specialization of AxisSetter for spectrograms
99 * Specialization of AxisSetter for spectrograms
100 * @sa SpectrogramSeries
100 * @sa SpectrogramSeries
101 */
101 */
102 template <typename T>
102 template <typename T>
103 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
103 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)
104 static void setProperties(T &dataSeries, QCustomPlot &plot, SqpColorScale &colorScale)
105 {
105 {
106 dataSeries.lockRead();
106 dataSeries.lockRead();
107 auto xAxisUnit = dataSeries.xAxisUnit();
107 auto xAxisUnit = dataSeries.xAxisUnit();
108 auto yAxisUnit = dataSeries.yAxisUnit();
108 auto yAxisUnit = dataSeries.yAxisUnit();
109 auto valuesUnit = dataSeries.valuesUnit();
109 auto valuesUnit = dataSeries.valuesUnit();
110 dataSeries.unlock();
110 dataSeries.unlock();
111
111
112 setAxisProperties(*plot.xAxis, xAxisUnit);
112 setAxisProperties(*plot.xAxis, xAxisUnit);
113 setAxisProperties(*plot.yAxis, yAxisUnit, QCPAxis::stLogarithmic);
113 setAxisProperties(*plot.yAxis, yAxisUnit, QCPAxis::stLogarithmic);
114
114
115 // Displays color scale in plot
115 // Displays color scale in plot
116 plot.plotLayout()->insertRow(0);
116 plot.plotLayout()->insertRow(0);
117 plot.plotLayout()->addElement(0, 0, colorScale.m_Scale);
117 plot.plotLayout()->addElement(0, 0, colorScale.m_Scale);
118 colorScale.m_Scale->setType(QCPAxis::atTop);
118 colorScale.m_Scale->setType(QCPAxis::atTop);
119 colorScale.m_Scale->setMinimumMargins(QMargins{0, 0, 0, 0});
119 colorScale.m_Scale->setMinimumMargins(QMargins{0, 0, 0, 0});
120
120
121 // Aligns color scale with axes
121 // Aligns color scale with axes
122 auto marginGroups = plot.axisRect()->marginGroups();
122 auto marginGroups = plot.axisRect()->marginGroups();
123 for (auto it = marginGroups.begin(), end = marginGroups.end(); it != end; ++it) {
123 for (auto it = marginGroups.begin(), end = marginGroups.end(); it != end; ++it) {
124 colorScale.m_Scale->setMarginGroup(it.key(), it.value());
124 colorScale.m_Scale->setMarginGroup(it.key(), it.value());
125 }
125 }
126
126
127 // Set color scale properties
127 // Set color scale properties
128 setAxisProperties(*colorScale.m_Scale->axis(), valuesUnit, QCPAxis::stLogarithmic);
128 setAxisProperties(*colorScale.m_Scale->axis(), valuesUnit, QCPAxis::stLogarithmic);
129 colorScale.m_AutomaticThreshold = true;
129 }
130 }
130 };
131 };
131
132
132 /**
133 /**
133 * Default implementation of IAxisHelper, which takes data series to set axes properties
134 * Default implementation of IAxisHelper, which takes data series to set axes properties
134 * @tparam T the data series' type
135 * @tparam T the data series' type
135 */
136 */
136 template <typename T>
137 template <typename T>
137 struct AxisHelper : public IAxisHelper {
138 struct AxisHelper : public IAxisHelper {
138 explicit AxisHelper(T &dataSeries) : m_DataSeries{dataSeries} {}
139 explicit AxisHelper(T &dataSeries) : m_DataSeries{dataSeries} {}
139
140
140 void setProperties(QCustomPlot &plot, SqpColorScale &colorScale) override
141 void setProperties(QCustomPlot &plot, SqpColorScale &colorScale) override
141 {
142 {
142 AxisSetter<T>::setProperties(m_DataSeries, plot, colorScale);
143 AxisSetter<T>::setProperties(m_DataSeries, plot, colorScale);
143 }
144 }
144
145
145 T &m_DataSeries;
146 T &m_DataSeries;
146 };
147 };
147
148
148 } // namespace
149 } // namespace
149
150
150 QString formatValue(double value, const QCPAxis &axis)
151 QString formatValue(double value, const QCPAxis &axis)
151 {
152 {
152 // If the axis is a time axis, formats the value as a date
153 // If the axis is a time axis, formats the value as a date
153 if (auto axisTicker = qSharedPointerDynamicCast<QCPAxisTickerDateTime>(axis.ticker())) {
154 if (auto axisTicker = qSharedPointerDynamicCast<QCPAxisTickerDateTime>(axis.ticker())) {
154 return DateUtils::dateTime(value, axisTicker->dateTimeSpec()).toString(DATETIME_FORMAT);
155 return DateUtils::dateTime(value, axisTicker->dateTimeSpec()).toString(DATETIME_FORMAT);
155 }
156 }
156 else {
157 else {
157 return QString::number(value, NUMBER_FORMAT, NUMBER_PRECISION);
158 return QString::number(value, NUMBER_FORMAT, NUMBER_PRECISION);
158 }
159 }
159 }
160 }
160
161
161 std::unique_ptr<IAxisHelper>
162 std::unique_ptr<IAxisHelper>
162 IAxisHelperFactory::create(std::shared_ptr<IDataSeries> dataSeries) noexcept
163 IAxisHelperFactory::create(std::shared_ptr<IDataSeries> dataSeries) noexcept
163 {
164 {
164 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(dataSeries)) {
165 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(dataSeries)) {
165 return std::make_unique<AxisHelper<ScalarSeries> >(*scalarSeries);
166 return std::make_unique<AxisHelper<ScalarSeries> >(*scalarSeries);
166 }
167 }
167 else if (auto spectrogramSeries = std::dynamic_pointer_cast<SpectrogramSeries>(dataSeries)) {
168 else if (auto spectrogramSeries = std::dynamic_pointer_cast<SpectrogramSeries>(dataSeries)) {
168 return std::make_unique<AxisHelper<SpectrogramSeries> >(*spectrogramSeries);
169 return std::make_unique<AxisHelper<SpectrogramSeries> >(*spectrogramSeries);
169 }
170 }
170 else if (auto vectorSeries = std::dynamic_pointer_cast<VectorSeries>(dataSeries)) {
171 else if (auto vectorSeries = std::dynamic_pointer_cast<VectorSeries>(dataSeries)) {
171 return std::make_unique<AxisHelper<VectorSeries> >(*vectorSeries);
172 return std::make_unique<AxisHelper<VectorSeries> >(*vectorSeries);
172 }
173 }
173 else {
174 else {
174 return std::make_unique<AxisHelper<IDataSeries> >(*dataSeries);
175 return std::make_unique<AxisHelper<IDataSeries> >(*dataSeries);
175 }
176 }
176 }
177 }
@@ -1,60 +1,60
1 #include "Visualization/SqpColorScale.h"
1 #include "Visualization/SqpColorScale.h"
2
2
3 #include <Data/DataSeriesUtils.h>
3 #include <Data/DataSeriesUtils.h>
4
4
5 #include <Visualization/QCPColorMapIterator.h>
5 #include <Visualization/QCPColorMapIterator.h>
6
6
7 Q_LOGGING_CATEGORY(LOG_SqpColorScale, "SqpColorScale")
7 Q_LOGGING_CATEGORY(LOG_SqpColorScale, "SqpColorScale")
8
8
9 namespace {
9 namespace {
10
10
11 const auto DEFAULT_GRADIENT_PRESET = QCPColorGradient::gpJet;
11 const auto DEFAULT_GRADIENT_PRESET = QCPColorGradient::gpJet;
12 const auto DEFAULT_RANGE = QCPRange{1.0e3, 1.7e7};
12 const auto DEFAULT_RANGE = QCPRange{1.0e3, 1.7e7};
13
13
14 } // namespace
14 } // namespace
15
15
16 std::pair<double, double> SqpColorScale::computeThresholds(const SqpColorScale &scale)
16 std::pair<double, double> SqpColorScale::computeThresholds(const SqpColorScale &scale)
17 {
17 {
18 auto qcpScale = scale.m_Scale;
18 auto qcpScale = scale.m_Scale;
19
19
20 auto colorMaps = qcpScale->colorMaps();
20 auto colorMaps = qcpScale->colorMaps();
21 if (colorMaps.size() != 1) {
21 if (colorMaps.size() != 1) {
22 return {std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN()};
22 return {std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN()};
23 }
23 }
24
24
25 // Computes thresholds
25 // Computes thresholds
26 auto isLogarithmicScale = qcpScale->dataScaleType() == QCPAxis::stLogarithmic;
26 auto isLogarithmicScale = qcpScale->dataScaleType() == QCPAxis::stLogarithmic;
27 auto colorMapData = colorMaps.first()->data();
27 auto colorMapData = colorMaps.first()->data();
28 QCPColorMapIterator begin{colorMapData, true};
28 QCPColorMapIterator begin{colorMapData, true};
29 QCPColorMapIterator end{colorMapData, false};
29 QCPColorMapIterator end{colorMapData, false};
30
30
31 return DataSeriesUtils::thresholds(begin, end, isLogarithmicScale);
31 return DataSeriesUtils::thresholds(begin, end, isLogarithmicScale);
32 }
32 }
33
33
34 SqpColorScale::SqpColorScale(QCustomPlot &plot)
34 SqpColorScale::SqpColorScale(QCustomPlot &plot)
35 : m_Scale{new QCPColorScale{&plot}},
35 : m_Scale{new QCPColorScale{&plot}},
36 m_AutomaticThreshold{true},
36 m_AutomaticThreshold{false},
37 m_GradientPreset{DEFAULT_GRADIENT_PRESET}
37 m_GradientPreset{DEFAULT_GRADIENT_PRESET}
38 {
38 {
39 m_Scale->setGradient(m_GradientPreset);
39 m_Scale->setGradient(m_GradientPreset);
40 m_Scale->setDataRange(DEFAULT_RANGE);
40 m_Scale->setDataRange(DEFAULT_RANGE);
41 }
41 }
42
42
43 void SqpColorScale::updateDataRange() noexcept
43 void SqpColorScale::updateDataRange() noexcept
44 {
44 {
45 // Updates data range only if mode is automatic
45 // Updates data range only if mode is automatic
46 if (!m_AutomaticThreshold) {
46 if (!m_AutomaticThreshold) {
47 return;
47 return;
48 }
48 }
49
49
50 double minThreshold, maxThreshold;
50 double minThreshold, maxThreshold;
51 std::tie(minThreshold, maxThreshold) = computeThresholds(*this);
51 std::tie(minThreshold, maxThreshold) = computeThresholds(*this);
52 if (std::isnan(minThreshold) || std::isnan(maxThreshold)) {
52 if (std::isnan(minThreshold) || std::isnan(maxThreshold)) {
53 qCCritical(LOG_SqpColorScale())
53 qCCritical(LOG_SqpColorScale())
54 << "Can't update data range of color scale: thresholds computed are invalid";
54 << "Can't update data range of color scale: thresholds computed are invalid";
55 return;
55 return;
56 }
56 }
57
57
58 // Updates thresholds
58 // Updates thresholds
59 m_Scale->setDataRange({minThreshold, maxThreshold});
59 m_Scale->setDataRange({minThreshold, maxThreshold});
60 }
60 }
General Comments 0
You need to be logged in to leave comments. Login now