##// END OF EJS Templates
Merge branch 'feature/MockSpectrogram2' into develop
Alexandre Leroux -
r909:c6a1fc96dbd2 merge
parent child
Show More
@@ -383,6 +383,10 public:
383 return std::make_pair(minIt, maxIt);
383 return std::make_pair(minIt, maxIt);
384 }
384 }
385
385
386 /// @return the y-axis associated to the data series
387 /// @todo pass getter as protected and use iterators to access the y-axis data
388 OptionalAxis yAxis() const { return m_YAxis; }
389
386 // /////// //
390 // /////// //
387 // Mutexes //
391 // Mutexes //
388 // /////// //
392 // /////// //
@@ -438,9 +442,6 protected:
438 // necessary to call the sort method here ('other' is sorted)
442 // necessary to call the sort method here ('other' is sorted)
439 }
443 }
440
444
441 /// @return the y-axis associated to the data series
442 OptionalAxis yAxis() const { return m_YAxis; }
443
444 /// Assignment operator
445 /// Assignment operator
445 template <int D>
446 template <int D>
446 DataSeries &operator=(DataSeries<D> other)
447 DataSeries &operator=(DataSeries<D> other)
@@ -41,6 +41,10 public:
41 /// @return gets the data at the index passed in parameter, NaN if the index is outside the
41 /// @return gets the data at the index passed in parameter, NaN if the index is outside the
42 /// bounds of the axis, or if the axis is undefined
42 /// bounds of the axis, or if the axis is undefined
43 double at(int index) const;
43 double at(int index) const;
44
45 ///@return the min and max values of the data on the axis, NaN values if there is no data
46 std::pair<double, double> bounds() const;
47
44 /// @return the number of data on the axis, 0 if the axis is not defined
48 /// @return the number of data on the axis, 0 if the axis is not defined
45 int size() const;
49 int size() const;
46 /// @return the unit of the axis, an empty unit if the axis is not defined
50 /// @return the unit of the axis, an empty unit if the axis is not defined
@@ -44,6 +44,31 double OptionalAxis::at(int index) const
44 }
44 }
45 }
45 }
46
46
47 std::pair<double, double> OptionalAxis::bounds() const
48 {
49 if (!m_Defined || m_Data->size() == 0) {
50 return std::make_pair(std::numeric_limits<double>::quiet_NaN(),
51 std::numeric_limits<double>::quiet_NaN());
52 }
53 else {
54
55 auto minIt = std::min_element(
56 m_Data->cbegin(), m_Data->cend(), [](const auto &it1, const auto &it2) {
57 return SortUtils::minCompareWithNaN(it1.first(), it2.first());
58 });
59
60 // Gets the iterator on the max of all values data
61 auto maxIt = std::max_element(
62 m_Data->cbegin(), m_Data->cend(), [](const auto &it1, const auto &it2) {
63 return SortUtils::maxCompareWithNaN(it1.first(), it2.first());
64 });
65
66 auto pair = std::make_pair(minIt->first(), maxIt->first());
67
68 return std::make_pair(minIt->first(), maxIt->first());
69 }
70 }
71
47 int OptionalAxis::size() const
72 int OptionalAxis::size() const
48 {
73 {
49 return m_Defined ? m_Data->size() : 0;
74 return m_Defined ? m_Data->size() : 0;
@@ -33,7 +33,6 private slots:
33 void testMerge_data();
33 void testMerge_data();
34 void testMerge();
34 void testMerge();
35
35
36 /// @todo ALX: test subdataseries
37 /// Tests get subdata of a spectrogram series
36 /// Tests get subdata of a spectrogram series
38 void testSubDataSeries_data();
37 void testSubDataSeries_data();
39 void testSubDataSeries();
38 void testSubDataSeries();
@@ -34,6 +34,8 struct VisualizationGraphHelper {
34
34
35 static void updateData(PlottablesMap &plottables, std::shared_ptr<IDataSeries> dataSeries,
35 static void updateData(PlottablesMap &plottables, std::shared_ptr<IDataSeries> dataSeries,
36 const SqpRange &dateTime);
36 const SqpRange &dateTime);
37
38 static void setYAxisRange(std::shared_ptr<Variable> variable, QCustomPlot &plot) noexcept;
37 };
39 };
38
40
39 #endif // SCIQLOP_VISUALIZATIONGRAPHHELPER_H
41 #endif // SCIQLOP_VISUALIZATIONGRAPHHELPER_H
@@ -46,7 +46,8 public:
46 /// Returns the list of all variables used in the graph
46 /// Returns the list of all variables used in the graph
47 QList<std::shared_ptr<Variable> > variables() const;
47 QList<std::shared_ptr<Variable> > variables() const;
48
48
49 void setYRange(const SqpRange &range);
49 /// Sets the y-axis range based on the data of a variable
50 void setYRange(std::shared_ptr<Variable> variable);
50 SqpRange graphRange() const noexcept;
51 SqpRange graphRange() const noexcept;
51 void setGraphRange(const SqpRange &range);
52 void setGraphRange(const SqpRange &range);
52
53
@@ -4,6 +4,7
4 #include <Common/ColorUtils.h>
4 #include <Common/ColorUtils.h>
5
5
6 #include <Data/ScalarSeries.h>
6 #include <Data/ScalarSeries.h>
7 #include <Data/SpectrogramSeries.h>
7 #include <Data/VectorSeries.h>
8 #include <Data/VectorSeries.h>
8
9
9 #include <Variable/Variable.h>
10 #include <Variable/Variable.h>
@@ -68,6 +69,24 struct PlottablesCreator<T,
68 };
69 };
69
70
70 /**
71 /**
72 * Specialization of PlottablesCreator for spectrograms
73 * @sa SpectrogramSeries
74 */
75 template <typename T>
76 struct PlottablesCreator<T,
77 typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
78 static PlottablesMap createPlottables(T &dataSeries, QCustomPlot &plot)
79 {
80 PlottablesMap result{};
81 result.insert({0, new QCPColorMap{plot.xAxis, plot.yAxis}});
82
83 plot.replot();
84
85 return result;
86 }
87 };
88
89 /**
71 * Struct used to update plottables, depending on the type of the data series from which to update
90 * Struct used to update plottables, depending on the type of the data series from which to update
72 * them
91 * them
73 * @tparam T the data series' type
92 * @tparam T the data series' type
@@ -75,9 +94,15 struct PlottablesCreator<T,
75 */
94 */
76 template <typename T, typename Enabled = void>
95 template <typename T, typename Enabled = void>
77 struct PlottablesUpdater {
96 struct PlottablesUpdater {
97 static void setPlotYAxisRange(T &, const SqpRange &, QCustomPlot &)
98 {
99 qCCritical(LOG_VisualizationGraphHelper())
100 << QObject::tr("Can't set plot y-axis range: unmanaged data series type");
101 }
102
78 static void updatePlottables(T &, PlottablesMap &, const SqpRange &, bool)
103 static void updatePlottables(T &, PlottablesMap &, const SqpRange &, bool)
79 {
104 {
80 qCCritical(LOG_DataSeries())
105 qCCritical(LOG_VisualizationGraphHelper())
81 << QObject::tr("Can't update plottables: unmanaged data series type");
106 << QObject::tr("Can't update plottables: unmanaged data series type");
82 }
107 }
83 };
108 };
@@ -91,6 +116,24 template <typename T>
91 struct PlottablesUpdater<T,
116 struct PlottablesUpdater<T,
92 typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
117 typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
93 or std::is_base_of<VectorSeries, T>::value> > {
118 or std::is_base_of<VectorSeries, T>::value> > {
119 static void setPlotYAxisRange(T &dataSeries, const SqpRange &xAxisRange, QCustomPlot &plot)
120 {
121 auto minValue = 0., maxValue = 0.;
122
123 dataSeries.lockRead();
124 auto valuesBounds = dataSeries.valuesBounds(xAxisRange.m_TStart, xAxisRange.m_TEnd);
125 auto end = dataSeries.cend();
126 if (valuesBounds.first != end && valuesBounds.second != end) {
127 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
128
129 minValue = rangeValue(valuesBounds.first->minValue());
130 maxValue = rangeValue(valuesBounds.second->maxValue());
131 }
132 dataSeries.unlock();
133
134 plot.yAxis->setRange(QCPRange{minValue, maxValue});
135 }
136
94 static void updatePlottables(T &dataSeries, PlottablesMap &plottables, const SqpRange &range,
137 static void updatePlottables(T &dataSeries, PlottablesMap &plottables, const SqpRange &range,
95 bool rescaleAxes)
138 bool rescaleAxes)
96 {
139 {
@@ -134,11 +177,85 struct PlottablesUpdater<T,
134 };
177 };
135
178
136 /**
179 /**
180 * Specialization of PlottablesUpdater for spectrograms
181 * @sa SpectrogramSeries
182 */
183 template <typename T>
184 struct PlottablesUpdater<T,
185 typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
186 static void setPlotYAxisRange(T &dataSeries, const SqpRange &xAxisRange, QCustomPlot &plot)
187 {
188 double min, max;
189 /// @todo ALX: use iterators here
190 std::tie(min, max) = dataSeries.yAxis().bounds();
191
192 if (!std::isnan(min) && !std::isnan(max)) {
193 plot.yAxis->setRange(QCPRange{min, max});
194 }
195 }
196
197 static void updatePlottables(T &dataSeries, PlottablesMap &plottables, const SqpRange &range,
198 bool rescaleAxes)
199 {
200 if (plottables.empty()) {
201 qCDebug(LOG_VisualizationGraphHelper())
202 << QObject::tr("Can't update spectrogram: no colormap has been associated");
203 return;
204 }
205
206 // Gets the colormap to update (normally there is only one colormap)
207 Q_ASSERT(plottables.size() == 1);
208 auto colormap = dynamic_cast<QCPColorMap *>(plottables.at(0));
209 Q_ASSERT(colormap != nullptr);
210
211 dataSeries.lockRead();
212
213 auto its = dataSeries.xAxisRange(range.m_TStart, range.m_TEnd);
214 /// @todo ALX: use iterators here
215 auto yAxis = dataSeries.yAxis();
216
217 // Gets properties of x-axis and y-axis to set size and range of the colormap
218 auto nbX = std::distance(its.first, its.second);
219 auto xMin = nbX != 0 ? its.first->x() : 0.;
220 auto xMax = nbX != 0 ? (its.second - 1)->x() : 0.;
221
222 auto nbY = yAxis.size();
223 auto yMin = 0., yMax = 0.;
224 if (nbY != 0) {
225 std::tie(yMin, yMax) = yAxis.bounds();
226 }
227
228 colormap->data()->setSize(nbX, nbY);
229 colormap->data()->setRange(QCPRange{xMin, xMax}, QCPRange{yMin, yMax});
230
231 // Sets values
232 auto xIndex = 0;
233 for (auto it = its.first; it != its.second; ++it, ++xIndex) {
234 for (auto yIndex = 0; yIndex < nbY; ++yIndex) {
235 colormap->data()->setCell(xIndex, yIndex, it->value(yIndex));
236 }
237 }
238
239 dataSeries.unlock();
240
241 // Rescales axes
242 auto plot = colormap->parentPlot();
243
244 if (rescaleAxes) {
245 plot->rescaleAxes();
246 }
247
248 plot->replot();
249 }
250 };
251
252 /**
137 * Helper used to create/update plottables
253 * Helper used to create/update plottables
138 */
254 */
139 struct IPlottablesHelper {
255 struct IPlottablesHelper {
140 virtual ~IPlottablesHelper() noexcept = default;
256 virtual ~IPlottablesHelper() noexcept = default;
141 virtual PlottablesMap create(QCustomPlot &plot) const = 0;
257 virtual PlottablesMap create(QCustomPlot &plot) const = 0;
258 virtual void setYAxisRange(const SqpRange &xAxisRange, QCustomPlot &plot) const = 0;
142 virtual void update(PlottablesMap &plottables, const SqpRange &range,
259 virtual void update(PlottablesMap &plottables, const SqpRange &range,
143 bool rescaleAxes = false) const = 0;
260 bool rescaleAxes = false) const = 0;
144 };
261 };
@@ -161,6 +278,11 struct PlottablesHelper : public IPlottablesHelper {
161 PlottablesUpdater<T>::updatePlottables(m_DataSeries, plottables, range, rescaleAxes);
278 PlottablesUpdater<T>::updatePlottables(m_DataSeries, plottables, range, rescaleAxes);
162 }
279 }
163
280
281 void setYAxisRange(const SqpRange &xAxisRange, QCustomPlot &plot) const override
282 {
283 return PlottablesUpdater<T>::setPlotYAxisRange(m_DataSeries, xAxisRange, plot);
284 }
285
164 T &m_DataSeries;
286 T &m_DataSeries;
165 };
287 };
166
288
@@ -170,6 +292,9 std::unique_ptr<IPlottablesHelper> createHelper(std::shared_ptr<IDataSeries> dat
170 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(dataSeries)) {
292 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(dataSeries)) {
171 return std::make_unique<PlottablesHelper<ScalarSeries> >(*scalarSeries);
293 return std::make_unique<PlottablesHelper<ScalarSeries> >(*scalarSeries);
172 }
294 }
295 else if (auto spectrogramSeries = std::dynamic_pointer_cast<SpectrogramSeries>(dataSeries)) {
296 return std::make_unique<PlottablesHelper<SpectrogramSeries> >(*spectrogramSeries);
297 }
173 else if (auto vectorSeries = std::dynamic_pointer_cast<VectorSeries>(dataSeries)) {
298 else if (auto vectorSeries = std::dynamic_pointer_cast<VectorSeries>(dataSeries)) {
174 return std::make_unique<PlottablesHelper<VectorSeries> >(*vectorSeries);
299 return std::make_unique<PlottablesHelper<VectorSeries> >(*vectorSeries);
175 }
300 }
@@ -195,6 +320,19 PlottablesMap VisualizationGraphHelper::create(std::shared_ptr<Variable> variabl
195 }
320 }
196 }
321 }
197
322
323 void VisualizationGraphHelper::setYAxisRange(std::shared_ptr<Variable> variable,
324 QCustomPlot &plot) noexcept
325 {
326 if (variable) {
327 auto helper = createHelper(variable->dataSeries());
328 helper->setYAxisRange(variable->range(), plot);
329 }
330 else {
331 qCDebug(LOG_VisualizationGraphHelper())
332 << QObject::tr("Can't set y-axis range of plot: the variable is null");
333 }
334 }
335
198 void VisualizationGraphHelper::updateData(PlottablesMap &plottables,
336 void VisualizationGraphHelper::updateData(PlottablesMap &plottables,
199 std::shared_ptr<IDataSeries> dataSeries,
337 std::shared_ptr<IDataSeries> dataSeries,
200 const SqpRange &dateTime)
338 const SqpRange &dateTime)
@@ -45,7 +45,6 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
45 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
45 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
46 bool m_DoAcquisition;
46 bool m_DoAcquisition;
47 bool m_IsCalibration;
47 bool m_IsCalibration;
48 QCPItemTracer *m_TextTracer;
49 /// Delegate used to attach rendering features to the plot
48 /// Delegate used to attach rendering features to the plot
50 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
49 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
51 };
50 };
@@ -177,9 +176,14 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
177 return variables;
176 return variables;
178 }
177 }
179
178
180 void VisualizationGraphWidget::setYRange(const SqpRange &range)
179 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
181 {
180 {
182 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
181 if (!variable) {
182 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
183 return;
184 }
185
186 VisualizationGraphHelper::setYAxisRange(variable, *ui->widget);
183 }
187 }
184
188
185 SqpRange VisualizationGraphWidget::graphRange() const noexcept
189 SqpRange VisualizationGraphWidget::graphRange() const noexcept
@@ -271,23 +271,7 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<V
271 this->insertGraph(index, graphWidget);
271 this->insertGraph(index, graphWidget);
272
272
273 graphWidget->addVariable(variable, range);
273 graphWidget->addVariable(variable, range);
274
274 graphWidget->setYRange(variable);
275 // get y using variable range
276 if (auto dataSeries = variable->dataSeries()) {
277 dataSeries->lockRead();
278 auto valuesBounds
279 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
280 auto end = dataSeries->cend();
281 if (valuesBounds.first != end && valuesBounds.second != end) {
282 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
283
284 auto minValue = rangeValue(valuesBounds.first->minValue());
285 auto maxValue = rangeValue(valuesBounds.second->maxValue());
286
287 graphWidget->setYRange(SqpRange{minValue, maxValue});
288 }
289 dataSeries->unlock();
290 }
291
275
292 return graphWidget;
276 return graphWidget;
293 }
277 }
General Comments 0
You need to be logged in to leave comments. Login now