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