##// END OF EJS Templates
Some refac on Spectrograms...
jeandet -
r1472:8b544a6af98d
parent child
Show More
@@ -1,1 +1,1
1 Subproject commit 70d6748a06620f865b683c86c89cc27e1cb0d4b9
1 Subproject commit c6cf2dba079da680390ae2de0522a39964c5e629
@@ -1,591 +1,638
1 #include "Visualization/VisualizationGraphHelper.h"
1 #include "Visualization/VisualizationGraphHelper.h"
2 #include "Visualization/qcustomplot.h"
2 #include "Visualization/qcustomplot.h"
3
3
4 #include <Data/ScalarTimeSerie.h>
4 #include <Data/ScalarTimeSerie.h>
5 #include <Data/SpectrogramTimeSerie.h>
5 #include <Data/SpectrogramTimeSerie.h>
6 #include <Data/TimeSeriesUtils.h>
6 #include <Data/TimeSeriesUtils.h>
7 #include <Data/VectorTimeSerie.h>
7 #include <Data/VectorTimeSerie.h>
8
8
9 #include <Common/cpp_utils.h>
9 #include <Common/cpp_utils.h>
10 #include <Variable/Variable2.h>
10 #include <Variable/Variable2.h>
11 #include <algorithm>
11 #include <algorithm>
12 #include <cmath>
12 #include <cmath>
13
13
14 Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper")
14 Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper")
15
15
16 namespace
16 namespace
17 {
17 {
18
18
19 class SqpDataContainer : public QCPGraphDataContainer
19 class SqpDataContainer : public QCPGraphDataContainer
20 {
20 {
21 public:
21 public:
22 void appendGraphData(const QCPGraphData& data) { mData.append(data); }
22 void appendGraphData(const QCPGraphData& data) { mData.append(data); }
23 };
23 };
24
24
25 /**
25 /**
26 * Struct used to create plottables, depending on the type of the data series from which to create
26 * Struct used to create plottables, depending on the type of the data series from which to create
27 * them
27 * them
28 * @tparam T the data series' type
28 * @tparam T the data series' type
29 * @remarks Default implementation can't create plottables
29 * @remarks Default implementation can't create plottables
30 */
30 */
31 template <typename T, typename Enabled = void>
31 template <typename T, typename Enabled = void>
32 struct PlottablesCreator
32 struct PlottablesCreator
33 {
33 {
34 static PlottablesMap createPlottables(QCustomPlot&, const std::shared_ptr<T>& dataSeries)
34 static PlottablesMap createPlottables(QCustomPlot&, const std::shared_ptr<T>& dataSeries)
35 {
35 {
36 return {};
36 return {};
37 }
37 }
38 };
38 };
39
39
40 PlottablesMap createGraphs(QCustomPlot& plot, int nbGraphs)
40 PlottablesMap createGraphs(QCustomPlot& plot, int nbGraphs)
41 {
41 {
42 PlottablesMap result {};
42 PlottablesMap result {};
43
43
44 // Creates {nbGraphs} QCPGraph to add to the plot
44 // Creates {nbGraphs} QCPGraph to add to the plot
45 for (auto i = 0; i < nbGraphs; ++i)
45 for (auto i = 0; i < nbGraphs; ++i)
46 {
46 {
47 auto graph = plot.addGraph();
47 auto graph = plot.addGraph();
48 result.insert({ i, graph });
48 result.insert({ i, graph });
49 }
49 }
50
50
51 plot.replot();
51 plot.replot();
52
52
53 return result;
53 return result;
54 }
54 }
55
55
56 /**
56 /**
57 * Specialization of PlottablesCreator for scalars
57 * Specialization of PlottablesCreator for scalars
58 * @sa ScalarSeries
58 * @sa ScalarSeries
59 */
59 */
60 template <typename T>
60 template <typename T>
61 struct PlottablesCreator<T, typename std::enable_if_t<std::is_base_of<ScalarTimeSerie, T>::value>>
61 struct PlottablesCreator<T, typename std::enable_if_t<std::is_base_of<ScalarTimeSerie, T>::value>>
62 {
62 {
63 static PlottablesMap createPlottables(QCustomPlot& plot, const std::shared_ptr<T>& dataSeries)
63 static PlottablesMap createPlottables(QCustomPlot& plot, const std::shared_ptr<T>& dataSeries)
64 {
64 {
65 return createGraphs(plot, 1);
65 return createGraphs(plot, 1);
66 }
66 }
67 };
67 };
68
68
69 /**
69 /**
70 * Specialization of PlottablesCreator for vectors
70 * Specialization of PlottablesCreator for vectors
71 * @sa VectorSeries
71 * @sa VectorSeries
72 */
72 */
73 template <typename T>
73 template <typename T>
74 struct PlottablesCreator<T, typename std::enable_if_t<std::is_base_of<VectorTimeSerie, T>::value>>
74 struct PlottablesCreator<T, typename std::enable_if_t<std::is_base_of<VectorTimeSerie, T>::value>>
75 {
75 {
76 static PlottablesMap createPlottables(QCustomPlot& plot, const std::shared_ptr<T>& dataSeries)
76 static PlottablesMap createPlottables(QCustomPlot& plot, const std::shared_ptr<T>& dataSeries)
77 {
77 {
78 return createGraphs(plot, 3);
78 return createGraphs(plot, 3);
79 }
79 }
80 };
80 };
81
81
82 /**
82 /**
83 * Specialization of PlottablesCreator for MultiComponentTimeSeries
83 * Specialization of PlottablesCreator for MultiComponentTimeSeries
84 * @sa VectorSeries
84 * @sa VectorSeries
85 */
85 */
86 template <typename T>
86 template <typename T>
87 struct PlottablesCreator<T,
87 struct PlottablesCreator<T,
88 typename std::enable_if_t<std::is_base_of<MultiComponentTimeSerie, T>::value>>
88 typename std::enable_if_t<std::is_base_of<MultiComponentTimeSerie, T>::value>>
89 {
89 {
90 static PlottablesMap createPlottables(QCustomPlot& plot, const std::shared_ptr<T>& dataSeries)
90 static PlottablesMap createPlottables(QCustomPlot& plot, const std::shared_ptr<T>& dataSeries)
91 {
91 {
92 return createGraphs(plot, dataSeries->size(1));
92 return createGraphs(plot, dataSeries->size(1));
93 }
93 }
94 };
94 };
95
95
96 /**
96 /**
97 * Specialization of PlottablesCreator for spectrograms
97 * Specialization of PlottablesCreator for spectrograms
98 * @sa SpectrogramSeries
98 * @sa SpectrogramSeries
99 */
99 */
100 template <typename T>
100 template <typename T>
101 struct PlottablesCreator<T,
101 struct PlottablesCreator<T,
102 typename std::enable_if_t<std::is_base_of<SpectrogramTimeSerie, T>::value>>
102 typename std::enable_if_t<std::is_base_of<SpectrogramTimeSerie, T>::value>>
103 {
103 {
104 static PlottablesMap createPlottables(QCustomPlot& plot, const std::shared_ptr<T>& dataSeries)
104 static PlottablesMap createPlottables(QCustomPlot& plot, const std::shared_ptr<T>& dataSeries)
105 {
105 {
106 PlottablesMap result {};
106 PlottablesMap result {};
107 result.insert({ 0, new QCPColorMap { plot.xAxis, plot.yAxis } });
107 result.insert({ 0, new QCPColorMap { plot.xAxis, plot.yAxis } });
108
108
109 plot.replot();
109 plot.replot();
110
110
111 return result;
111 return result;
112 }
112 }
113 };
113 };
114
114
115 /**
115 /**
116 * Struct used to update plottables, depending on the type of the data series from which to update
116 * Struct used to update plottables, depending on the type of the data series from which to update
117 * them
117 * them
118 * @tparam T the data series' type
118 * @tparam T the data series' type
119 * @remarks Default implementation can't update plottables
119 * @remarks Default implementation can't update plottables
120 */
120 */
121 template <typename T, typename Enabled = void>
121 template <typename T, typename Enabled = void>
122 struct PlottablesUpdater
122 struct PlottablesUpdater
123 {
123 {
124 static void setPlotYAxisRange(T&, const DateTimeRange&, QCustomPlot&)
124 static void setPlotYAxisRange(T&, const DateTimeRange&, QCustomPlot&)
125 {
125 {
126 qCCritical(LOG_VisualizationGraphHelper())
126 qCCritical(LOG_VisualizationGraphHelper())
127 << QObject::tr("Can't set plot y-axis range: unmanaged data series type");
127 << QObject::tr("Can't set plot y-axis range: unmanaged data series type");
128 }
128 }
129
129
130 static void updatePlottables(T&, PlottablesMap&, const DateTimeRange&, bool)
130 static void updatePlottables(T&, PlottablesMap&, const DateTimeRange&, bool)
131 {
131 {
132 qCCritical(LOG_VisualizationGraphHelper())
132 qCCritical(LOG_VisualizationGraphHelper())
133 << QObject::tr("Can't update plottables: unmanaged data series type");
133 << QObject::tr("Can't update plottables: unmanaged data series type");
134 }
134 }
135 };
135 };
136
136
137 /**
137 /**
138 * Specialization of PlottablesUpdater for scalars and vectors
138 * Specialization of PlottablesUpdater for scalars and vectors
139 * @sa ScalarSeries
139 * @sa ScalarSeries
140 * @sa VectorSeries
140 * @sa VectorSeries
141 */
141 */
142 template <typename T>
142 template <typename T>
143 struct PlottablesUpdater<T, typename std::enable_if_t<std::is_base_of<ScalarTimeSerie, T>::value>>
143 struct PlottablesUpdater<T, typename std::enable_if_t<std::is_base_of<ScalarTimeSerie, T>::value>>
144 {
144 {
145 static void setPlotYAxisRange(T& dataSeries, const DateTimeRange& xAxisRange, QCustomPlot& plot)
145 static void setPlotYAxisRange(T& dataSeries, const DateTimeRange& xAxisRange, QCustomPlot& plot)
146 {
146 {
147 auto minValue = 0., maxValue = 0.;
147 auto minValue = 0., maxValue = 0.;
148 if (auto serie = dynamic_cast<ScalarTimeSerie*>(&dataSeries))
148 if (auto serie = dynamic_cast<ScalarTimeSerie*>(&dataSeries))
149 {
149 {
150 if (serie->size())
150 if (serie->size())
151 {
151 {
152 maxValue = (*std::max_element(std::begin(*serie), std::end(*serie))).v();
152 maxValue = (*std::max_element(std::begin(*serie), std::end(*serie))).v();
153 minValue = (*std::min_element(std::begin(*serie), std::end(*serie))).v();
153 minValue = (*std::min_element(std::begin(*serie), std::end(*serie))).v();
154 }
154 }
155 }
155 }
156 plot.yAxis->setRange(QCPRange { minValue, maxValue });
156 plot.yAxis->setRange(QCPRange { minValue, maxValue });
157 }
157 }
158
158
159 static void updatePlottables(
159 static void updatePlottables(
160 T& dataSeries, PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes)
160 T& dataSeries, PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes)
161 {
161 {
162
162
163 // For each plottable to update, resets its data
163 // For each plottable to update, resets its data
164 for (const auto& plottable : plottables)
164 for (const auto& plottable : plottables)
165 {
165 {
166 if (auto graph = dynamic_cast<QCPGraph*>(plottable.second))
166 if (auto graph = dynamic_cast<QCPGraph*>(plottable.second))
167 {
167 {
168 auto dataContainer = QSharedPointer<SqpDataContainer>::create();
168 auto dataContainer = QSharedPointer<SqpDataContainer>::create();
169 if (auto serie = dynamic_cast<ScalarTimeSerie*>(&dataSeries))
169 if (auto serie = dynamic_cast<ScalarTimeSerie*>(&dataSeries))
170 {
170 {
171 std::for_each(
171 std::for_each(
172 std::begin(*serie), std::end(*serie), [&dataContainer](const auto& value) {
172 std::begin(*serie), std::end(*serie), [&dataContainer](const auto& value) {
173 dataContainer->appendGraphData(QCPGraphData(value.t(), value.v()));
173 dataContainer->appendGraphData(QCPGraphData(value.t(), value.v()));
174 });
174 });
175 }
175 }
176 graph->setData(dataContainer);
176 graph->setData(dataContainer);
177 }
177 }
178 }
178 }
179
179
180 if (!plottables.empty())
180 if (!plottables.empty())
181 {
181 {
182 auto plot = plottables.begin()->second->parentPlot();
182 auto plot = plottables.begin()->second->parentPlot();
183
183
184 if (rescaleAxes)
184 if (rescaleAxes)
185 {
185 {
186 plot->rescaleAxes();
186 plot->rescaleAxes();
187 }
187 }
188 }
188 }
189 }
189 }
190 };
190 };
191
191
192
192
193 template <typename T>
193 template <typename T>
194 struct PlottablesUpdater<T, typename std::enable_if_t<std::is_base_of<VectorTimeSerie, T>::value>>
194 struct PlottablesUpdater<T, typename std::enable_if_t<std::is_base_of<VectorTimeSerie, T>::value>>
195 {
195 {
196 static void setPlotYAxisRange(T& dataSeries, const DateTimeRange& xAxisRange, QCustomPlot& plot)
196 static void setPlotYAxisRange(T& dataSeries, const DateTimeRange& xAxisRange, QCustomPlot& plot)
197 {
197 {
198 double minValue = 0., maxValue = 0.;
198 double minValue = 0., maxValue = 0.;
199 if (auto serie = dynamic_cast<VectorTimeSerie*>(&dataSeries))
199 if (auto serie = dynamic_cast<VectorTimeSerie*>(&dataSeries))
200 {
200 {
201 std::for_each(
201 std::for_each(
202 std::begin(*serie), std::end(*serie), [&minValue, &maxValue](const auto& v) {
202 std::begin(*serie), std::end(*serie), [&minValue, &maxValue](const auto& v) {
203 minValue = std::min({ minValue, v.v().x, v.v().y, v.v().z });
203 minValue = std::min({ minValue, v.v().x, v.v().y, v.v().z });
204 maxValue = std::max({ maxValue, v.v().x, v.v().y, v.v().z });
204 maxValue = std::max({ maxValue, v.v().x, v.v().y, v.v().z });
205 });
205 });
206 }
206 }
207
207
208 plot.yAxis->setRange(QCPRange { minValue, maxValue });
208 plot.yAxis->setRange(QCPRange { minValue, maxValue });
209 }
209 }
210
210
211 static void updatePlottables(
211 static void updatePlottables(
212 T& dataSeries, PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes)
212 T& dataSeries, PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes)
213 {
213 {
214
214
215 // For each plottable to update, resets its data
215 // For each plottable to update, resets its data
216 for (const auto& plottable : plottables)
216 for (const auto& plottable : plottables)
217 {
217 {
218 if (auto graph = dynamic_cast<QCPGraph*>(plottable.second))
218 if (auto graph = dynamic_cast<QCPGraph*>(plottable.second))
219 {
219 {
220 auto dataContainer = QSharedPointer<SqpDataContainer>::create();
220 auto dataContainer = QSharedPointer<SqpDataContainer>::create();
221 if (auto serie = dynamic_cast<VectorTimeSerie*>(&dataSeries))
221 if (auto serie = dynamic_cast<VectorTimeSerie*>(&dataSeries))
222 {
222 {
223 switch (plottable.first)
223 switch (plottable.first)
224 {
224 {
225 case 0:
225 case 0:
226 std::for_each(std::begin(*serie), std::end(*serie),
226 std::for_each(std::begin(*serie), std::end(*serie),
227 [&dataContainer](const auto& value) {
227 [&dataContainer](const auto& value) {
228 dataContainer->appendGraphData(
228 dataContainer->appendGraphData(
229 QCPGraphData(value.t(), value.v().x));
229 QCPGraphData(value.t(), value.v().x));
230 });
230 });
231 break;
231 break;
232 case 1:
232 case 1:
233 std::for_each(std::begin(*serie), std::end(*serie),
233 std::for_each(std::begin(*serie), std::end(*serie),
234 [&dataContainer](const auto& value) {
234 [&dataContainer](const auto& value) {
235 dataContainer->appendGraphData(
235 dataContainer->appendGraphData(
236 QCPGraphData(value.t(), value.v().y));
236 QCPGraphData(value.t(), value.v().y));
237 });
237 });
238 break;
238 break;
239 case 2:
239 case 2:
240 std::for_each(std::begin(*serie), std::end(*serie),
240 std::for_each(std::begin(*serie), std::end(*serie),
241 [&dataContainer](const auto& value) {
241 [&dataContainer](const auto& value) {
242 dataContainer->appendGraphData(
242 dataContainer->appendGraphData(
243 QCPGraphData(value.t(), value.v().z));
243 QCPGraphData(value.t(), value.v().z));
244 });
244 });
245 break;
245 break;
246 default:
246 default:
247 break;
247 break;
248 }
248 }
249 }
249 }
250 graph->setData(dataContainer);
250 graph->setData(dataContainer);
251 }
251 }
252 }
252 }
253
253
254 if (!plottables.empty())
254 if (!plottables.empty())
255 {
255 {
256 auto plot = plottables.begin()->second->parentPlot();
256 auto plot = plottables.begin()->second->parentPlot();
257
257
258 if (rescaleAxes)
258 if (rescaleAxes)
259 {
259 {
260 plot->rescaleAxes();
260 plot->rescaleAxes();
261 }
261 }
262 }
262 }
263 }
263 }
264 };
264 };
265
265
266
266
267 template <typename T>
267 template <typename T>
268 struct PlottablesUpdater<T,
268 struct PlottablesUpdater<T,
269 typename std::enable_if_t<std::is_base_of<MultiComponentTimeSerie, T>::value>>
269 typename std::enable_if_t<std::is_base_of<MultiComponentTimeSerie, T>::value>>
270 {
270 {
271 static void setPlotYAxisRange(T& dataSeries, const DateTimeRange& xAxisRange, QCustomPlot& plot)
271 static void setPlotYAxisRange(T& dataSeries, const DateTimeRange& xAxisRange, QCustomPlot& plot)
272 {
272 {
273 double minValue = 0., maxValue = 0.;
273 double minValue = 0., maxValue = 0.;
274 if (auto serie = dynamic_cast<MultiComponentTimeSerie*>(&dataSeries))
274 if (auto serie = dynamic_cast<MultiComponentTimeSerie*>(&dataSeries))
275 {
275 {
276 std::for_each(std::begin(*serie), std::end(*serie), [&minValue, &maxValue](auto& v) {
276 std::for_each(std::begin(*serie), std::end(*serie), [&minValue, &maxValue](auto& v) {
277 minValue = std::min(minValue, std::min_element(v.begin(), v.end())->v());
277 minValue = std::min(minValue, std::min_element(v.begin(), v.end())->v());
278 maxValue = std::max(maxValue, std::max_element(v.begin(), v.end())->v());
278 maxValue = std::max(maxValue, std::max_element(v.begin(), v.end())->v());
279 });
279 });
280 }
280 }
281 plot.yAxis->setRange(QCPRange { minValue, maxValue });
281 plot.yAxis->setRange(QCPRange { minValue, maxValue });
282 }
282 }
283
283
284 static void updatePlottables(
284 static void updatePlottables(
285 T& dataSeries, PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes)
285 T& dataSeries, PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes)
286 {
286 {
287 for (const auto& plottable : plottables)
287 for (const auto& plottable : plottables)
288 {
288 {
289 if (auto graph = dynamic_cast<QCPGraph*>(plottable.second))
289 if (auto graph = dynamic_cast<QCPGraph*>(plottable.second))
290 {
290 {
291 auto dataContainer = QSharedPointer<SqpDataContainer>::create();
291 auto dataContainer = QSharedPointer<SqpDataContainer>::create();
292 if (auto serie = dynamic_cast<MultiComponentTimeSerie*>(&dataSeries))
292 if (auto serie = dynamic_cast<MultiComponentTimeSerie*>(&dataSeries))
293 {
293 {
294 // TODO
294 // TODO
295 std::for_each(std::begin(*serie), std::end(*serie),
295 std::for_each(std::begin(*serie), std::end(*serie),
296 [&dataContainer, component = plottable.first](const auto& value) {
296 [&dataContainer, component = plottable.first](const auto& value) {
297 dataContainer->appendGraphData(
297 dataContainer->appendGraphData(
298 QCPGraphData(value.t(), value[component]));
298 QCPGraphData(value.t(), value[component]));
299 });
299 });
300 }
300 }
301 graph->setData(dataContainer);
301 graph->setData(dataContainer);
302 }
302 }
303 }
303 }
304
304
305 if (!plottables.empty())
305 if (!plottables.empty())
306 {
306 {
307 auto plot = plottables.begin()->second->parentPlot();
307 auto plot = plottables.begin()->second->parentPlot();
308
308
309 if (rescaleAxes)
309 if (rescaleAxes)
310 {
310 {
311 plot->rescaleAxes();
311 plot->rescaleAxes();
312 }
312 }
313 }
313 }
314 }
314 }
315 };
315 };
316
316
317 /*=============================================================*/
317 /*=============================================================*/
318 // TODO move this to dedicated srcs
318 // TODO move this to dedicated srcs
319 /*=============================================================*/
319 /*=============================================================*/
320 struct ColomapProperties
320 struct ColomapProperties
321 {
321 {
322 int h_size_px;
322 int h_size_px;
323 int v_size_px;
323 int v_size_px;
324 double h_resolutuon;
324 double h_resolutuon;
325 double v_resolutuon;
325 double v_resolutuon;
326 };
326 };
327
327
328 inline ColomapProperties CMAxisAnalysis(const TimeSeriesUtils::axis_properties& xAxisProperties,
328 inline ColomapProperties CMAxisAnalysis(const TimeSeriesUtils::axis_properties& xAxisProperties,
329 const TimeSeriesUtils::axis_properties& yAxisProperties)
329 const TimeSeriesUtils::axis_properties& yAxisProperties)
330 {
330 {
331 int colormap_h_size
331 int colormap_h_size
332 = std::min(32000, static_cast<int>(xAxisProperties.range / xAxisProperties.max_resolution));
332 = std::min(32000, static_cast<int>(xAxisProperties.range / xAxisProperties.max_resolution));
333 int colormap_v_size = static_cast<int>(yAxisProperties.range / yAxisProperties.max_resolution);
333 int colormap_v_size = static_cast<int>(yAxisProperties.range / yAxisProperties.max_resolution);
334 double colormap_h_resolution = xAxisProperties.range / static_cast<double>(colormap_h_size);
334 double colormap_h_resolution = xAxisProperties.range / static_cast<double>(colormap_h_size);
335 double colormap_v_resolution = yAxisProperties.range / static_cast<double>(colormap_v_size);
335 double colormap_v_resolution = yAxisProperties.range / static_cast<double>(colormap_v_size);
336 return ColomapProperties { colormap_h_size, colormap_v_size, colormap_h_resolution,
336 return ColomapProperties { colormap_h_size, colormap_v_size, colormap_h_resolution,
337 colormap_v_resolution };
337 colormap_v_resolution };
338 }
338 }
339
339
340
341 template <bool condition, typename T, typename U>
342 std::enable_if_t<condition, T> constexpr conditional_v(T first, U second)
343 {
344 return first;
345 }
346
347 template <bool condition, typename T, typename U>
348 std::enable_if_t<!condition, U> constexpr conditional_v(T first, U second)
349 {
350 return second;
351 }
352
353 template <bool reversedAxis = true, bool reversedData = true>
340 inline std::vector<std::pair<int, int>> build_access_pattern(const std::vector<double>& axis,
354 inline std::vector<std::pair<int, int>> build_access_pattern(const std::vector<double>& axis,
341 const TimeSeriesUtils::axis_properties& axisProperties,
355 const TimeSeriesUtils::axis_properties& axisProperties,
342 const ColomapProperties& colormap_properties)
356 const ColomapProperties& colormap_properties)
343 {
357 {
344 std::vector<std::pair<int, int>> access_pattern;
358 std::vector<std::pair<int, int>> access_pattern;
345 for (int index = 0, cel_index = axis.size() - 1; index < colormap_properties.v_size_px; index++)
359 for (int index = 0, axis_index = conditional_v<reversedAxis>(axis.size() - 1, 0),
360 data_index = conditional_v<reversedData>(axis.size() - 1, 0);
361 index < colormap_properties.v_size_px; index++)
346 {
362 {
347 double current_y = pow(10., (axisProperties.max_resolution * index) + axisProperties.min);
363 double current_y = (axisProperties.max_resolution * index) + axisProperties.min;
348 if (current_y > axis[cel_index])
364 if (current_y > axis[axis_index])
349 cel_index--;
365 {
350 access_pattern.push_back({ index, cel_index });
366 conditional_v<reversedAxis>(
367 [&axis_index]() { axis_index--; }, [&axis_index]() { axis_index++; })();
368 conditional_v<reversedData>(
369 [&data_index]() { data_index--; }, [&data_index]() { data_index++; })();
370 }
371 access_pattern.push_back({ index, data_index });
351 }
372 }
352 return access_pattern;
373 return access_pattern;
353 }
374 }
354
375
355 /*=============================================================*/
376 inline bool is_log(const std::vector<double>& axis)
356
357 /**
358 * Specialization of PlottablesUpdater for spectrograms
359 * @sa SpectrogramSeries
360 */
361 template <typename T>
362 struct PlottablesUpdater<T,
363 typename std::enable_if_t<std::is_base_of<SpectrogramTimeSerie, T>::value>>
364 {
377 {
365 static void setPlotYAxisRange(T& dataSeries, const DateTimeRange& xAxisRange, QCustomPlot& plot)
378 if (axis.size() > 2)
366 {
379 {
367 auto [minValue, maxValue] = dataSeries.axis_range(1);
380 auto first = axis.front(), midle = axis[axis.size() / 2], last = axis.back();
368 std::cout << "min=" << minValue << " max=" << maxValue << std::endl;
381 auto error_linear = (midle - (last + first) / 2) / midle;
369 plot.yAxis->setRange(QCPRange { minValue, maxValue });
382 first = log10(first);
383 midle = log10(midle);
384 last = log10(last);
385 auto error_log = (midle - (last + first) / 2) / midle;
386 return error_log < error_linear;
370 }
387 }
371
388 return false;
372 static void updatePlottables(
373 T& dataSeries, PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes)
374 {
375 if (plottables.empty())
376 {
377 qCDebug(LOG_VisualizationGraphHelper())
378 << QObject::tr("Can't update spectrogram: no colormap has been associated");
379 return;
380 }
389 }
381
390
382 // Gets the colormap to update (normally there is only one colormap)
391 template <typename accessPattern_t, typename colomapT, typename axProp_t, typename cmProp_t>
383 Q_ASSERT(plottables.size() == 1);
392 inline void fill_data(SpectrogramTimeSerie* serie, colomapT* colormap,
384 auto colormap = dynamic_cast<QCPColorMap*>(plottables.at(0));
393 const accessPattern_t& y_access_pattern, const axProp_t& xAxisProperties,
385 Q_ASSERT(colormap != nullptr);
394 const cmProp_t& colormap_properties)
386 auto plot = colormap->parentPlot();
387 auto [minValue, maxValue] = dataSeries.axis_range(1);
388 plot->yAxis->setRange(QCPRange { minValue, maxValue });
389 if (auto serie = dynamic_cast<SpectrogramTimeSerie*>(&dataSeries))
390 {
395 {
391 if (serie->size(0) > 2)
392 {
393 const auto& xAxis = serie->axis(0);
394 auto yAxis = serie->axis(1); // copy for in place reverse order
395 std::reverse(std::begin(yAxis), std::end(yAxis));
396 auto xAxisProperties = TimeSeriesUtils::axis_analysis<TimeSeriesUtils::IsLinear,
397 TimeSeriesUtils::CheckMedian>(xAxis, serie->min_sampling);
398 auto yAxisProperties = TimeSeriesUtils::axis_analysis<TimeSeriesUtils::IsLog,
399 TimeSeriesUtils::DontCheckMedian>(yAxis);
400 auto colormap_properties = CMAxisAnalysis(xAxisProperties, yAxisProperties);
401
402 colormap->data()->setSize(
403 colormap_properties.h_size_px, colormap_properties.v_size_px);
404 colormap->data()->setRange(
405 QCPRange { xAxisProperties.min, xAxisProperties.max }, { minValue, maxValue });
406
407 auto y_access_pattern
408 = build_access_pattern(serie->axis(1), yAxisProperties, colormap_properties);
409
410 auto line = serie->begin();
396 auto line = serie->begin();
411 auto next_line = line + 1;
397 auto next_line = line + 1;
412 double current_time = xAxisProperties.min;
398 double current_time = xAxisProperties.min;
413 int x_index = 0;
399 int x_index = 0;
414 auto x_min_resolution
400 auto x_min_resolution
415 = std::fmin(2. * serie->max_sampling, xAxisProperties.max_resolution * 100.);
401 = std::fmin(2. * serie->max_sampling, xAxisProperties.max_resolution * 100.);
416 std::vector<double> line_values(serie->size(1));
402 std::vector<double> line_values(serie->size(1));
417 double avg_coef = 0.;
403 double avg_coef = 0.;
418 while (x_index < colormap_properties.h_size_px)
404 while (x_index < colormap_properties.h_size_px)
419 {
405 {
420 if (next_line != std::end(*serie) and current_time >= next_line->t())
406 if (next_line != std::end(*serie) and current_time >= next_line->t())
421 {
407 {
422 line = next_line;
408 line = next_line;
423 next_line++;
409 next_line++;
424 }
410 }
425 if ((current_time - xAxisProperties.min)
411 if ((current_time - xAxisProperties.min)
426 > (static_cast<double>(x_index + 1) * colormap_properties.h_resolutuon))
412 > (static_cast<double>(x_index + 1) * colormap_properties.h_resolutuon))
427 {
413 {
428 std::for_each(std::cbegin(y_access_pattern), std::cend(y_access_pattern),
414 std::for_each(std::cbegin(y_access_pattern), std::cend(y_access_pattern),
429 [&colormap, &line_values, x_index, avg_coef](const auto& acc) {
415 [&colormap, &line_values, x_index, avg_coef](const auto& acc) {
430 colormap->data()->setCell(
416 colormap->data()->setCell(
431 x_index, acc.first, line_values[acc.second] / avg_coef);
417 x_index, acc.first, line_values[acc.second] / avg_coef);
432 });
418 });
433 std::fill(std::begin(line_values), std::end(line_values), 0.);
419 std::fill(std::begin(line_values), std::end(line_values), 0.);
434 x_index++;
420 x_index++;
435 avg_coef = 0.;
421 avg_coef = 0.;
436 }
422 }
437 if (line->t() + x_min_resolution > current_time)
423 if (line->t() + x_min_resolution > current_time)
438 {
424 {
439 {
425 {
440 std::transform(std::begin(*line), std::end(*line),
426 std::transform(std::begin(*line), std::end(*line), std::cbegin(line_values),
441 std::cbegin(line_values), std::begin(line_values),
427 std::begin(line_values),
442 [](const auto& input, auto output) { return input.v() + output; });
428 [](const auto& input, auto output) { return input.v() + output; });
443 }
429 }
444 avg_coef += 1.;
430 avg_coef += 1.;
445 }
431 }
446 else
432 else
447 {
433 {
448 for (int y_index = 0; y_index < colormap_properties.v_size_px; y_index++)
434 for (int y_index = 0; y_index < colormap_properties.v_size_px; y_index++)
449 {
435 {
450 if (avg_coef > 0.)
436 if (avg_coef > 0.)
451 {
437 {
452 std::fill(std::begin(line_values), std::end(line_values), 0);
438 std::fill(std::begin(line_values), std::end(line_values), 0);
453 }
439 }
454 }
440 }
455 }
441 }
456 current_time += xAxisProperties.max_resolution * 0.9;
442 current_time += xAxisProperties.max_resolution * 0.9;
457 }
443 }
458 }
444 }
445
446 /*=============================================================*/
447
448 /**
449 * Specialization of PlottablesUpdater for spectrograms
450 * @sa SpectrogramSeries
451 */
452 template <typename T>
453 struct PlottablesUpdater<T,
454 typename std::enable_if_t<std::is_base_of<SpectrogramTimeSerie, T>::value>>
455 {
456 static void setPlotYAxisRange(T& dataSeries, const DateTimeRange& xAxisRange, QCustomPlot& plot)
457 {
458 auto [minValue, maxValue] = dataSeries.axis_range(1);
459 plot.yAxis->setRange(QCPRange { minValue, maxValue });
460 }
461
462 static void updatePlottables(
463 T& dataSeries, PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes)
464 {
465 if (plottables.empty())
466 {
467 qCDebug(LOG_VisualizationGraphHelper())
468 << QObject::tr("Can't update spectrogram: no colormap has been associated");
469 return;
470 }
471
472 // Gets the colormap to update (normally there is only one colormap)
473 Q_ASSERT(plottables.size() == 1);
474 auto colormap = dynamic_cast<QCPColorMap*>(plottables.at(0));
475 Q_ASSERT(colormap != nullptr);
476 auto plot = colormap->parentPlot();
477 auto [minValue, maxValue] = dataSeries.axis_range(1);
478 plot->yAxis->setRange(QCPRange { minValue, maxValue });
479 if (auto serie = dynamic_cast<SpectrogramTimeSerie*>(&dataSeries))
480 {
481 if (serie->size(0) > 2)
482 {
483 if (serie->y_is_log)
484 colormap->setDataScaleType(QCPAxis::stLogarithmic);
485 else
486 colormap->setDataScaleType(QCPAxis::stLinear);
487 const auto& xAxis = serie->axis(0);
488 auto yAxis = serie->axis(1); // copy for in place reverse order
489 auto y_is_log = is_log(yAxis);
490 std::reverse(std::begin(yAxis), std::end(yAxis));
491 auto xAxisProperties = TimeSeriesUtils::axis_analysis<TimeSeriesUtils::IsLinear,
492 TimeSeriesUtils::CheckMedian>(xAxis, serie->min_sampling);
493 auto yAxisProperties = TimeSeriesUtils::axis_analysis<TimeSeriesUtils::IsLog,
494 TimeSeriesUtils::DontCheckMedian>(yAxis);
495 auto colormap_properties = CMAxisAnalysis(xAxisProperties, yAxisProperties);
496
497 colormap->data()->setSize(
498 colormap_properties.h_size_px, colormap_properties.v_size_px);
499 colormap->data()->setRange(
500 QCPRange { xAxisProperties.min, xAxisProperties.max }, { minValue, maxValue });
501
502 auto y_access_pattern = build_access_pattern<false, true>(
503 yAxis, yAxisProperties, colormap_properties);
504 fill_data(serie, colormap, y_access_pattern, xAxisProperties, colormap_properties);
505 }
459 colormap->rescaleDataRange(true);
506 colormap->rescaleDataRange(true);
460 if (rescaleAxes)
507 if (rescaleAxes)
461 {
508 {
462 plot->rescaleAxes();
509 plot->rescaleAxes();
463 }
510 }
464 }
511 }
465 }
512 }
466 };
513 };
467
514
468 /**
515 /**
469 * Helper used to create/update plottables
516 * Helper used to create/update plottables
470 */
517 */
471 struct IPlottablesHelper
518 struct IPlottablesHelper
472 {
519 {
473 virtual ~IPlottablesHelper() noexcept = default;
520 virtual ~IPlottablesHelper() noexcept = default;
474 virtual PlottablesMap create(QCustomPlot& plot) const = 0;
521 virtual PlottablesMap create(QCustomPlot& plot) const = 0;
475 virtual void setYAxisRange(const DateTimeRange& xAxisRange, QCustomPlot& plot) const = 0;
522 virtual void setYAxisRange(const DateTimeRange& xAxisRange, QCustomPlot& plot) const = 0;
476 virtual void update(
523 virtual void update(
477 PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes = false) const = 0;
524 PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes = false) const = 0;
478 };
525 };
479
526
480 /**
527 /**
481 * Default implementation of IPlottablesHelper, which takes data series to create/update
528 * Default implementation of IPlottablesHelper, which takes data series to create/update
482 * plottables
529 * plottables
483 * @tparam T the data series' type
530 * @tparam T the data series' type
484 */
531 */
485 template <typename T>
532 template <typename T>
486 struct PlottablesHelper : public IPlottablesHelper
533 struct PlottablesHelper : public IPlottablesHelper
487 {
534 {
488 explicit PlottablesHelper(std::shared_ptr<T> dataSeries) : m_DataSeries { dataSeries } {}
535 explicit PlottablesHelper(std::shared_ptr<T> dataSeries) : m_DataSeries { dataSeries } {}
489
536
490 PlottablesMap create(QCustomPlot& plot) const override
537 PlottablesMap create(QCustomPlot& plot) const override
491 {
538 {
492 return PlottablesCreator<T>::createPlottables(plot, m_DataSeries);
539 return PlottablesCreator<T>::createPlottables(plot, m_DataSeries);
493 }
540 }
494
541
495 void update(
542 void update(
496 PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes) const override
543 PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes) const override
497 {
544 {
498 if (m_DataSeries)
545 if (m_DataSeries)
499 {
546 {
500 PlottablesUpdater<T>::updatePlottables(*m_DataSeries, plottables, range, rescaleAxes);
547 PlottablesUpdater<T>::updatePlottables(*m_DataSeries, plottables, range, rescaleAxes);
501 }
548 }
502 else
549 else
503 {
550 {
504 qCCritical(LOG_VisualizationGraphHelper()) << "Can't update plottables: inconsistency "
551 qCCritical(LOG_VisualizationGraphHelper()) << "Can't update plottables: inconsistency "
505 "between the type of data series and the "
552 "between the type of data series and the "
506 "type supposed";
553 "type supposed";
507 }
554 }
508 }
555 }
509
556
510 void setYAxisRange(const DateTimeRange& xAxisRange, QCustomPlot& plot) const override
557 void setYAxisRange(const DateTimeRange& xAxisRange, QCustomPlot& plot) const override
511 {
558 {
512 if (m_DataSeries)
559 if (m_DataSeries)
513 {
560 {
514 PlottablesUpdater<T>::setPlotYAxisRange(*m_DataSeries, xAxisRange, plot);
561 PlottablesUpdater<T>::setPlotYAxisRange(*m_DataSeries, xAxisRange, plot);
515 }
562 }
516 else
563 else
517 {
564 {
518 qCCritical(LOG_VisualizationGraphHelper()) << "Can't update plottables: inconsistency "
565 qCCritical(LOG_VisualizationGraphHelper()) << "Can't update plottables: inconsistency "
519 "between the type of data series and the "
566 "between the type of data series and the "
520 "type supposed";
567 "type supposed";
521 }
568 }
522 }
569 }
523
570
524 std::shared_ptr<T> m_DataSeries;
571 std::shared_ptr<T> m_DataSeries;
525 };
572 };
526
573
527 /// Creates IPlottablesHelper according to the type of data series a variable holds
574 /// Creates IPlottablesHelper according to the type of data series a variable holds
528 std::unique_ptr<IPlottablesHelper> createHelper(std::shared_ptr<Variable2> variable) noexcept
575 std::unique_ptr<IPlottablesHelper> createHelper(std::shared_ptr<Variable2> variable) noexcept
529 {
576 {
530 switch (variable->type())
577 switch (variable->type())
531 {
578 {
532 case DataSeriesType::SCALAR:
579 case DataSeriesType::SCALAR:
533 return std::make_unique<PlottablesHelper<ScalarTimeSerie>>(
580 return std::make_unique<PlottablesHelper<ScalarTimeSerie>>(
534 std::dynamic_pointer_cast<ScalarTimeSerie>(variable->data()));
581 std::dynamic_pointer_cast<ScalarTimeSerie>(variable->data()));
535 case DataSeriesType::SPECTROGRAM:
582 case DataSeriesType::SPECTROGRAM:
536 return std::make_unique<PlottablesHelper<SpectrogramTimeSerie>>(
583 return std::make_unique<PlottablesHelper<SpectrogramTimeSerie>>(
537 std::dynamic_pointer_cast<SpectrogramTimeSerie>(variable->data()));
584 std::dynamic_pointer_cast<SpectrogramTimeSerie>(variable->data()));
538 case DataSeriesType::VECTOR:
585 case DataSeriesType::VECTOR:
539 return std::make_unique<PlottablesHelper<VectorTimeSerie>>(
586 return std::make_unique<PlottablesHelper<VectorTimeSerie>>(
540 std::dynamic_pointer_cast<VectorTimeSerie>(variable->data()));
587 std::dynamic_pointer_cast<VectorTimeSerie>(variable->data()));
541 case DataSeriesType::MULTICOMPONENT:
588 case DataSeriesType::MULTICOMPONENT:
542 return std::make_unique<PlottablesHelper<MultiComponentTimeSerie>>(
589 return std::make_unique<PlottablesHelper<MultiComponentTimeSerie>>(
543 std::dynamic_pointer_cast<MultiComponentTimeSerie>(variable->data()));
590 std::dynamic_pointer_cast<MultiComponentTimeSerie>(variable->data()));
544 default:
591 default:
545 // Creates default helper
592 // Creates default helper
546 break;
593 break;
547 }
594 }
548
595
549 return std::make_unique<PlottablesHelper<TimeSeries::ITimeSerie>>(nullptr);
596 return std::make_unique<PlottablesHelper<TimeSeries::ITimeSerie>>(nullptr);
550 }
597 }
551
598
552 } // namespace
599 } // namespace
553
600
554 PlottablesMap VisualizationGraphHelper::create(
601 PlottablesMap VisualizationGraphHelper::create(
555 std::shared_ptr<Variable2> variable, QCustomPlot& plot) noexcept
602 std::shared_ptr<Variable2> variable, QCustomPlot& plot) noexcept
556 {
603 {
557 if (variable)
604 if (variable)
558 {
605 {
559 auto helper = createHelper(variable);
606 auto helper = createHelper(variable);
560 auto plottables = helper->create(plot);
607 auto plottables = helper->create(plot);
561 return plottables;
608 return plottables;
562 }
609 }
563 else
610 else
564 {
611 {
565 qCDebug(LOG_VisualizationGraphHelper())
612 qCDebug(LOG_VisualizationGraphHelper())
566 << QObject::tr("Can't create graph plottables : the variable is null");
613 << QObject::tr("Can't create graph plottables : the variable is null");
567 return PlottablesMap {};
614 return PlottablesMap {};
568 }
615 }
569 }
616 }
570
617
571 void VisualizationGraphHelper::setYAxisRange(
618 void VisualizationGraphHelper::setYAxisRange(
572 std::shared_ptr<Variable2> variable, QCustomPlot& plot) noexcept
619 std::shared_ptr<Variable2> variable, QCustomPlot& plot) noexcept
573 {
620 {
574 if (variable)
621 if (variable)
575 {
622 {
576 auto helper = createHelper(variable);
623 auto helper = createHelper(variable);
577 helper->setYAxisRange(variable->range(), plot);
624 helper->setYAxisRange(variable->range(), plot);
578 }
625 }
579 else
626 else
580 {
627 {
581 qCDebug(LOG_VisualizationGraphHelper())
628 qCDebug(LOG_VisualizationGraphHelper())
582 << QObject::tr("Can't set y-axis range of plot: the variable is null");
629 << QObject::tr("Can't set y-axis range of plot: the variable is null");
583 }
630 }
584 }
631 }
585
632
586 void VisualizationGraphHelper::updateData(
633 void VisualizationGraphHelper::updateData(
587 PlottablesMap& plottables, std::shared_ptr<Variable2> variable, const DateTimeRange& dateTime)
634 PlottablesMap& plottables, std::shared_ptr<Variable2> variable, const DateTimeRange& dateTime)
588 {
635 {
589 auto helper = createHelper(variable);
636 auto helper = createHelper(variable);
590 helper->update(plottables, dateTime);
637 helper->update(plottables, dateTime);
591 }
638 }
@@ -1,100 +1,100
1 import traceback
1 import traceback
2 import os
2 import os
3 from datetime import datetime, timedelta, timezone
3 from datetime import datetime, timedelta, timezone
4 import PythonProviders
4 import PythonProviders
5 import pysciqlopcore
5 import pysciqlopcore
6 import numpy as np
6 import numpy as np
7 import requests
7 import requests
8 import copy
8 import copy
9 from spwc.amda import AMDA
9 from spwc.amda import AMDA
10
10
11 amda = AMDA()
11 amda = AMDA()
12
12
13 def amda_make_scalar(var=None):
13 def amda_make_scalar(var=None):
14 if var is None:
14 if var is None:
15 return pysciqlopcore.ScalarTimeSerie(1)
15 return pysciqlopcore.ScalarTimeSerie(1)
16 else:
16 else:
17 return pysciqlopcore.ScalarTimeSerie(var.time,var.data)
17 return pysciqlopcore.ScalarTimeSerie(var.time,var.data)
18
18
19 def amda_make_vector(var=None):
19 def amda_make_vector(var=None):
20 if var is None:
20 if var is None:
21 return pysciqlopcore.VectorTimeSerie(1)
21 return pysciqlopcore.VectorTimeSerie(1)
22 else:
22 else:
23 return pysciqlopcore.VectorTimeSerie(var.time,var.data)
23 return pysciqlopcore.VectorTimeSerie(var.time,var.data)
24
24
25 def amda_make_multi_comp(var=None):
25 def amda_make_multi_comp(var=None):
26 if var is None:
26 if var is None:
27 return pysciqlopcore.MultiComponentTimeSerie((0,2))
27 return pysciqlopcore.MultiComponentTimeSerie((0,2))
28 else:
28 else:
29 return pysciqlopcore.MultiComponentTimeSerie(var.time,var.data)
29 return pysciqlopcore.MultiComponentTimeSerie(var.time,var.data)
30
30
31 def amda_make_spectro(var=None):
31 def amda_make_spectro(var=None):
32 if var is None:
32 if var is None:
33 return pysciqlopcore.SpectrogramTimeSerie((0,2))
33 return pysciqlopcore.SpectrogramTimeSerie((0,2))
34 else:
34 else:
35 min_sampling = float(var.meta.get("DATASET_MIN_SAMPLING","nan"))
35 min_sampling = float(var.meta.get("DATASET_MIN_SAMPLING","nan"))
36 max_sampling = float(var.meta.get("DATASET_MAX_SAMPLING","nan"))
36 max_sampling = float(var.meta.get("DATASET_MAX_SAMPLING","nan"))
37 if "PARAMETER_TABLE_MIN_VALUES[1]" in var.meta:
37 if "PARAMETER_TABLE_MIN_VALUES[1]" in var.meta:
38 min_v = np.array([ float(v) for v in var.meta["PARAMETER_TABLE_MIN_VALUES[1]"].split(',') ])
38 min_v = np.array([ float(v) for v in var.meta["PARAMETER_TABLE_MIN_VALUES[1]"].split(',') ])
39 max_v = np.array([ float(v) for v in var.meta["PARAMETER_TABLE_MAX_VALUES[1]"].split(',') ])
39 max_v = np.array([ float(v) for v in var.meta["PARAMETER_TABLE_MAX_VALUES[1]"].split(',') ])
40 y = (max_v + min_v)/2.
40 y = (max_v + min_v)/2.
41 elif "PARAMETER_TABLE_MIN_VALUES[0]" in var.meta:
41 elif "PARAMETER_TABLE_MIN_VALUES[0]" in var.meta:
42 min_v = np.array([ float(v) for v in var.meta["PARAMETER_TABLE_MIN_VALUES[0]"].split(',') ])
42 min_v = np.array([ float(v) for v in var.meta["PARAMETER_TABLE_MIN_VALUES[0]"].split(',') ])
43 max_v = np.array([ float(v) for v in var.meta["PARAMETER_TABLE_MAX_VALUES[0]"].split(',') ])
43 max_v = np.array([ float(v) for v in var.meta["PARAMETER_TABLE_MAX_VALUES[0]"].split(',') ])
44 y = (max_v + min_v)/2.
44 y = (max_v + min_v)/2.
45 else:
45 else:
46 y = np.logspace(1,3,var.data.shape[1])[::-1]
46 y = np.logspace(1,3,var.data.shape[1])[::-1]
47 return pysciqlopcore.SpectrogramTimeSerie(var.time,y,var.data,min_sampling,max_sampling)
47 return pysciqlopcore.SpectrogramTimeSerie(var.time,y,var.data,min_sampling,max_sampling,True)
48
48
49 def amda_get_sample(metadata,start,stop):
49 def amda_get_sample(metadata,start,stop):
50 ts_type = amda_make_scalar
50 ts_type = amda_make_scalar
51 try:
51 try:
52 param_id = None
52 param_id = None
53 for key,value in metadata:
53 for key,value in metadata:
54 if key == 'xml:id':
54 if key == 'xml:id':
55 param_id = value
55 param_id = value
56 elif key == 'type':
56 elif key == 'type':
57 if value == 'vector':
57 if value == 'vector':
58 ts_type = amda_make_vector
58 ts_type = amda_make_vector
59 elif value == 'multicomponent':
59 elif value == 'multicomponent':
60 ts_type = amda_make_multi_comp
60 ts_type = amda_make_multi_comp
61 elif value == 'spectrogram':
61 elif value == 'spectrogram':
62 ts_type = amda_make_spectro
62 ts_type = amda_make_spectro
63 tstart=datetime.fromtimestamp(start, tz=timezone.utc)
63 tstart=datetime.fromtimestamp(start, tz=timezone.utc)
64 tend=datetime.fromtimestamp(stop, tz=timezone.utc)
64 tend=datetime.fromtimestamp(stop, tz=timezone.utc)
65 var = amda.get_parameter(start_time=tstart, stop_time=tend, parameter_id=param_id, method="REST")
65 var = amda.get_parameter(start_time=tstart, stop_time=tend, parameter_id=param_id, method="REST")
66 return ts_type(var)
66 return ts_type(var)
67 except Exception as e:
67 except Exception as e:
68 print(traceback.format_exc())
68 print(traceback.format_exc())
69 print("Error in amda.py ",str(e))
69 print("Error in amda.py ",str(e))
70 return ts_type()
70 return ts_type()
71
71
72
72
73 if len(amda.component) is 0:
73 if len(amda.component) is 0:
74 amda.update_inventory()
74 amda.update_inventory()
75 parameters = copy.deepcopy(amda.parameter)
75 parameters = copy.deepcopy(amda.parameter)
76 for name,component in amda.component.items():
76 for name,component in amda.component.items():
77 if 'components' in parameters[component['parameter']]:
77 if 'components' in parameters[component['parameter']]:
78 parameters[component['parameter']]['components'].append(component)
78 parameters[component['parameter']]['components'].append(component)
79 else:
79 else:
80 parameters[component['parameter']]['components']=[component]
80 parameters[component['parameter']]['components']=[component]
81
81
82 products = []
82 products = []
83 for key,parameter in parameters.items():
83 for key,parameter in parameters.items():
84 path = f"/AMDA/{parameter['mission']}/{parameter.get('observatory','')}/{parameter['instrument']}/{parameter['dataset']}/{parameter['name']}"
84 path = f"/AMDA/{parameter['mission']}/{parameter.get('observatory','')}/{parameter['instrument']}/{parameter['dataset']}/{parameter['name']}"
85 components = [component['name'] for component in parameter.get('components',[])]
85 components = [component['name'] for component in parameter.get('components',[])]
86 metadata = [ (key,item) for key,item in parameter.items() if key is not 'components' ]
86 metadata = [ (key,item) for key,item in parameter.items() if key is not 'components' ]
87 n_components = parameter.get('size',0)
87 n_components = parameter.get('size',0)
88 if n_components == '3':
88 if n_components == '3':
89 metadata.append(("type","vector"))
89 metadata.append(("type","vector"))
90 elif parameter.get('display_type','')=="spectrogram":
90 elif parameter.get('display_type','')=="spectrogram":
91 metadata.append(("type","spectrogram"))
91 metadata.append(("type","spectrogram"))
92 elif n_components !=0:
92 elif n_components !=0:
93 metadata.append(("type","multicomponent"))
93 metadata.append(("type","multicomponent"))
94 else:
94 else:
95 metadata.append(("type","scalar"))
95 metadata.append(("type","scalar"))
96 products.append( (path, components, metadata))
96 products.append( (path, components, metadata))
97
97
98 PythonProviders.register_product(products, amda_get_sample)
98 PythonProviders.register_product(products, amda_get_sample)
99
99
100
100
@@ -1,96 +1,96
1 import traceback
1 import traceback
2 import pandas as pds
2 import pandas as pds
3 import PythonProviders
3 import PythonProviders
4 import pysciqlopcore
4 import pysciqlopcore
5 import numpy as np
5 import numpy as np
6 import math
6 import math
7 from spwc.cache import _cache
7 from spwc.cache import _cache
8 from spwc.common.datetime_range import DateTimeRange
8 from spwc.common.datetime_range import DateTimeRange
9 from functools import partial
9 from functools import partial
10 from datetime import datetime, timedelta, timezone
10 from datetime import datetime, timedelta, timezone
11 from spwc.common.variable import SpwcVariable
11 from spwc.common.variable import SpwcVariable
12
12
13 def make_scalar(x):
13 def make_scalar(x):
14 y = np.cos(x/10.)
14 y = np.cos(x/10.)
15 return SpwcVariable(time=x, data=y)
15 return SpwcVariable(time=x, data=y)
16
16
17 def make_vector(x):
17 def make_vector(x):
18 v=np.ones((len(x),3))
18 v=np.ones((len(x),3))
19 for i in range(3):
19 for i in range(3):
20 v.transpose()[:][i] = np.cos(x/10. + float(i)) + (100. * np.cos(x/10000. + float(i)))
20 v.transpose()[:][i] = np.cos(x/10. + float(i)) + (100. * np.cos(x/10000. + float(i)))
21 return SpwcVariable(time=x, data=v)
21 return SpwcVariable(time=x, data=v)
22
22
23
23
24 def make_multicomponent(x):
24 def make_multicomponent(x):
25 v=np.ones((len(x),4))
25 v=np.ones((len(x),4))
26 for i in range(4):
26 for i in range(4):
27 v.transpose()[:][i] = float(i+1) * np.cos(x/10. + float(i))
27 v.transpose()[:][i] = float(i+1) * np.cos(x/10. + float(i))
28 return SpwcVariable(time=x, data=v)
28 return SpwcVariable(time=x, data=v)
29
29
30 def make_spectrogram(x):
30 def make_spectrogram(x):
31 v=np.ones((len(x),32))
31 v=np.ones((len(x),32))
32 for i in range(32):
32 for i in range(32):
33 v.transpose()[:][i] = 100.*(2.+ float(i+1) * np.cos(x/1024. + float(i)))
33 v.transpose()[:][i] = 100.*(2.+ float(i+1) * np.cos(x/1024. + float(i)))
34 return SpwcVariable(time=x, data=v)
34 return SpwcVariable(time=x, data=v)
35
35
36
36
37 def _get_data(p_type, start, stop):
37 def _get_data(p_type, start, stop):
38 if type(start) is datetime:
38 if type(start) is datetime:
39 start = start.timestamp()
39 start = start.timestamp()
40 stop = stop.timestamp()
40 stop = stop.timestamp()
41 x = np.arange(math.ceil(start), math.floor(stop))
41 x = np.arange(math.ceil(start), math.floor(stop))
42 if p_type == 'scalar':
42 if p_type == 'scalar':
43 return make_scalar(x)
43 return make_scalar(x)
44 if p_type == 'vector':
44 if p_type == 'vector':
45 return make_vector(x)
45 return make_vector(x)
46 if p_type == 'multicomponent':
46 if p_type == 'multicomponent':
47 return make_multicomponent(x)
47 return make_multicomponent(x)
48 if p_type == 'spectrogram':
48 if p_type == 'spectrogram':
49 return make_spectrogram(np.arange(math.ceil(start), math.floor(stop),15.))
49 return make_spectrogram(np.arange(math.ceil(start), math.floor(stop),15.))
50 return None
50 return None
51
51
52 def get_data(metadata,start,stop):
52 def get_data(metadata,start,stop):
53 ts_type = pysciqlopcore.ScalarTimeSerie
53 ts_type = pysciqlopcore.ScalarTimeSerie
54 default_ctor_args = 1
54 default_ctor_args = 1
55 use_cache = False
55 use_cache = False
56 p_type = 'scalar'
56 p_type = 'scalar'
57 try:
57 try:
58 for key,value in metadata:
58 for key,value in metadata:
59 if key == 'type':
59 if key == 'type':
60 p_type = value
60 p_type = value
61 if value == 'vector':
61 if value == 'vector':
62 ts_type = pysciqlopcore.VectorTimeSerie
62 ts_type = pysciqlopcore.VectorTimeSerie
63 elif value == 'multicomponent':
63 elif value == 'multicomponent':
64 ts_type = pysciqlopcore.MultiComponentTimeSerie
64 ts_type = pysciqlopcore.MultiComponentTimeSerie
65 default_ctor_args = (0,2)
65 default_ctor_args = (0,2)
66 elif value == 'spectrogram':
66 elif value == 'spectrogram':
67 ts_type = lambda t,values: pysciqlopcore.SpectrogramTimeSerie(t,np.logspace(1,3,32)[::-1],values,np.nan,np.nan)
67 ts_type = lambda t,values: pysciqlopcore.SpectrogramTimeSerie(t,np.logspace(1,3,32)[::-1],values,np.nan,np.nan,True)
68 default_ctor_args = (0,2)
68 default_ctor_args = (0,2)
69 if key == 'cache' and value == 'true':
69 if key == 'cache' and value == 'true':
70 use_cache = True
70 use_cache = True
71 if use_cache:
71 if use_cache:
72 cache_product = f"tests/{p_type}"
72 cache_product = f"tests/{p_type}"
73 var = _cache.get_data(cache_product, DateTimeRange(datetime.fromtimestamp(start, tz=timezone.utc), datetime.fromtimestamp(stop, tz=timezone.utc)),
73 var = _cache.get_data(cache_product, DateTimeRange(datetime.fromtimestamp(start, tz=timezone.utc), datetime.fromtimestamp(stop, tz=timezone.utc)),
74 partial(_get_data, p_type),
74 partial(_get_data, p_type),
75 fragment_hours=24)
75 fragment_hours=24)
76 else:
76 else:
77 print("No Cache")
77 print("No Cache")
78 var = _get_data(p_type, start, stop)
78 var = _get_data(p_type, start, stop)
79 return ts_type(var.time,var.data)
79 return ts_type(var.time,var.data)
80 except Exception as e:
80 except Exception as e:
81 print(traceback.format_exc())
81 print(traceback.format_exc())
82 print("Error in test.py ",str(e))
82 print("Error in test.py ",str(e))
83 return ts_type(default_ctor_args)
83 return ts_type(default_ctor_args)
84
84
85 products = [
85 products = [
86 ("/tests/without_cache/scalar",[],[("type","scalar")]),
86 ("/tests/without_cache/scalar",[],[("type","scalar")]),
87 ("/tests/without_cache/vector",[],[("type","vector")]),
87 ("/tests/without_cache/vector",[],[("type","vector")]),
88 ("/tests/without_cache/multicomponent",[],[("type","multicomponent"),('size','4')]),
88 ("/tests/without_cache/multicomponent",[],[("type","multicomponent"),('size','4')]),
89 ("/tests/without_cache/spectrogram",[],[("type","spectrogram"),('size','32')]),
89 ("/tests/without_cache/spectrogram",[],[("type","spectrogram"),('size','32')]),
90 ("/tests/with_cache/scalar",[],[("type","scalar"), ("cache","true")]),
90 ("/tests/with_cache/scalar",[],[("type","scalar"), ("cache","true")]),
91 ("/tests/with_cache/vector",[],[("type","vector"), ("cache","true")]),
91 ("/tests/with_cache/vector",[],[("type","vector"), ("cache","true")]),
92 ("/tests/with_cache/multicomponent",[],[("type","multicomponent"),('size','4'), ("cache","true")])
92 ("/tests/with_cache/multicomponent",[],[("type","multicomponent"),('size','4'), ("cache","true")])
93 ]
93 ]
94
94
95
95
96 PythonProviders.register_product(products ,get_data)
96 PythonProviders.register_product(products ,get_data)
General Comments 0
You need to be logged in to leave comments. Login now