Commit 3cf118118221e740de4f2e3907900973ec700c34
1 parent
dc7a34dc
Exists in
master
and in
37 other branches
FFT Validated and I add Test fucntions
Showing
7 changed files
with
1074 additions
and
678 deletions
Show diff stats
src/ParamOutputImpl/Plot/InstantPlot/PlotFunction.cc
... | ... | @@ -14,6 +14,7 @@ |
14 | 14 | #include "fonctions/fourier/DiscreteFourierTransform.cc" |
15 | 15 | #include "fonctions/fourier/DiscreteFourierTransform.hh" |
16 | 16 | #include <algorithm> |
17 | +#include <complex> | |
17 | 18 | #include <limits> |
18 | 19 | #include <numeric> |
19 | 20 | |
... | ... | @@ -45,14 +46,162 @@ namespace plot |
45 | 46 | } |
46 | 47 | } |
47 | 48 | |
49 | + void PlotFunction::createParameters(std::list<std::string> &usedParametersId_) | |
50 | + { | |
51 | + PanelPlotOutput::createParameters(usedParametersId_); | |
52 | + } | |
53 | + | |
54 | + void PlotFunction::writeContext(ContextFileWriter &writer, AMDA::Parameters::TimeIntervalList::iterator currentTimeInterval) | |
55 | + { | |
56 | + writer.startElement("panel"); | |
57 | + _panel->writeContext(_pls, writer); | |
58 | + | |
59 | + writer.startElement("parameters"); | |
60 | + | |
61 | + for (ParameterAxesList::iterator it = _parameterAxesList.begin(); | |
62 | + it != _parameterAxesList.end(); ++it) | |
63 | + { | |
64 | + AMDA::Parameters::ParameterSPtr originalParam = | |
65 | + _parameterManager.getParameter(it->_originalParamId); | |
66 | + | |
67 | + // Retrieve ParamInfo Manager | |
68 | + ParamMgr *piMgr = ParamMgr::getInstance(); | |
69 | + ParamInfoSPtr paramInfo = piMgr->getParamInfoFromId(it->_originalParamId); | |
70 | + | |
71 | + double resol = originalParam->getDataWriterTemplate()->getMinSampling(); | |
72 | + std::string resolstr = std::to_string(resol); | |
73 | + | |
74 | + writer.startElement("parameter"); | |
75 | + writer.addAttribute("id", paramInfo->getName().c_str()); | |
76 | + writer.addAttribute("name", paramInfo->getName().c_str()); | |
77 | + writer.addAttribute("shortname", paramInfo->getShortName().c_str()); | |
78 | + writer.addAttribute("MinSampling", resolstr.c_str()); | |
79 | + writer.addAttribute("unit", paramInfo->getUnits().c_str()); | |
80 | + | |
81 | + std::ostringstream legends; | |
82 | + | |
83 | + for (auto lSeries : it->getYSeriePropertiesList()) | |
84 | + { | |
85 | + writer.startElement("serie"); | |
86 | + writer.addAttribute("id", std::to_string(lSeries.getId()).c_str()); | |
87 | + | |
88 | + std::ostringstream labels; | |
89 | + for (auto lIndex : lSeries.getIndexList(_pParameterValues)) | |
90 | + { | |
91 | + std::string label = PanelPlotOutput::getSerieParamsLegendString(lSeries, lIndex, it->_originalParamId); | |
92 | + labels << label << ";"; | |
93 | + } | |
94 | + | |
95 | + writer.addAttribute("serie_label", labels.str().c_str()); | |
96 | + writer.addAttribute("dimSize", "-1"); | |
97 | + | |
98 | + std::ostringstream values; | |
99 | + | |
100 | + plot::ParameterData &data = (*_pParameterValues)[lSeries.getParamId()]; | |
101 | + for (int index_time = 0; index_time < data.getSize(); index_time++) | |
102 | + { | |
103 | + double time = data.getTimes()[index_time]; | |
104 | + values << std::fixed << time; | |
105 | + | |
106 | + for (auto lIndex : lSeries.getIndexList(_pParameterValues)) | |
107 | + { | |
108 | + double value = data.getValues(lIndex)[index_time]; | |
109 | + values << ";" << std::fixed << value; | |
110 | + } | |
111 | + values << "|"; | |
112 | + } | |
113 | + writer.addAttribute("data", values.str().c_str()); | |
114 | + writer.endElement(); | |
115 | + } | |
116 | + | |
117 | + if (it->getSpectroProperties() != nullptr) | |
118 | + { | |
119 | + plot::ParameterData &data = (*_pParameterValues)[it->getSpectroProperties()->getParamId()]; | |
120 | + SpectroProperties *pSpectro = it->getSpectroProperties().get(); | |
121 | + int dimSize = -1; | |
122 | + if (pSpectro->getRelatedDim() == 0) | |
123 | + dimSize = data.getDim1Size(); | |
124 | + else | |
125 | + dimSize = data.getDim2Size(); | |
126 | + | |
127 | + std::ostringstream values; | |
128 | + for (int index_time = 0; index_time < data.getSize(); index_time++) | |
129 | + { | |
130 | + double time = data.getTimes()[index_time]; | |
131 | + values << std::fixed << time; | |
132 | + double valueTemp = 0.0; | |
133 | + for (int j = 0; j < dimSize; j++) | |
134 | + { | |
135 | + double value; | |
136 | + if (pSpectro->getRelatedDim() == 0) | |
137 | + value = data.getValues(AMDA::Common::ParameterIndexComponent(j, -1), 0)[index_time]; | |
138 | + else | |
139 | + value = data.getValues(AMDA::Common::ParameterIndexComponent(-1, j), 0)[index_time]; | |
140 | + valueTemp += value; | |
141 | + } | |
142 | + values << ";" << std::fixed << valueTemp << "|"; | |
143 | + LOG4CXX_DEBUG(gLogger, time << std::fixed << " COUCOU " << valueTemp); | |
144 | + } | |
145 | + | |
146 | + writer.startElement("serie"); | |
147 | + writer.addAttribute("id", "1"); | |
148 | + writer.addAttribute("serie_label", ";"); | |
149 | + writer.addAttribute("dimSize", std::to_string(dimSize).c_str()); | |
150 | + writer.addAttribute("data", values.str().c_str()); | |
151 | + writer.endElement(); | |
152 | + } | |
153 | + writer.endElement(); | |
154 | + } | |
155 | + writer.endElement(); | |
156 | + writer.endElement(); | |
157 | + } | |
158 | + | |
159 | + void PlotFunction::applyFunction() | |
160 | + { | |
161 | + std::string paramId = ""; | |
162 | + bool isSpectro = false; | |
163 | + SeriesProperties lSeries; | |
164 | + for (auto parameter : _parameterAxesList) | |
165 | + { | |
166 | + paramId = parameter._originalParamId; | |
167 | + for (auto lSeries : parameter.getYSeriePropertiesList()) | |
168 | + { | |
169 | + for (auto lIndex : lSeries.getIndexList(_pParameterValues)) | |
170 | + { | |
171 | + std::string id = std::to_string(lSeries.getId()) + "_" + lSeries.getParamId() + "_" + std::to_string(lIndex.getDim1Index()); | |
172 | + plot::ParameterData &data = (*_pParameterValues)[lSeries.getParamId()]; | |
173 | + PlotFunction::compute(lIndex, data, &lSeries, nullptr, parameter._originalParamId); | |
174 | + } | |
175 | + } | |
176 | + } | |
177 | + | |
178 | + for (auto parameter : _parameterAxesList) | |
179 | + { | |
180 | + paramId = parameter._originalParamId; | |
181 | + if (parameter.getSpectroProperties() != nullptr) | |
182 | + { | |
183 | + isSpectro = true; | |
184 | + ParameterData &data = (*_pParameterValues)[parameter.getSpectroProperties()->getParamId()]; | |
185 | + SpectroProperties *pSpectro = parameter.getSpectroProperties().get(); | |
186 | + PlotFunction::compute(AMDA::Common::ParameterIndexComponent(-1, -1), data, nullptr, pSpectro, parameter._originalParamId); | |
187 | + } | |
188 | + } | |
189 | + | |
190 | + PlotFunction::createXAxis(); | |
191 | + PlotFunction::createYAxis(paramId, isSpectro); | |
192 | + } | |
193 | + | |
48 | 194 | void PlotFunction::drawSeries(double startDate, double stopDate, int intervalIndex, std::string pParamId, |
49 | 195 | SeriesProperties &pSerie, |
50 | 196 | AMDA::Common::ParameterIndexComponent pParamIndex, |
51 | 197 | ParameterAxes ¶m, bool moreThanOneSerieForAxis) |
52 | 198 | { |
53 | 199 | std::string id = std::to_string(pSerie.getId()) + "_" + pSerie.getParamId() + "_" + std::to_string(pParamIndex.getDim1Index()); |
200 | + LOG4CXX_DEBUG(gLogger, " id Serie " << id); | |
54 | 201 | std::vector<double> xValues = xValuesMap[id]; |
55 | 202 | std::vector<double> yValues = yValuesMap[id]; |
203 | + std::string ss = PanelPlotOutput::getSerieParamsLegendString(pSerie, pParamIndex, pParamId); | |
204 | + LOG4CXX_DEBUG(gLogger, " HHHHH" << ss); | |
56 | 205 | |
57 | 206 | double *coloredComputedValues = NULL; |
58 | 207 | int nbValues = yValues.size(); |
... | ... | @@ -83,28 +232,46 @@ namespace plot |
83 | 232 | nbValues, xValuesTemp, yValuesTemp, coloredComputedValues); |
84 | 233 | } |
85 | 234 | |
86 | - void PlotFunction::configureSeriesAxis() | |
235 | + void PlotFunction::drawInstantPlot() | |
87 | 236 | { |
88 | - //_panel->_leftMargin = 10; | |
89 | - //_panel->_rightMargin = 5; | |
90 | - //_panel->_bottomMargin = 4; | |
91 | - | |
92 | - SeriesProperties lSeries; | |
93 | 237 | for (auto parameter : _parameterAxesList) |
94 | 238 | { |
95 | - for (auto lSeries : parameter.getYSeriePropertiesList()) | |
239 | + if (parameter.getSpectroProperties() != nullptr) | |
96 | 240 | { |
97 | - for (auto lIndex : lSeries.getIndexList(_pParameterValues)) | |
98 | - { | |
99 | - std::string id = std::to_string(lSeries.getId()) + "_" + lSeries.getParamId() + "_" + std::to_string(lIndex.getDim1Index()); | |
100 | - plot::ParameterData data = (*_pParameterValues)[lSeries.getParamId()]; | |
101 | - PlotFunction::compute(lIndex, data, id, lSeries.getParamId()); | |
102 | - } | |
241 | + std::string pramId = parameter.getSpectroProperties()->getParamId(); | |
242 | + std::vector<double> xValues = xValuesMap[pramId]; | |
243 | + std::vector<double> yValues = yValuesMap[pramId]; | |
244 | + plot::SeriesProperties *pSerie = new plot::SeriesProperties(); | |
245 | + | |
246 | + double *coloredComputedValues = NULL; | |
247 | + int nbValues = yValues.size(); | |
248 | + | |
249 | + double *yValuesTemp = &yValues[0]; | |
250 | + double *xValuesTemp = &xValues[0]; | |
251 | + | |
252 | + pSerie->setXAxisId(X_AXIS_ID); | |
253 | + pSerie->setYAxisId(Y_AXIS_ID); | |
254 | + | |
255 | + PanelPlotOutput::drawSeries(0, 0, 0, "", | |
256 | + *pSerie, AMDA::Common::ParameterIndexComponent(-1, -1), parameter, false); | |
257 | + | |
258 | + Color lineColor = getSerieLineColor(*pSerie, false); | |
259 | + Color symbolColor = getSerieSymbolColor(*pSerie, lineColor); | |
260 | + | |
261 | + drawSymbols( | |
262 | + pSerie->getSymbolProperties().getType(), | |
263 | + pSerie->getSymbolProperties().getSize(), 1., | |
264 | + symbolColor, | |
265 | + nbValues, xValuesTemp, yValuesTemp, coloredComputedValues); | |
266 | + | |
267 | + drawLines( | |
268 | + pSerie->getLineProperties().getType(), | |
269 | + pSerie->getLineProperties().getStyle(), | |
270 | + pSerie->getLineProperties().getWidth(), | |
271 | + lineColor, | |
272 | + nbValues, xValuesTemp, yValuesTemp, coloredComputedValues); | |
103 | 273 | } |
104 | 274 | } |
105 | - | |
106 | - PlotFunction::createXAxis(); | |
107 | - PlotFunction::createYAxis(); | |
108 | 275 | } |
109 | 276 | |
110 | 277 | void PlotFunction::createXAxis() |
... | ... | @@ -112,6 +279,8 @@ namespace plot |
112 | 279 | double minValue = 0; |
113 | 280 | double maxValue = 0; |
114 | 281 | PlotFunction::getMinMax(xValuesMap, &minValue, &maxValue); |
282 | + LOG4CXX_DEBUG(gLogger, " min X " << minValue); | |
283 | + LOG4CXX_DEBUG(gLogger, " man X " << maxValue); | |
115 | 284 | // Create X axis |
116 | 285 | boost::shared_ptr<TimeAxis> lXAxis(new TimeAxis()); |
117 | 286 | lXAxis.get()->_timeFormat = "%H:%M"; |
... | ... | @@ -132,18 +301,22 @@ namespace plot |
132 | 301 | _panel->addAxis(X_AXIS_ID, lXAxis); |
133 | 302 | } |
134 | 303 | |
135 | - void PlotFunction::createYAxis() | |
304 | + void PlotFunction::createYAxis(std::string paramId, bool isSpectro) | |
136 | 305 | { |
137 | 306 | std::string y_label = ""; |
138 | 307 | if (function == PlotFunction::Function::AVG) |
139 | - y_label = "AVG"; | |
140 | - else | |
141 | - y_label = "Amplitude"; | |
308 | + y_label = ""; | |
309 | + else if (function == PlotFunction::Function::SUM) | |
310 | + y_label = ""; | |
311 | + else if (function == PlotFunction::Function::FFT) | |
312 | + y_label = "DSP"; | |
142 | 313 | |
143 | 314 | double minValue = 0; |
144 | 315 | double maxValue = 0; |
145 | 316 | |
146 | 317 | PlotFunction::getMinMax(yValuesMap, &minValue, &maxValue); |
318 | + LOG4CXX_DEBUG(gLogger, " min Y " << minValue); | |
319 | + LOG4CXX_DEBUG(gLogger, " man Y " << maxValue); | |
147 | 320 | // Create X axis |
148 | 321 | boost::shared_ptr<Axis> lYAxis(new Axis(false)); |
149 | 322 | plot::Range range_x = Range(minValue - abs(minValue) * 0.10, maxValue + abs(maxValue) * 0.1); |
... | ... | @@ -159,6 +332,16 @@ namespace plot |
159 | 332 | lYAxis.get()->_showTickMark = true; |
160 | 333 | lYAxis.get()->_used = true; |
161 | 334 | // add X Axis to panel |
335 | + if (isSpectro) | |
336 | + { | |
337 | + AxisLegendManager::setAxisLegendForSpectro(this, lYAxis, paramId); | |
338 | + } | |
339 | + else | |
340 | + { | |
341 | + AxisLegendManager::AxisParamsComponents axisParamsComponents; | |
342 | + axisParamsComponents[paramId].push_back(ParameterIndexComponentColor(1, -1, lYAxis->_color)); | |
343 | + AxisLegendManager::setAxisLegendForSeries(this, lYAxis, axisParamsComponents); | |
344 | + } | |
162 | 345 | _panel->addAxis(Y_AXIS_ID, lYAxis); |
163 | 346 | } |
164 | 347 | |
... | ... | @@ -181,12 +364,24 @@ namespace plot |
181 | 364 | *maxToFill = maxValue; |
182 | 365 | } |
183 | 366 | |
184 | - void PlotFunction::compute(AMDA::Common::ParameterIndexComponent pParamIndex, plot::ParameterData data, std::string id, std::string param_id) | |
367 | + void PlotFunction::compute(AMDA::Common::ParameterIndexComponent pParamIndex, plot::ParameterData &data, SeriesProperties *pSerie, SpectroProperties *pSpectro, std::string paramOriginID) | |
185 | 368 | { |
186 | 369 | double samplingValue = 60.0; |
187 | 370 | int nb_points = data.getSize(); |
371 | + std::string param_id, id; | |
188 | 372 | |
189 | - auto it = find(paramsNbPoints.begin(), paramsNbPoints.end(), param_id); | |
373 | + if (pSerie == nullptr) | |
374 | + { | |
375 | + param_id = pSpectro->getParamId(); | |
376 | + id = param_id; | |
377 | + } | |
378 | + else | |
379 | + { | |
380 | + param_id = pSerie->getParamId(); | |
381 | + id = std::to_string(pSerie->getId()) + "_" + param_id + "_" + std::to_string(pParamIndex.getDim1Index()); | |
382 | + } | |
383 | + | |
384 | + auto it = find(paramsNbPoints.begin(), paramsNbPoints.end(), paramOriginID); | |
190 | 385 | // If parameter was found |
191 | 386 | if (it != paramsNbPoints.end()) |
192 | 387 | { |
... | ... | @@ -196,57 +391,129 @@ namespace plot |
196 | 391 | } |
197 | 392 | else |
198 | 393 | { |
199 | - std::stringstream lError; | |
394 | + /*std::stringstream lError; | |
200 | 395 | lError << "PlotFunction::compute" |
201 | - << ": param with id " << param_id << " is not found in param_nb_points xml node."; | |
396 | + << ": param with id " << paramOriginID << " is not found in param_nb_points xml node."; | |
202 | 397 | LOG4CXX_DEBUG(gLogger, lError.str()); |
203 | - BOOST_THROW_EXCEPTION(PanelPlotOutputException() << AMDA::errno_code(AMDA_ERROR_PLOTFUNCTION_PARAM_NOT_FOUND) << AMDA::ex_msg(lError.str())); | |
398 | + BOOST_THROW_EXCEPTION(PanelPlotOutputException() << AMDA::errno_code(AMDA_ERROR_PLOTFUNCTION_PARAM_NOT_FOUND) << AMDA::ex_msg(lError.str()));*/ | |
204 | 399 | } |
205 | 400 | |
206 | - double *values = data.getValues(pParamIndex, 0); | |
401 | + std::vector<double> xValues; | |
402 | + std::vector<double> yValues; | |
207 | 403 | |
208 | - double *timeValues = &data.getTimes()[0]; | |
404 | + int dimSize = -1; | |
405 | + if (pSpectro != nullptr) | |
406 | + if (pSpectro->getRelatedDim() == 0) | |
407 | + dimSize = data.getDim1Size(); | |
408 | + else | |
409 | + dimSize = data.getDim2Size(); | |
209 | 410 | |
210 | - std::vector<double> signal; | |
211 | - for (int i = 0; i < data.getSize(); i++) | |
212 | - signal.push_back(values[i]); | |
411 | + for (int index_time = 0; index_time < data.getSize(); index_time++) | |
412 | + { | |
413 | + double time = data.getTimes()[index_time]; | |
414 | + xValues.push_back(time); | |
213 | 415 | |
214 | - std::vector<double> xValues; | |
215 | - std::vector<double> yValues; | |
416 | + double valueTemp = 0.0; | |
417 | + for (int j = 0; j < dimSize; j++) | |
418 | + { | |
419 | + double value; | |
420 | + if (pSpectro->getRelatedDim() == 0) | |
421 | + value = data.getValues(AMDA::Common::ParameterIndexComponent(j, -1), 0)[index_time]; | |
422 | + else | |
423 | + value = data.getValues(AMDA::Common::ParameterIndexComponent(-1, j), 0)[index_time]; | |
424 | + valueTemp += value; | |
425 | + } | |
216 | 426 | |
217 | - if (function == PlotFunction::Function::AVG) | |
427 | + LOG4CXX_DEBUG(gLogger, time << std::fixed << " " << valueTemp); | |
428 | + if (dimSize < 0) | |
429 | + valueTemp = data.getValues(pParamIndex, 0)[index_time]; | |
430 | + | |
431 | + yValues.push_back(valueTemp); | |
432 | + } | |
433 | + | |
434 | + if (function == PlotFunction::Function::SUM) | |
218 | 435 | { |
219 | - double sum = std::accumulate(signal.begin(), signal.end(), 0); | |
220 | - for (int i = 0; i < data.getSize(); i++) | |
436 | + if (dimSize < 0) | |
221 | 437 | { |
222 | - yValues.push_back(sum / data.getSize()); | |
223 | - xValues.push_back(timeValues[i]); | |
438 | + double sum = std::accumulate(yValues.begin(), yValues.end(), 0); | |
439 | + yValues.assign(yValues.size(), sum); | |
224 | 440 | } |
225 | 441 | } |
226 | - else | |
442 | + else if (function == PlotFunction::Function::AVG) | |
443 | + { | |
444 | + int size = dimSize; | |
445 | + if (dimSize < 0) | |
446 | + { | |
447 | + double sum = std::accumulate(yValues.begin(), yValues.end(), 0); | |
448 | + yValues.assign(yValues.size(), sum); | |
449 | + size = data.getSize(); | |
450 | + } | |
451 | + | |
452 | + transform(yValues.begin(), yValues.end(), yValues.begin(), [size](double &c) | |
453 | + { return c / size; }); | |
454 | + } | |
455 | + else if (function == PlotFunction::Function::FFT) | |
227 | 456 | { |
228 | - DiscreteFourierTransform<double, double> DFT(std::min(nb_points, data.getSize()), signal, 1 / samplingValue); | |
229 | - DFT.compute(); | |
457 | + DiscreteFourierTransform<double, double> DFT(std::min(nb_points, data.getSize()), yValues, 1.0 / samplingValue); | |
458 | + // DFT.compute(); | |
459 | + | |
460 | + std::vector<double> vect; | |
461 | + vect.push_back(1); | |
462 | + vect.push_back(2); | |
463 | + vect.push_back(1); | |
464 | + vect.push_back(-1); | |
465 | + vect.push_back(1.5); | |
466 | + | |
467 | + std::vector<std::complex<double>> vectOUT = DFT.fft(vect); | |
468 | + for (int u = 0; u < vectOUT.size(); u++) | |
469 | + { | |
470 | + LOG4CXX_DEBUG(gLogger, "Real part: " << real(vectOUT[u]) << " Imaginary part: " << imag(vectOUT[u]) << " " << abs(vectOUT[u])); | |
471 | + } | |
230 | 472 | |
231 | - yValues = DFT.getAmplitudes(); | |
473 | + vectOUT = DFT.dft(vect); | |
474 | + for (int u = 0; u < vectOUT.size(); u++) | |
475 | + { | |
476 | + LOG4CXX_DEBUG(gLogger, "Real part: " << real(vectOUT[u]) << " Imaginary part: " << imag(vectOUT[u]) << " " << abs(vectOUT[u])); | |
477 | + } | |
478 | + | |
479 | + std::vector<double> x_ = DFT.createTestPoints(600, 1.0 / 800); | |
480 | + std::vector<double> y_ = DFT.createTestFunction(x_); | |
481 | + std::vector<std::complex<double>> ph = DFT.dft(y_); | |
482 | + LOG4CXX_DEBUG(gLogger, "size of x_ : " << x_.size() << " size of y " << y_.size() << " size of phasors " << ph.size()); | |
483 | + DFT.setPhasors(ph); | |
484 | + for (int u = 0; u < ph.size(); u++) | |
485 | + { | |
486 | + std::complex<double> mycomplex = ph[u]; | |
487 | + } | |
488 | + std::vector<double> dsp = DFT.computeDSP(ph); | |
489 | + for (int u = 0; u < dsp.size(); u++) | |
490 | + { | |
491 | + LOG4CXX_DEBUG(gLogger, " DSP " << dsp[u]); | |
492 | + } | |
493 | + | |
494 | + yValues = dsp; | |
495 | + // dsp; // DFT.getAmplitudes(); | |
232 | 496 | |
233 | 497 | if (abscisse.getType() == Abscisse::Abscisse_Type::FREQUENCY) |
234 | - xValues = DFT.getFrequences(); | |
498 | + { | |
499 | + xValues = DFT.getFreq(ph, 1.0 / 800); // DFT.getFrequences(); | |
500 | + for (int u = 0; u < xValues.size(); u++) | |
501 | + { | |
502 | + LOG4CXX_DEBUG(gLogger, " indice " << u << " freq " << xValues[u]); | |
503 | + } | |
504 | + } | |
235 | 505 | else |
236 | 506 | xValues = DFT.getPeriodes(); |
507 | + // xValues = x_; | |
237 | 508 | } |
238 | 509 | |
239 | 510 | if (ordonneeScale == Axis::Scale::LOGARITHMIC) |
240 | - { | |
241 | 511 | std::for_each(yValues.begin(), yValues.end(), [&](double &i) |
242 | 512 | { return log10(i); }); |
243 | - } | |
244 | 513 | |
245 | 514 | if (abscisseScale == Axis::Scale::LOGARITHMIC) |
246 | - { | |
247 | 515 | std::for_each(xValues.begin(), xValues.end(), [&](double &i) |
248 | 516 | { return log10(i); }); |
249 | - } | |
250 | 517 | |
251 | 518 | PlotFunction::xValuesMap[id] = xValues; |
252 | 519 | PlotFunction::yValuesMap[id] = yValues; |
... | ... | @@ -302,7 +569,7 @@ namespace plot |
302 | 569 | |
303 | 570 | void PlotFunction::preparePlotArea(double startTime, double stopTime, int intervalIndex) |
304 | 571 | { |
305 | - PlotFunction::configureSeriesAxis(); | |
572 | + PlotFunction::applyFunction(); | |
306 | 573 | |
307 | 574 | if (abscisse.getType() == Abscisse::TIME) |
308 | 575 | { |
... | ... | @@ -310,32 +577,9 @@ namespace plot |
310 | 577 | getTimeAxisDecorator()->configure(this, dynamic_cast<TimeAxis *>(xAxis.get()), startTime, stopTime, _pParameterValues); |
311 | 578 | _pls->timefmt(getTimeAxisDecorator()->getPlFormat().c_str()); |
312 | 579 | } |
313 | - PanelPlotOutput::preparePlotArea(startTime, stopTime, intervalIndex); | |
314 | - } | |
315 | - | |
316 | - void PlotFunction::createParameters(std::list<std::string> &usedParametersId_) | |
317 | - { | |
318 | - | |
319 | - for (ParameterAxesList::iterator it = _parameterAxesList.begin(); | |
320 | - it != _parameterAxesList.end(); ++it) | |
321 | - { | |
322 | - AMDA::Parameters::ParameterSPtr originalParam = | |
323 | - _parameterManager.getParameter(it->_originalParamId); | |
580 | + PanelPlotOutput::configureParamsLegend(startTime, stopTime, intervalIndex); | |
324 | 581 | |
325 | - // For each series | |
326 | - std::vector<SeriesProperties>::iterator ity; | |
327 | - for (ity = it->getYSeriePropertiesList().begin(); ity != it->getYSeriePropertiesList().end(); | |
328 | - ++ity) | |
329 | - { | |
330 | - // Add parameter to parameters list | |
331 | - if (std::find(usedParametersId_.begin(), usedParametersId_.end(), | |
332 | - originalParam->getId()) == usedParametersId_.end()) | |
333 | - usedParametersId_.push_back(originalParam->getId()); | |
334 | - | |
335 | - // link this paramter to the serie | |
336 | - ity->setParamId(originalParam->getId()); | |
337 | - } | |
338 | - } | |
582 | + PanelPlotOutput::preparePlotArea(startTime, stopTime, intervalIndex); | |
339 | 583 | } |
340 | 584 | |
341 | 585 | /** |
... | ... | @@ -349,23 +593,6 @@ namespace plot |
349 | 593 | _panel->draw(_pls); |
350 | 594 | fillBackground(_pls); |
351 | 595 | |
352 | - bool noData = true; | |
353 | - | |
354 | - if (_parameterAxesList.empty()) | |
355 | - { | |
356 | - noData = false; // Do not draw No Data if the panel is empty | |
357 | - _panel->drawEmptyPanel(_pls); | |
358 | - } | |
359 | - | |
360 | - // Set pointer to ParameterData list | |
361 | - if (_pParameterValues == NULL) | |
362 | - { | |
363 | - std::stringstream lError; | |
364 | - lError << "PanelPlotOutput::draw - Pointer to parameterValues is not set"; | |
365 | - BOOST_THROW_EXCEPTION( | |
366 | - PanelPlotOutputException() << AMDA::ex_msg(lError.str())); | |
367 | - } | |
368 | - | |
369 | 596 | // Compute nb series to draw by y axis |
370 | 597 | std::map<std::string, int> nbSeriesByYAxisMap = getNbSeriesByYAxis(); |
371 | 598 | SeriesProperties lSeries; |
... | ... | @@ -386,10 +613,6 @@ namespace plot |
386 | 613 | drawSeries(startTime, stopTime, intervalIndex, parameter._originalParamId, |
387 | 614 | lSeries, lIndex, parameter, moreThanOneSerieForYAxis); |
388 | 615 | ParameterData &data = (*_pParameterValues)[lSeries.getParamId()]; |
389 | - if (noData) | |
390 | - { | |
391 | - noData = data.noData(lIndex); | |
392 | - } | |
393 | 616 | } |
394 | 617 | } |
395 | 618 | } |
... | ... | @@ -400,6 +623,7 @@ namespace plot |
400 | 623 | PlotFunction::drawStartDate(_timeFormat, startTime, stopTime); |
401 | 624 | } |
402 | 625 | |
403 | - return noData; | |
626 | + PlotFunction::drawInstantPlot(); | |
627 | + return true; | |
404 | 628 | } |
405 | 629 | } | ... | ... |
src/ParamOutputImpl/Plot/InstantPlot/PlotFunction.hh
... | ... | @@ -148,8 +148,11 @@ namespace plot |
148 | 148 | virtual bool draw(double startTime, double stopTime, int intervalIndex, |
149 | 149 | bool isFirstInterval, bool isLastInterval); |
150 | 150 | |
151 | + virtual void writeContext(ContextFileWriter &writer, AMDA::Parameters::TimeIntervalList::iterator currentTimeInterval); | |
152 | + | |
151 | 153 | private: |
152 | - void configureSeriesAxis(); | |
154 | + void drawInstantPlot(); | |
155 | + void applyFunction(); | |
153 | 156 | void configureAxisLegend(); |
154 | 157 | /** |
155 | 158 | * @brief Afficher sur le plot the starting date |
... | ... | @@ -163,7 +166,7 @@ namespace plot |
163 | 166 | * @brief Créer un axe Y pour accueillir les valeurs calculées de l'axe Y |
164 | 167 | * |
165 | 168 | */ |
166 | - void createYAxis(); | |
169 | + void createYAxis(std::string paramId, bool isSpectro); | |
167 | 170 | /** |
168 | 171 | * @brief Créer un axe X pour accueillir les valeurs calculées de l'axe X |
169 | 172 | * |
... | ... | @@ -184,7 +187,7 @@ namespace plot |
184 | 187 | * @param id id pseudo param |
185 | 188 | * @param param_id id du paramètre |
186 | 189 | */ |
187 | - void compute(AMDA::Common::ParameterIndexComponent pParamIndex, plot::ParameterData data, std::string id, std::string param_id); | |
190 | + void compute(AMDA::Common::ParameterIndexComponent pParamIndex, plot::ParameterData &data, SeriesProperties *pSerie, SpectroProperties *pSpectro, std::string paramOriginID); | |
188 | 191 | |
189 | 192 | /** |
190 | 193 | * @brief Une map pour stocker les valeurs calculées de l'axe X associés aux pseudo paramètres crées localement | ... | ... |
src/ParamOutputImpl/Plot/InstantPlot/PlotFunctionNode.cc
... | ... | @@ -67,8 +67,8 @@ namespace plot |
67 | 67 | plot->setFunction(PlotFunction::Function::AVG); |
68 | 68 | else if (strcmp(valueString, PlotFunctuion_Type_FFT) == 0) |
69 | 69 | plot->setFunction(PlotFunction::Function::FFT); |
70 | - else | |
71 | - plot->setFunction(PlotFunction::Function::NONE); | |
70 | + else if (strcmp(valueString, PlotFunctuion_Type_SUM) == 0) | |
71 | + plot->setFunction(PlotFunction::Function::SUM); | |
72 | 72 | xmlFree(value); |
73 | 73 | } |
74 | 74 | ... | ... |
src/ParamOutputImpl/Plot/PanelPlotOutput.cc
src/ParamOutputImpl/Plot/PanelPlotOutput.hh
... | ... | @@ -8,592 +8,600 @@ |
8 | 8 | #ifndef PANELPLOTOUTPUT_HH_ |
9 | 9 | #define PANELPLOTOUTPUT_HH_ |
10 | 10 | |
11 | -#include "ParamOutput.hh" | |
11 | +#include "ContextFileWriter.hh" | |
12 | +#include "Layout.hh" | |
12 | 13 | #include "Panel.hh" |
14 | +#include "PanelPlotOutputException.hh" | |
15 | +#include "ParamOutput.hh" | |
13 | 16 | #include "ParameterAxes.hh" |
14 | -#include <vector> | |
15 | -#include <tuple> | |
16 | 17 | #include "ParameterData.hh" |
18 | +#include "PlotLogger.hh" | |
17 | 19 | #include <AMDA_exception.hh> |
18 | 20 | #include <cxxabi.h> |
19 | -#include "PlotLogger.hh" | |
20 | -#include "PanelPlotOutputException.hh" | |
21 | -#include "Layout.hh" | |
22 | -#include "ContextFileWriter.hh" | |
21 | +#include <tuple> | |
22 | +#include <vector> | |
23 | 23 | |
24 | 24 | #include <cfloat> |
25 | 25 | |
26 | -namespace plot { | |
27 | - | |
28 | -// 0 => xmin | |
29 | -// 1 => xmax | |
30 | -// 2 => ymin | |
31 | -// 3 => ymax | |
32 | -typedef std::tuple<double, double, double, double> PlWindow; | |
33 | -// 0 => x major tick space | |
34 | -// 1 => x minor tick number | |
35 | -// 2 => y major tick space | |
36 | -// 3 => y minor tick number | |
37 | -typedef std::tuple<double, double, double, double> TickConf; | |
38 | - | |
39 | -/** | |
40 | - * Margin. | |
41 | - */ | |
42 | -struct Margin { | |
43 | - double _left; | |
44 | - double _right; | |
45 | - double _top; | |
46 | - double _bottom; | |
47 | -}; | |
48 | - | |
49 | -class PanelPlotOutput { | |
50 | -public: | |
51 | - static const float DEFAULT_TICK_LENGTH_FACTOR; | |
52 | - | |
53 | - /** | |
54 | - * Width character proportion is approximatively 0.83 times smaller than height. | |
55 | - */ | |
56 | - static const float CHAR_RATIO; | |
57 | - | |
58 | - /** | |
59 | - * This two next attribute tell from which tick length plplot is insufficient to calculate space between tickmarks and ticks. | |
60 | - * Space between the two is static and can't be modified by user request. | |
61 | - * So when limit is reached we must bypass problem by setting two different viewport to let sufficient space between tickmarks and ticks. | |
62 | - */ | |
63 | - static const float VERTICAL_TICK_LENGTH_LIMIT; | |
64 | - static const float HORIZONTAL_TICK_LENGTH_LIMIT; | |
65 | - static const float YAXISMARGIN; | |
26 | +namespace plot | |
27 | +{ | |
66 | 28 | |
67 | - PanelPlotOutput(AMDA::Parameters::ParameterManager& manager, | |
68 | - boost::shared_ptr<Panel> panel, bool isStandalone = true); | |
69 | - virtual ~PanelPlotOutput(); | |
29 | + // 0 => xmin | |
30 | + // 1 => xmax | |
31 | + // 2 => ymin | |
32 | + // 3 => ymax | |
33 | + typedef std::tuple<double, double, double, double> PlWindow; | |
34 | + // 0 => x major tick space | |
35 | + // 1 => x minor tick number | |
36 | + // 2 => y major tick space | |
37 | + // 3 => y minor tick number | |
38 | + typedef std::tuple<double, double, double, double> TickConf; | |
70 | 39 | |
71 | 40 | /** |
72 | - * type name. This name is used to identify nodes in xml config | |
73 | - * and xml request. | |
74 | - * @return | |
41 | + * Margin. | |
75 | 42 | */ |
76 | - virtual const std::string typeName() = 0; | |
77 | - | |
78 | - /** | |
79 | - * @brief Compute the initial plot area for the panel | |
80 | - */ | |
81 | - virtual void preparePlotArea (double startTime, double stopTime, int intervalIndex); | |
82 | - | |
83 | - /** | |
84 | - * @brief Retrieve plot area bounds for the panel | |
85 | - */ | |
86 | - virtual void getPlotAreaBounds (Bounds &plotAreaBounds); | |
87 | - | |
88 | - /** | |
89 | - * @brief Force the plot area horizontal position and width | |
90 | - */ | |
91 | - virtual void forcePlotAreaPosAndWidth(double plotAreaX, double plotAreaWidth); | |
92 | - | |
93 | - /** | |
94 | - * @brief Retrieve left axis tickMark width | |
95 | - */ | |
96 | - virtual int getLeftAxisTickMarkWidth (void); | |
97 | - | |
98 | - /** | |
99 | - * @brief Force left axis tickmark width for the panel | |
100 | - */ | |
101 | - virtual void forceLeftAxisTickMarkWidth(int leftAxisTickMarkWidth); | |
102 | - | |
103 | - /** | |
104 | - * @brief draw the plot for the current time interval | |
105 | - */ | |
106 | - virtual bool draw(double startTime, double stopTime, int intervalIndex, bool isFirstInterval, bool isLastInterval); | |
107 | - | |
108 | - /** | |
109 | - * @brief Write plot context | |
110 | - */ | |
111 | - void writeContext(ContextFileWriter &writer, AMDA::Parameters::TimeIntervalList::iterator currentTimeInterval); | |
112 | - | |
113 | - /* | |
114 | - * @brief Set a pointer to the time intervals list | |
115 | - */ | |
116 | - void setTimeIntervalListPtr(AMDA::Parameters::TimeIntervalList *timeIntervalListPtr); | |
117 | - | |
118 | - /** | |
119 | - * Sets PLplot stream to draw panel and plot | |
120 | - */ | |
121 | - virtual void setPlStream(std::shared_ptr<plstream>& pls); | |
122 | - | |
123 | - /** | |
124 | - * Adds a parameter | |
125 | - */ | |
126 | - virtual void addParam(const std::string& name) { | |
127 | - ParameterAxes newParameter(name); | |
128 | - _parameterAxesList.push_back(newParameter); | |
129 | - } | |
130 | - | |
131 | - virtual ParameterAxes& getParameter(const std::string& name) { | |
132 | - for (ParameterAxes& param : _parameterAxesList) { | |
133 | - if (param._originalParamId == name) { | |
134 | - return param; | |
135 | - } | |
136 | - } | |
137 | - ParameterAxes newParameter(name); | |
138 | - _parameterAxesList.push_back(newParameter); | |
139 | - return _parameterAxesList.back(); | |
140 | - } | |
141 | - | |
142 | - /* | |
143 | - * Create a sampled parameter from an original parameter and a sampling value | |
144 | - */ | |
145 | - AMDA::Parameters::ParameterSPtr createSampledParameter(AMDA::Parameters::ParameterSPtr& originalParam, float samplingValue); | |
146 | - | |
147 | - /* | |
148 | - * Create a sampled parameter from an original parameter and a reference parameter for time definition | |
149 | - */ | |
150 | - AMDA::Parameters::ParameterSPtr createSampledParameterUnderReferenceParameter(AMDA::Parameters::ParameterSPtr& originalParam, | |
151 | - AMDA::Parameters::ParameterSPtr& refParam); | |
152 | - | |
153 | - /** | |
154 | - * Create parameters needed for this plot | |
155 | - * By default, the creation method create parameters for a time serie. | |
156 | - * Override it for other plot type | |
157 | - */ | |
158 | - virtual void createParameters(std::list<std::string>& usedParametersId_); | |
159 | - | |
160 | - /** | |
161 | - * Get related ParameterAxes for a given color serie id | |
162 | - */ | |
163 | - ParameterAxes* getParameterAxesByColorSerieId(int colorSerieId); | |
164 | - | |
165 | - /** | |
166 | - * Get related ParameterAxes for a given x serie id | |
167 | - */ | |
168 | - ParameterAxes* getParameterAxesByXSerieId(int xSerieId); | |
169 | - | |
170 | - /** | |
171 | - * Gets sampling value from resolution (point-per-plot) according to | |
172 | - * the plot time interval and the base parameter sampling value. | |
173 | - */ | |
174 | - virtual double getCorrectedSamplingValue(int maxResolution, double samplingValue); | |
175 | - | |
176 | - /** | |
177 | - * @brief Get the list of indexes used for a parameter | |
178 | - */ | |
179 | - virtual std::vector<AMDA::Common::ParameterIndexComponent> getParamUsedIndexes(std::string paramId, int dim1Size, int dim2Size = -1); | |
180 | - | |
181 | - const Margin getMargin(){ | |
182 | - Bounds panelBounds(_panel->getBoundsInPlPage()); | |
183 | - | |
184 | - Margin m; | |
185 | - m._left = _plotAreaBounds._x - panelBounds._x; | |
186 | - m._right = (panelBounds._x + panelBounds._width) - (_plotAreaBounds._x + _plotAreaBounds._width); | |
187 | - m._top = (panelBounds._y + panelBounds._height) - (_plotAreaBounds._y + _plotAreaBounds._height); | |
188 | - m._bottom = _plotAreaBounds._y - panelBounds._y; | |
189 | - return m; | |
190 | - } | |
191 | - | |
192 | - /** | |
193 | - * @brief reset plot | |
194 | - */ | |
195 | - virtual void resetPlot() { | |
196 | - if (_panel != nullptr) | |
197 | - _panel->resetPlot(); | |
198 | - _automaticSerieColorCursor = 0; | |
199 | - _nbSeriesByYAxisMap.clear(); | |
200 | - _pls.reset(); | |
201 | - } | |
202 | - | |
203 | - /* | |
204 | - * @brief Set pointer to params values | |
205 | - */ | |
206 | - void setParameterValues(std::map<std::string, ParameterData> *pParameterValues); | |
207 | - | |
208 | - /* | |
209 | - * @brief Get computed values (in relation with the y axis definition) for a y serie, an index of the serie and a time interval | |
210 | - * Do not forget to delete (*computedValues) !! | |
211 | - * Do not delete (*timeValues), the buffer is not copied !! | |
212 | - */ | |
213 | - bool getComputedValuesFromSerieAndInterval(double startDate, double stopDate, SeriesProperties &rSeriesProperties, | |
214 | - AMDA::Common::ParameterIndexComponent index, double** computedValues, double** timeValues, int& nbValues); | |
215 | - | |
216 | - /* | |
217 | - * @brief Get computed values (in relation with the color axis definition) for a color serie and a time interval | |
218 | - * Do not forget to delete computedValues !! | |
219 | - * Don't delete timeValues !! | |
220 | - */ | |
221 | - bool getColoredComputedValuesFromSerieAndInterval(double startDate, double stopDate, SeriesProperties &rSeriesProperties, | |
222 | - double** computedValues, double** timeValues, int& nbValues); | |
223 | - | |
224 | - /* | |
225 | - * @brief Get computed values (in relation with the y axis definition) for a y serie and a time interval | |
226 | - * Do not forget to delete computedValues !! | |
227 | - * Don't delete timeValues !! | |
228 | - */ | |
229 | - bool getErrorComputedValuesFromSerieAndInterval(double startDate, double stopDate, SeriesProperties &rSeriesProperties, | |
230 | - double** minComputedValues, double** minTimeValues, int& nbMinValues, | |
231 | - double** maxComputedValues, double** maxTimeValues, int& nbMaxValues); | |
232 | - | |
233 | - /** | |
234 | - *@brief Defines the layout constraint to be used for the panel when used within a layout | |
235 | - */ | |
236 | - virtual PanelConstraint getLayoutConstraint (void) { | |
237 | - return PanelConstraint::MaxWidth; | |
238 | - } | |
239 | - | |
240 | - /** | |
241 | - * @brief Get nb series to draw by y axis | |
242 | - */ | |
243 | - std::map<std::string,int>& getNbSeriesByYAxis(); | |
244 | - | |
245 | - /* | |
246 | - * @brief Return the color to draw the line of a serie | |
247 | - */ | |
248 | - Color getSerieLineColor(SeriesProperties &rSeriesProperties, bool moreThanOneSerieForAxis); | |
249 | - | |
250 | - /** | |
251 | - * @brief Plot container | |
252 | - */ | |
253 | - boost::shared_ptr<Panel> _panel; | |
254 | - | |
255 | - /** | |
256 | - * @brief Parameters and series info | |
257 | - */ | |
258 | - ParameterAxesList _parameterAxesList; | |
259 | - | |
260 | - /* | |
261 | - * @brief Type used to define a matrix grid | |
262 | - */ | |
263 | - struct GridPart | |
43 | + struct Margin | |
264 | 44 | { |
265 | - double x[2]; | |
266 | - double y[2]; | |
267 | - double value; | |
268 | - double isColorIndex; | |
45 | + double _left; | |
46 | + double _right; | |
47 | + double _top; | |
48 | + double _bottom; | |
269 | 49 | }; |
270 | 50 | |
271 | - typedef std::vector<GridPart> MatrixGrid; | |
272 | - | |
273 | - // datastore for sauvaud plot | |
274 | - struct SauvaudPart | |
51 | + class PanelPlotOutput | |
275 | 52 | { |
276 | - double x[2]; | |
277 | - double y[2]; | |
278 | - std::vector<double> value; | |
279 | - double isColorIndex; | |
280 | - }; | |
281 | - | |
282 | - typedef std::vector<SauvaudPart> SauvaudGrid; | |
283 | - | |
284 | - /* | |
285 | - * @brief Draw a matrix | |
286 | - */ | |
287 | - void drawMatrix(MatrixGrid& matrixGrid, double minDataVal, double maxDataVal, | |
288 | - Color minValColor, Color maxValColor, int colorMapIndex, bool useLog0AsMin = false); | |
289 | - | |
290 | - void draw2DMatrix(SauvaudGrid& sauvaudGrid, double minDataVal, double maxDataVal, | |
291 | - Color minValColor, Color maxValColor, int colorMapIndex, bool useLog0AsMin = false); | |
292 | - | |
293 | - /** | |
294 | - * @brief Reset cursor used to attribute automatically a color to a serie | |
295 | - */ | |
296 | - void resetAutomaticSerieColorCursor() { | |
297 | - _automaticSerieColorCursor = 0; | |
298 | - } | |
299 | - | |
300 | - /** | |
301 | - * Draw a rectangle | |
302 | - */ | |
303 | - void drawRectangle(double xmin, double xmax, double ymin, double ymax, Color& pColor, double alpha = 1.); | |
304 | - | |
305 | - bool isStandalone() { | |
306 | - return _isStandalone; | |
307 | - } | |
308 | - | |
309 | - AMDA::Parameters::ParameterManager& _parameterManager; | |
310 | - | |
311 | - std::map<std::string, ParameterData> *_pParameterValues; | |
312 | - | |
313 | -protected: | |
314 | - | |
315 | - AMDA::Parameters::TimeIntervalList* _timeIntervalListPtr; | |
316 | - | |
317 | - /** | |
318 | - * @brief Compute plot area. | |
319 | - * @note If ratio need to be kept, ratio will be kept between width and height. | |
320 | - * @param bounds_ plot area bounds. It is updated by this method. | |
321 | - */ | |
322 | - virtual void calculatePlotArea(const Bounds& panelBounds_, Bounds& bounds_); | |
323 | - | |
324 | - /** | |
325 | - *@brief computes Panel Plot XY ratio | |
326 | - */ | |
327 | - void computePanelPlotXYRatio(void); | |
328 | - | |
329 | - /** | |
330 | - * @brief Get colored value associated to a data value. Return false if the value is filtered. | |
331 | - */ | |
332 | - bool getColoredValue(double value, double filterMin, double filterMax, bool useLog0AsMin, PLFLT &col); | |
333 | - | |
334 | - /** | |
335 | - *@brief Draw fill area between parameter and constant or between parameters | |
336 | - */ | |
337 | - virtual void drawFills(double startDate, double stopDate); | |
338 | - | |
339 | - /** | |
340 | - * Draw list of symbols | |
341 | - */ | |
342 | - void drawSymbols(SymbolType pType, int pSize, double pFactor, Color pColor, | |
343 | - int pNbData, double* pXData, double* pYData, | |
344 | - double* pZData = NULL, double filterZMin = -DBL_MAX, double filterZMax = DBL_MAX); | |
345 | - | |
346 | - /** | |
347 | - * Draw list of lines | |
348 | - */ | |
349 | - void drawLines(LineType pType, LineStyle pStyle, int pWidth, Color& pColor, | |
350 | - int pNbData, double* pXData, double* pYData, | |
351 | - double* pZData = NULL, double filterZMin = -DBL_MAX, double filterZMax = DBL_MAX); | |
352 | - | |
353 | - /** | |
354 | - * Draw errors segments | |
355 | - */ | |
356 | - void drawYErrors (LineType pType, LineStyle pStyle, int pWidth, Color& pColor, | |
357 | - int pNbData, double* pXData, double* pYMinData, double* pYMaxData); | |
358 | - | |
359 | - /** | |
360 | - *@brief Draw the serie of a parameter component on plot. | |
361 | - */ | |
362 | - virtual void drawSeries(double startDate, double stopDate, int intervalIndex, std::string pParamId, SeriesProperties& pSeries, | |
363 | - AMDA::Common::ParameterIndexComponent pParamIndex, ParameterAxes& param, bool moreThanOneSerieForAxis); | |
364 | - | |
365 | - /** | |
366 | - *@brief Draw the spectro of a parameter on plot. | |
367 | - */ | |
368 | - virtual void drawSpectro(double startDate, double stopDate, std::string pParamId, | |
369 | - SpectroProperties& pSpectro); | |
370 | - | |
371 | - /** | |
372 | - *@brief Draw sauvaud plot of a parameter on plot. | |
373 | - */ | |
374 | - virtual void drawSauvaud(double startDate, double stopDate, std::string pParamId, | |
375 | - SauvaudProperties& pSauvaud, int subIndex, int subsNumber, std::string opositeLegend); | |
376 | - | |
377 | - virtual void drawIntervals(double startDate, double stopDate, std::string pParamId, | |
378 | - IntervalsProperties& pIntervals); | |
379 | - | |
380 | - /* | |
381 | - * @brief Draw interval | |
382 | - */ | |
383 | - virtual void drawSerieInterval(SeriesProperties& pSeries, | |
384 | - double* xValues, double* yValues, double* timeValues, | |
385 | - int nbValues, int intervalIndex); | |
386 | - | |
387 | - /** | |
388 | - * Draw an horizontal axis. | |
389 | - * Subclasses may override it to take into account decorator attached to that axis (for instance). | |
390 | - * @param pXAxis axis to draw. | |
391 | - * @param pPlWindow real word ranges. | |
392 | - * @param pPlotAreaSize plot ranges. | |
393 | - * @param pTickConf ticks configuration. | |
394 | - */ | |
395 | - virtual void drawXAxis(boost::shared_ptr<Axis> pXAxis, PlWindow& pPlWindow, Bounds& pPlotAreaSize, TickConf& pTickConf); | |
396 | - /** | |
397 | - * Draw a vertical axis. | |
398 | - * Subclasses may override it to take into account decorator attached to that axis (for instance). | |
399 | - * @param pXAxis axis to draw. | |
400 | - * @param pPlWindow real word ranges. | |
401 | - * @param pPlotAreaSize plot ranges. | |
402 | - * @param pTickConf ticks configuration. | |
403 | - */ | |
404 | - virtual void drawYAxis(boost::shared_ptr<Axis> pXAxis, PlWindow& pPlWindow, Bounds& pPlotAreaSize, TickConf& pTickConf); | |
405 | - /** | |
406 | - * @brief Draw legend for each axis. | |
407 | - * @param pAxis axis to draw. | |
408 | - * @param pPlWindow real word ranges. | |
409 | - * @param pPlotAreaSize plot ranges. | |
410 | - */ | |
411 | - virtual void drawLegends(boost::shared_ptr<Axis>& pAxis, PlWindow& pPlWindow, Bounds& pPlotAreaSize); | |
412 | - | |
413 | - /** | |
414 | - * @brief Draw parameters legend. | |
415 | - */ | |
416 | - virtual void drawParamsLegend(void); | |
417 | - | |
418 | - /** | |
419 | - * @brief Draw text legends. | |
420 | - */ | |
421 | - virtual void drawTextLegends(void); | |
422 | - | |
423 | - /** | |
424 | - * Convert an X axis string value to a double X value | |
425 | - * Subclasses may override it to take into account specific value meaning. | |
426 | - * @param value string value to convert. | |
427 | - */ | |
428 | - virtual double convertXAxisValue(const std::string &value); | |
429 | - | |
430 | - /** | |
431 | - * Convert an Y axis string value to a double Y value | |
432 | - * Subclasses may override it to take into account specific value meaning. | |
433 | - * @param value string value to convert. | |
434 | - */ | |
435 | - virtual double convertYAxisValue(const std::string &value); | |
436 | - | |
437 | - /** | |
438 | - * Draw X constant lines linked to an axis. | |
439 | - * Subclasses may override it to take into account decorator attached (for instance). | |
440 | - * @param pXAxis axis to draw. | |
441 | - * @param pPlWindow real word ranges. | |
442 | - */ | |
443 | - virtual void drawXConstantLines(boost::shared_ptr<Axis> pAxis, PlWindow& pPlWindow); | |
444 | - /** | |
445 | - * Draw X constant lines linked to an axis. | |
446 | - * Subclasses may override it to take into account decorator attached (for instance). | |
447 | - * @param pXAxis axis to draw. | |
448 | - * @param pPlWindow real word ranges. | |
449 | - */ | |
450 | - virtual void drawYConstantLines(boost::shared_ptr<Axis> pAxis, PlWindow& pPlWindow); | |
451 | - /** | |
452 | - * Draw textPlots for a panel. | |
453 | - * Subclasses may override it for specific drawings. | |
454 | - * @param pPlWindow real word ranges. | |
455 | - */ | |
456 | - virtual void drawTextPlots(boost::shared_ptr<Axis> pXAxis, boost::shared_ptr<Axis> pYAxis, PlWindow& pPlWindow, const TextPlots &textPlots); | |
457 | - | |
458 | - | |
459 | - /** | |
460 | - * Draw curvePlot for a panel. | |
461 | - * Subclasses may override it for specific drawings. | |
462 | - * @param curvePlot curve properties. | |
463 | - */ | |
464 | - virtual void drawCurvePlot(CurvePlot &curvePlot); | |
465 | - | |
466 | - /** | |
467 | - * @brief Identify if other side of the plot area need to be drawn or not. | |
468 | - * @note A plot area side need to be drawn when there is no axis associated to it. | |
469 | - */ | |
470 | - virtual std::string drawOppositeSide(boost::shared_ptr<Axis> pAxis); | |
471 | - | |
472 | - /** | |
473 | - *@brief Draw additional objects on plot. | |
474 | - */ | |
475 | - virtual void drawAdditionalObjects (); | |
476 | - | |
477 | - /** | |
478 | - * Draw a z axis | |
479 | - */ | |
480 | - virtual void drawZAxis(boost::shared_ptr<Axis> pZAxis, PlWindow& pPlWindow, Bounds& pPlotAreaSize, TickConf& pTickConf); | |
481 | - | |
482 | - | |
483 | - /** | |
484 | - * Get X Axis range for a serie | |
485 | - */ | |
486 | - Range getXAxisRange (SeriesProperties& pSeries, boost::shared_ptr<Axis> pAxis); | |
487 | - | |
488 | - /** | |
489 | - * Get Y Axis range for a serie | |
490 | - */ | |
491 | - Range getYAxisRange (SeriesProperties& pSeries, boost::shared_ptr<Axis> pAxis); | |
492 | - | |
493 | - /** | |
494 | - * Get Z Axis range for a serie | |
495 | - */ | |
496 | - Range getZAxisRange (SeriesProperties& pSeries, boost::shared_ptr<Axis> pAxis); | |
497 | - | |
498 | - /* | |
499 | - * @brief Return the color to draw the symbols of a serie | |
500 | - */ | |
501 | - Color getSerieSymbolColor(SeriesProperties &rSeriesProperties, Color &pLineColor); | |
502 | - | |
503 | - /** | |
504 | - * @brief Configure params legend for a plot. | |
505 | - */ | |
506 | - virtual void configureParamsLegend(double startTime, double stopTime, int intervalIndex); | |
507 | - | |
508 | - /** | |
509 | - * @brief Add a serie to the param legend | |
510 | - */ | |
511 | - void addSerieToParamsLegend(SeriesProperties& lSeriesProperties, | |
512 | - AMDA::Common::ParameterIndexComponent& index, std::string originalParamId, | |
513 | - Color& lineColor, Color& symbolColor, | |
514 | - double startTime, double stopTime, int intervalIndex); | |
515 | - | |
516 | - /* | |
517 | - * @brief Return the associated params legend to a serie | |
518 | - */ | |
519 | - virtual std::string getSerieParamsLegendString(SeriesProperties &rSeriesProperties, | |
520 | - AMDA::Common::ParameterIndexComponent& index, std::string originalParamId); | |
53 | + public: | |
54 | + static const float DEFAULT_TICK_LENGTH_FACTOR; | |
55 | + | |
56 | + /** | |
57 | + * Width character proportion is approximatively 0.83 times smaller than height. | |
58 | + */ | |
59 | + static const float CHAR_RATIO; | |
60 | + | |
61 | + /** | |
62 | + * This two next attribute tell from which tick length plplot is insufficient to calculate space between tickmarks and ticks. | |
63 | + * Space between the two is static and can't be modified by user request. | |
64 | + * So when limit is reached we must bypass problem by setting two different viewport to let sufficient space between tickmarks and ticks. | |
65 | + */ | |
66 | + static const float VERTICAL_TICK_LENGTH_LIMIT; | |
67 | + static const float HORIZONTAL_TICK_LENGTH_LIMIT; | |
68 | + static const float YAXISMARGIN; | |
69 | + | |
70 | + PanelPlotOutput(AMDA::Parameters::ParameterManager &manager, | |
71 | + boost::shared_ptr<Panel> panel, bool isStandalone = true); | |
72 | + virtual ~PanelPlotOutput(); | |
73 | + | |
74 | + /** | |
75 | + * type name. This name is used to identify nodes in xml config | |
76 | + * and xml request. | |
77 | + * @return | |
78 | + */ | |
79 | + virtual const std::string typeName() = 0; | |
80 | + | |
81 | + /** | |
82 | + * @brief Compute the initial plot area for the panel | |
83 | + */ | |
84 | + virtual void preparePlotArea(double startTime, double stopTime, int intervalIndex); | |
85 | + | |
86 | + /** | |
87 | + * @brief Retrieve plot area bounds for the panel | |
88 | + */ | |
89 | + virtual void getPlotAreaBounds(Bounds &plotAreaBounds); | |
90 | + | |
91 | + /** | |
92 | + * @brief Force the plot area horizontal position and width | |
93 | + */ | |
94 | + virtual void forcePlotAreaPosAndWidth(double plotAreaX, double plotAreaWidth); | |
95 | + | |
96 | + /** | |
97 | + * @brief Retrieve left axis tickMark width | |
98 | + */ | |
99 | + virtual int getLeftAxisTickMarkWidth(void); | |
100 | + | |
101 | + /** | |
102 | + * @brief Force left axis tickmark width for the panel | |
103 | + */ | |
104 | + virtual void forceLeftAxisTickMarkWidth(int leftAxisTickMarkWidth); | |
105 | + | |
106 | + /** | |
107 | + * @brief draw the plot for the current time interval | |
108 | + */ | |
109 | + virtual bool draw(double startTime, double stopTime, int intervalIndex, bool isFirstInterval, bool isLastInterval); | |
110 | + | |
111 | + /** | |
112 | + * @brief Write plot context | |
113 | + */ | |
114 | + virtual void writeContext(ContextFileWriter &writer, AMDA::Parameters::TimeIntervalList::iterator currentTimeInterval); | |
115 | + | |
116 | + /* | |
117 | + * @brief Set a pointer to the time intervals list | |
118 | + */ | |
119 | + void setTimeIntervalListPtr(AMDA::Parameters::TimeIntervalList *timeIntervalListPtr); | |
120 | + | |
121 | + /** | |
122 | + * Sets PLplot stream to draw panel and plot | |
123 | + */ | |
124 | + virtual void setPlStream(std::shared_ptr<plstream> &pls); | |
125 | + | |
126 | + /** | |
127 | + * Adds a parameter | |
128 | + */ | |
129 | + virtual void addParam(const std::string &name) | |
130 | + { | |
131 | + ParameterAxes newParameter(name); | |
132 | + _parameterAxesList.push_back(newParameter); | |
133 | + } | |
521 | 134 | |
522 | - /** | |
523 | - * @brief plplot stream | |
524 | - */ | |
525 | - std::shared_ptr<plstream> _pls; | |
135 | + virtual ParameterAxes &getParameter(const std::string &name) | |
136 | + { | |
137 | + for (ParameterAxes ¶m : _parameterAxesList) | |
138 | + { | |
139 | + if (param._originalParamId == name) | |
140 | + { | |
141 | + return param; | |
142 | + } | |
143 | + } | |
144 | + ParameterAxes newParameter(name); | |
145 | + _parameterAxesList.push_back(newParameter); | |
146 | + return _parameterAxesList.back(); | |
147 | + } | |
526 | 148 | |
527 | - /* | |
528 | - * Dumps properties for test. | |
529 | - */ | |
530 | - virtual void dump(std::ostream& out_); | |
149 | + /* | |
150 | + * Create a sampled parameter from an original parameter and a sampling value | |
151 | + */ | |
152 | + AMDA::Parameters::ParameterSPtr createSampledParameter(AMDA::Parameters::ParameterSPtr &originalParam, float samplingValue); | |
153 | + | |
154 | + /* | |
155 | + * Create a sampled parameter from an original parameter and a reference parameter for time definition | |
156 | + */ | |
157 | + AMDA::Parameters::ParameterSPtr createSampledParameterUnderReferenceParameter(AMDA::Parameters::ParameterSPtr &originalParam, | |
158 | + AMDA::Parameters::ParameterSPtr &refParam); | |
159 | + | |
160 | + /** | |
161 | + * Create parameters needed for this plot | |
162 | + * By default, the creation method create parameters for a time serie. | |
163 | + * Override it for other plot type | |
164 | + */ | |
165 | + virtual void createParameters(std::list<std::string> &usedParametersId_); | |
166 | + | |
167 | + /** | |
168 | + * Get related ParameterAxes for a given color serie id | |
169 | + */ | |
170 | + ParameterAxes *getParameterAxesByColorSerieId(int colorSerieId); | |
171 | + | |
172 | + /** | |
173 | + * Get related ParameterAxes for a given x serie id | |
174 | + */ | |
175 | + ParameterAxes *getParameterAxesByXSerieId(int xSerieId); | |
176 | + | |
177 | + /** | |
178 | + * Gets sampling value from resolution (point-per-plot) according to | |
179 | + * the plot time interval and the base parameter sampling value. | |
180 | + */ | |
181 | + virtual double getCorrectedSamplingValue(int maxResolution, double samplingValue); | |
182 | + | |
183 | + /** | |
184 | + * @brief Get the list of indexes used for a parameter | |
185 | + */ | |
186 | + virtual std::vector<AMDA::Common::ParameterIndexComponent> getParamUsedIndexes(std::string paramId, int dim1Size, int dim2Size = -1); | |
187 | + | |
188 | + const Margin getMargin() | |
189 | + { | |
190 | + Bounds panelBounds(_panel->getBoundsInPlPage()); | |
191 | + | |
192 | + Margin m; | |
193 | + m._left = _plotAreaBounds._x - panelBounds._x; | |
194 | + m._right = (panelBounds._x + panelBounds._width) - (_plotAreaBounds._x + _plotAreaBounds._width); | |
195 | + m._top = (panelBounds._y + panelBounds._height) - (_plotAreaBounds._y + _plotAreaBounds._height); | |
196 | + m._bottom = _plotAreaBounds._y - panelBounds._y; | |
197 | + return m; | |
198 | + } | |
531 | 199 | |
532 | - /** | |
533 | - * @brief Fill the background of the plot area | |
534 | - * | |
535 | - * @param pls | |
536 | - */ | |
200 | + /** | |
201 | + * @brief reset plot | |
202 | + */ | |
203 | + virtual void resetPlot() | |
204 | + { | |
205 | + if (_panel != nullptr) | |
206 | + _panel->resetPlot(); | |
207 | + _automaticSerieColorCursor = 0; | |
208 | + _nbSeriesByYAxisMap.clear(); | |
209 | + _pls.reset(); | |
210 | + } | |
537 | 211 | |
538 | - void fillBackground(std::shared_ptr<plstream> &pls); | |
212 | + /* | |
213 | + * @brief Set pointer to params values | |
214 | + */ | |
215 | + void setParameterValues(std::map<std::string, ParameterData> *pParameterValues); | |
216 | + | |
217 | + /* | |
218 | + * @brief Get computed values (in relation with the y axis definition) for a y serie, an index of the serie and a time interval | |
219 | + * Do not forget to delete (*computedValues) !! | |
220 | + * Do not delete (*timeValues), the buffer is not copied !! | |
221 | + */ | |
222 | + bool getComputedValuesFromSerieAndInterval(double startDate, double stopDate, SeriesProperties &rSeriesProperties, | |
223 | + AMDA::Common::ParameterIndexComponent index, double **computedValues, double **timeValues, int &nbValues); | |
224 | + | |
225 | + /* | |
226 | + * @brief Get computed values (in relation with the color axis definition) for a color serie and a time interval | |
227 | + * Do not forget to delete computedValues !! | |
228 | + * Don't delete timeValues !! | |
229 | + */ | |
230 | + bool getColoredComputedValuesFromSerieAndInterval(double startDate, double stopDate, SeriesProperties &rSeriesProperties, | |
231 | + double **computedValues, double **timeValues, int &nbValues); | |
232 | + | |
233 | + /* | |
234 | + * @brief Get computed values (in relation with the y axis definition) for a y serie and a time interval | |
235 | + * Do not forget to delete computedValues !! | |
236 | + * Don't delete timeValues !! | |
237 | + */ | |
238 | + bool getErrorComputedValuesFromSerieAndInterval(double startDate, double stopDate, SeriesProperties &rSeriesProperties, | |
239 | + double **minComputedValues, double **minTimeValues, int &nbMinValues, | |
240 | + double **maxComputedValues, double **maxTimeValues, int &nbMaxValues); | |
241 | + | |
242 | + /** | |
243 | + *@brief Defines the layout constraint to be used for the panel when used within a layout | |
244 | + */ | |
245 | + virtual PanelConstraint getLayoutConstraint(void) | |
246 | + { | |
247 | + return PanelConstraint::MaxWidth; | |
248 | + } | |
539 | 249 | |
540 | -private: | |
250 | + /** | |
251 | + * @brief Get nb series to draw by y axis | |
252 | + */ | |
253 | + std::map<std::string, int> &getNbSeriesByYAxis(); | |
254 | + | |
255 | + /* | |
256 | + * @brief Return the color to draw the line of a serie | |
257 | + */ | |
258 | + Color getSerieLineColor(SeriesProperties &rSeriesProperties, bool moreThanOneSerieForAxis); | |
259 | + | |
260 | + /** | |
261 | + * @brief Plot container | |
262 | + */ | |
263 | + boost::shared_ptr<Panel> _panel; | |
264 | + | |
265 | + /** | |
266 | + * @brief Parameters and series info | |
267 | + */ | |
268 | + ParameterAxesList _parameterAxesList; | |
269 | + | |
270 | + /* | |
271 | + * @brief Type used to define a matrix grid | |
272 | + */ | |
273 | + struct GridPart | |
274 | + { | |
275 | + double x[2]; | |
276 | + double y[2]; | |
277 | + double value; | |
278 | + double isColorIndex; | |
279 | + }; | |
280 | + | |
281 | + typedef std::vector<GridPart> MatrixGrid; | |
282 | + | |
283 | + // datastore for sauvaud plot | |
284 | + struct SauvaudPart | |
285 | + { | |
286 | + double x[2]; | |
287 | + double y[2]; | |
288 | + std::vector<double> value; | |
289 | + double isColorIndex; | |
290 | + }; | |
291 | + | |
292 | + typedef std::vector<SauvaudPart> SauvaudGrid; | |
293 | + | |
294 | + /* | |
295 | + * @brief Draw a matrix | |
296 | + */ | |
297 | + void drawMatrix(MatrixGrid &matrixGrid, double minDataVal, double maxDataVal, | |
298 | + Color minValColor, Color maxValColor, int colorMapIndex, bool useLog0AsMin = false); | |
299 | + | |
300 | + void draw2DMatrix(SauvaudGrid &sauvaudGrid, double minDataVal, double maxDataVal, | |
301 | + Color minValColor, Color maxValColor, int colorMapIndex, bool useLog0AsMin = false); | |
302 | + | |
303 | + /** | |
304 | + * @brief Reset cursor used to attribute automatically a color to a serie | |
305 | + */ | |
306 | + void resetAutomaticSerieColorCursor() | |
307 | + { | |
308 | + _automaticSerieColorCursor = 0; | |
309 | + } | |
541 | 310 | |
542 | - void drawAxis(boost::shared_ptr<Axis> pAxis, TickConf& pTickConf, std::string pXAxisOptions, | |
543 | - std::string pYAxisOptions); | |
311 | + /** | |
312 | + * Draw a rectangle | |
313 | + */ | |
314 | + void drawRectangle(double xmin, double xmax, double ymin, double ymax, Color &pColor, double alpha = 1.); | |
544 | 315 | |
545 | - double estimateZAxisWidth(boost::shared_ptr<Axis> pZAxis); | |
316 | + bool isStandalone() | |
317 | + { | |
318 | + return _isStandalone; | |
319 | + } | |
546 | 320 | |
547 | - /** | |
548 | - * @brief _plotAreaSideSet Store which side of plot area is linked to an axis. | |
549 | - */ | |
550 | - std::map<PlotCommon::Position, bool> _plotAreaSideSet; | |
321 | + AMDA::Parameters::ParameterManager &_parameterManager; | |
322 | + | |
323 | + std::map<std::string, ParameterData> *_pParameterValues; | |
324 | + | |
325 | + protected: | |
326 | + AMDA::Parameters::TimeIntervalList *_timeIntervalListPtr; | |
327 | + | |
328 | + /** | |
329 | + * @brief Compute plot area. | |
330 | + * @note If ratio need to be kept, ratio will be kept between width and height. | |
331 | + * @param bounds_ plot area bounds. It is updated by this method. | |
332 | + */ | |
333 | + virtual void calculatePlotArea(const Bounds &panelBounds_, Bounds &bounds_); | |
334 | + | |
335 | + /** | |
336 | + *@brief computes Panel Plot XY ratio | |
337 | + */ | |
338 | + void computePanelPlotXYRatio(void); | |
339 | + | |
340 | + /** | |
341 | + * @brief Get colored value associated to a data value. Return false if the value is filtered. | |
342 | + */ | |
343 | + bool getColoredValue(double value, double filterMin, double filterMax, bool useLog0AsMin, PLFLT &col); | |
344 | + | |
345 | + /** | |
346 | + *@brief Draw fill area between parameter and constant or between parameters | |
347 | + */ | |
348 | + virtual void drawFills(double startDate, double stopDate); | |
349 | + | |
350 | + /** | |
351 | + * Draw list of symbols | |
352 | + */ | |
353 | + void drawSymbols(SymbolType pType, int pSize, double pFactor, Color pColor, | |
354 | + int pNbData, double *pXData, double *pYData, | |
355 | + double *pZData = NULL, double filterZMin = -DBL_MAX, double filterZMax = DBL_MAX); | |
356 | + | |
357 | + /** | |
358 | + * Draw list of lines | |
359 | + */ | |
360 | + void drawLines(LineType pType, LineStyle pStyle, int pWidth, Color &pColor, | |
361 | + int pNbData, double *pXData, double *pYData, | |
362 | + double *pZData = NULL, double filterZMin = -DBL_MAX, double filterZMax = DBL_MAX); | |
363 | + | |
364 | + /** | |
365 | + * Draw errors segments | |
366 | + */ | |
367 | + void drawYErrors(LineType pType, LineStyle pStyle, int pWidth, Color &pColor, | |
368 | + int pNbData, double *pXData, double *pYMinData, double *pYMaxData); | |
369 | + | |
370 | + /** | |
371 | + *@brief Draw the serie of a parameter component on plot. | |
372 | + */ | |
373 | + virtual void drawSeries(double startDate, double stopDate, int intervalIndex, std::string pParamId, SeriesProperties &pSeries, | |
374 | + AMDA::Common::ParameterIndexComponent pParamIndex, ParameterAxes ¶m, bool moreThanOneSerieForAxis); | |
375 | + | |
376 | + /** | |
377 | + *@brief Draw the spectro of a parameter on plot. | |
378 | + */ | |
379 | + virtual void drawSpectro(double startDate, double stopDate, std::string pParamId, | |
380 | + SpectroProperties &pSpectro); | |
381 | + | |
382 | + /** | |
383 | + *@brief Draw sauvaud plot of a parameter on plot. | |
384 | + */ | |
385 | + virtual void drawSauvaud(double startDate, double stopDate, std::string pParamId, | |
386 | + SauvaudProperties &pSauvaud, int subIndex, int subsNumber, std::string opositeLegend); | |
387 | + | |
388 | + virtual void drawIntervals(double startDate, double stopDate, std::string pParamId, | |
389 | + IntervalsProperties &pIntervals); | |
390 | + | |
391 | + /* | |
392 | + * @brief Draw interval | |
393 | + */ | |
394 | + virtual void drawSerieInterval(SeriesProperties &pSeries, | |
395 | + double *xValues, double *yValues, double *timeValues, | |
396 | + int nbValues, int intervalIndex); | |
397 | + | |
398 | + /** | |
399 | + * Draw an horizontal axis. | |
400 | + * Subclasses may override it to take into account decorator attached to that axis (for instance). | |
401 | + * @param pXAxis axis to draw. | |
402 | + * @param pPlWindow real word ranges. | |
403 | + * @param pPlotAreaSize plot ranges. | |
404 | + * @param pTickConf ticks configuration. | |
405 | + */ | |
406 | + virtual void drawXAxis(boost::shared_ptr<Axis> pXAxis, PlWindow &pPlWindow, Bounds &pPlotAreaSize, TickConf &pTickConf); | |
407 | + /** | |
408 | + * Draw a vertical axis. | |
409 | + * Subclasses may override it to take into account decorator attached to that axis (for instance). | |
410 | + * @param pXAxis axis to draw. | |
411 | + * @param pPlWindow real word ranges. | |
412 | + * @param pPlotAreaSize plot ranges. | |
413 | + * @param pTickConf ticks configuration. | |
414 | + */ | |
415 | + virtual void drawYAxis(boost::shared_ptr<Axis> pXAxis, PlWindow &pPlWindow, Bounds &pPlotAreaSize, TickConf &pTickConf); | |
416 | + /** | |
417 | + * @brief Draw legend for each axis. | |
418 | + * @param pAxis axis to draw. | |
419 | + * @param pPlWindow real word ranges. | |
420 | + * @param pPlotAreaSize plot ranges. | |
421 | + */ | |
422 | + virtual void drawLegends(boost::shared_ptr<Axis> &pAxis, PlWindow &pPlWindow, Bounds &pPlotAreaSize); | |
423 | + | |
424 | + /** | |
425 | + * @brief Draw parameters legend. | |
426 | + */ | |
427 | + virtual void drawParamsLegend(void); | |
428 | + | |
429 | + /** | |
430 | + * @brief Draw text legends. | |
431 | + */ | |
432 | + virtual void drawTextLegends(void); | |
433 | + | |
434 | + /** | |
435 | + * Convert an X axis string value to a double X value | |
436 | + * Subclasses may override it to take into account specific value meaning. | |
437 | + * @param value string value to convert. | |
438 | + */ | |
439 | + virtual double convertXAxisValue(const std::string &value); | |
440 | + | |
441 | + /** | |
442 | + * Convert an Y axis string value to a double Y value | |
443 | + * Subclasses may override it to take into account specific value meaning. | |
444 | + * @param value string value to convert. | |
445 | + */ | |
446 | + virtual double convertYAxisValue(const std::string &value); | |
447 | + | |
448 | + /** | |
449 | + * Draw X constant lines linked to an axis. | |
450 | + * Subclasses may override it to take into account decorator attached (for instance). | |
451 | + * @param pXAxis axis to draw. | |
452 | + * @param pPlWindow real word ranges. | |
453 | + */ | |
454 | + virtual void drawXConstantLines(boost::shared_ptr<Axis> pAxis, PlWindow &pPlWindow); | |
455 | + /** | |
456 | + * Draw X constant lines linked to an axis. | |
457 | + * Subclasses may override it to take into account decorator attached (for instance). | |
458 | + * @param pXAxis axis to draw. | |
459 | + * @param pPlWindow real word ranges. | |
460 | + */ | |
461 | + virtual void drawYConstantLines(boost::shared_ptr<Axis> pAxis, PlWindow &pPlWindow); | |
462 | + /** | |
463 | + * Draw textPlots for a panel. | |
464 | + * Subclasses may override it for specific drawings. | |
465 | + * @param pPlWindow real word ranges. | |
466 | + */ | |
467 | + virtual void drawTextPlots(boost::shared_ptr<Axis> pXAxis, boost::shared_ptr<Axis> pYAxis, PlWindow &pPlWindow, const TextPlots &textPlots); | |
468 | + | |
469 | + /** | |
470 | + * Draw curvePlot for a panel. | |
471 | + * Subclasses may override it for specific drawings. | |
472 | + * @param curvePlot curve properties. | |
473 | + */ | |
474 | + virtual void drawCurvePlot(CurvePlot &curvePlot); | |
475 | + | |
476 | + /** | |
477 | + * @brief Identify if other side of the plot area need to be drawn or not. | |
478 | + * @note A plot area side need to be drawn when there is no axis associated to it. | |
479 | + */ | |
480 | + virtual std::string drawOppositeSide(boost::shared_ptr<Axis> pAxis); | |
481 | + | |
482 | + /** | |
483 | + *@brief Draw additional objects on plot. | |
484 | + */ | |
485 | + virtual void drawAdditionalObjects(); | |
486 | + | |
487 | + /** | |
488 | + * Draw a z axis | |
489 | + */ | |
490 | + virtual void drawZAxis(boost::shared_ptr<Axis> pZAxis, PlWindow &pPlWindow, Bounds &pPlotAreaSize, TickConf &pTickConf); | |
491 | + | |
492 | + /** | |
493 | + * Get X Axis range for a serie | |
494 | + */ | |
495 | + Range getXAxisRange(SeriesProperties &pSeries, boost::shared_ptr<Axis> pAxis); | |
496 | + | |
497 | + /** | |
498 | + * Get Y Axis range for a serie | |
499 | + */ | |
500 | + Range getYAxisRange(SeriesProperties &pSeries, boost::shared_ptr<Axis> pAxis); | |
501 | + | |
502 | + /** | |
503 | + * Get Z Axis range for a serie | |
504 | + */ | |
505 | + Range getZAxisRange(SeriesProperties &pSeries, boost::shared_ptr<Axis> pAxis); | |
506 | + | |
507 | + /* | |
508 | + * @brief Return the color to draw the symbols of a serie | |
509 | + */ | |
510 | + Color getSerieSymbolColor(SeriesProperties &rSeriesProperties, Color &pLineColor); | |
511 | + | |
512 | + /** | |
513 | + * @brief Configure params legend for a plot. | |
514 | + */ | |
515 | + virtual void configureParamsLegend(double startTime, double stopTime, int intervalIndex); | |
516 | + | |
517 | + /** | |
518 | + * @brief Add a serie to the param legend | |
519 | + */ | |
520 | + void addSerieToParamsLegend(SeriesProperties &lSeriesProperties, | |
521 | + AMDA::Common::ParameterIndexComponent &index, std::string originalParamId, | |
522 | + Color &lineColor, Color &symbolColor, | |
523 | + double startTime, double stopTime, int intervalIndex); | |
524 | + | |
525 | + /* | |
526 | + * @brief Return the associated params legend to a serie | |
527 | + */ | |
528 | + virtual std::string getSerieParamsLegendString(SeriesProperties &rSeriesProperties, | |
529 | + AMDA::Common::ParameterIndexComponent &index, std::string originalParamId); | |
530 | + | |
531 | + /** | |
532 | + * @brief plplot stream | |
533 | + */ | |
534 | + std::shared_ptr<plstream> _pls; | |
535 | + | |
536 | + /* | |
537 | + * Dumps properties for test. | |
538 | + */ | |
539 | + virtual void dump(std::ostream &out_); | |
540 | + | |
541 | + /** | |
542 | + * @brief Fill the background of the plot area | |
543 | + * | |
544 | + * @param pls | |
545 | + */ | |
546 | + | |
547 | + void fillBackground(std::shared_ptr<plstream> &pls); | |
548 | + | |
549 | + private: | |
550 | + void drawAxis(boost::shared_ptr<Axis> pAxis, TickConf &pTickConf, std::string pXAxisOptions, | |
551 | + std::string pYAxisOptions); | |
552 | + | |
553 | + double estimateZAxisWidth(boost::shared_ptr<Axis> pZAxis); | |
554 | + | |
555 | + /** | |
556 | + * @brief _plotAreaSideSet Store which side of plot area is linked to an axis. | |
557 | + */ | |
558 | + std::map<PlotCommon::Position, bool> _plotAreaSideSet; | |
559 | + | |
560 | + /** | |
561 | + * @brief nb series to draw by y axis | |
562 | + */ | |
563 | + std::map<std::string, int> _nbSeriesByYAxisMap; | |
564 | + | |
565 | + /** | |
566 | + * @brief plot array on which to draw data. | |
567 | + */ | |
568 | + Bounds _plotAreaBounds; | |
569 | + | |
570 | + /* | |
571 | + * @brief Panel XY ratio used for angular conversion | |
572 | + */ | |
573 | + double _panelPlotXYRatio; | |
574 | + | |
575 | + /* | |
576 | + * @brief Panel left axis tickmark width | |
577 | + */ | |
578 | + double _leftAxisTickMarkWidth; | |
579 | + | |
580 | + /* | |
581 | + * @brief cursor use to set a default color to a serie | |
582 | + */ | |
583 | + int _automaticSerieColorCursor; | |
584 | + | |
585 | + /* | |
586 | + * | |
587 | + */ | |
588 | + bool _isStandalone; | |
589 | + | |
590 | + void reserveSpaceForAxis(boost::shared_ptr<Axis> &pAxis, double titleHeight, std::map<PlotCommon::Position, int> nbAxesBySide, | |
591 | + double &topSpace, double &bottomSpace, double &leftSpace, double &rightSpace); | |
592 | + | |
593 | + void reserveSpaceForTextLegend(boost::shared_ptr<TextLegendProperties> &pTextLegendProp, double titleHeight, double &topSpace, double &bottomSpace, double &leftSpace, double &rightSpace); | |
594 | + }; | |
551 | 595 | |
552 | 596 | /** |
553 | - * @brief nb series to draw by y axis | |
597 | + * Calculate room taken by tick. | |
554 | 598 | */ |
555 | - std::map<std::string,int> _nbSeriesByYAxisMap; | |
599 | + double getHorizontalTickLength(Axis *pAxis, double charHeight); | |
556 | 600 | |
557 | 601 | /** |
558 | - * @brief plot array on which to draw data. | |
602 | + * Calculate room taken by tick. | |
559 | 603 | */ |
560 | - Bounds _plotAreaBounds; | |
561 | - | |
562 | - /* | |
563 | - * @brief Panel XY ratio used for angular conversion | |
564 | - */ | |
565 | - double _panelPlotXYRatio; | |
566 | - | |
567 | - /* | |
568 | - * @brief Panel left axis tickmark width | |
569 | - */ | |
570 | - double _leftAxisTickMarkWidth; | |
571 | - | |
572 | - /* | |
573 | - * @brief cursor use to set a default color to a serie | |
574 | - */ | |
575 | - int _automaticSerieColorCursor; | |
576 | - | |
577 | - /* | |
578 | - * | |
579 | - */ | |
580 | - bool _isStandalone; | |
581 | - | |
582 | - void reserveSpaceForAxis (boost::shared_ptr<Axis>& pAxis, double titleHeight, std::map<PlotCommon::Position, int> nbAxesBySide, | |
583 | - double& topSpace, double& bottomSpace, double& leftSpace, double& rightSpace); | |
584 | - | |
585 | - void reserveSpaceForTextLegend (boost::shared_ptr<TextLegendProperties>& pTextLegendProp, double titleHeight, double& topSpace, double& bottomSpace, double& leftSpace, double& rightSpace); | |
586 | -}; | |
587 | - | |
588 | -/** | |
589 | - * Calculate room taken by tick. | |
590 | - */ | |
591 | -double getHorizontalTickLength(Axis* pAxis, double charHeight); | |
592 | - | |
593 | -/** | |
594 | - * Calculate room taken by tick. | |
595 | - */ | |
596 | -double getVerticalTickLength(Axis* pAxis, double charHeight); | |
604 | + double getVerticalTickLength(Axis *pAxis, double charHeight); | |
597 | 605 | |
598 | 606 | } /* namespace plot */ |
599 | 607 | #endif /* PANELPLOTOUTPUT_HH_ */ | ... | ... |
src/Parameters/fonctions/fourier/DiscreteFourierTransform.cc
... | ... | @@ -7,38 +7,172 @@ DiscreteFourierTransform<T, E>::DiscreteFourierTransform(int nbEchantillons_, ve |
7 | 7 | nbEchantillons = nbEchantillons_; |
8 | 8 | frequenceEchantillonnage = frequenceEchantillonnage_; |
9 | 9 | signal = signal_; |
10 | + | |
11 | + // Padding the input isgnal with 0's if it's small than nbEchantillons | |
12 | + | |
13 | + while (signal.size() < nbEchantillons) | |
14 | + { | |
15 | + signal.push_back((T)0); | |
16 | + } | |
10 | 17 | } |
11 | 18 | |
12 | 19 | template <class T, class E> |
13 | 20 | void DiscreteFourierTransform<T, E>::compute() |
14 | 21 | { |
15 | - for (int k = 0; k < nbEchantillons; k++) | |
22 | + const int N = signal.size(); | |
23 | + if (DiscreteFourierTransform<T, E>::isPowerOfTwo(N)) | |
24 | + { | |
25 | + phasors = DiscreteFourierTransform<T, E>::fft(signal); | |
26 | + } | |
27 | + else | |
28 | + { | |
29 | + phasors = DiscreteFourierTransform<T, E>::dft(signal); | |
30 | + } | |
31 | +} | |
32 | + | |
33 | +template <class T, class E> | |
34 | +std::vector<E> DiscreteFourierTransform<T, E>::createTestPoints(int N, double sampleSpacing) | |
35 | +{ | |
36 | + std::vector<E> out; | |
37 | + const E t = (E)sampleSpacing; | |
38 | + for (int i = 0; i < N; i++) | |
39 | + { | |
40 | + out.push_back((E)t * i); | |
41 | + } | |
42 | + return out; | |
43 | +} | |
44 | + | |
45 | +template <class T, class E> | |
46 | +std::vector<E> DiscreteFourierTransform<T, E>::createTestFunction(std::vector<E> x) | |
47 | +{ | |
48 | + const int N = x.size(); | |
49 | + std::vector<E> out; | |
50 | + for (int i = 0; i < N; i++) | |
51 | + { | |
52 | + const E val = (E)sin(50.0 * 2.0 * M_PI * x[i]) + 0.5 * sin(80.0 * 2.0 * M_PI * x[i]); | |
53 | + out.push_back(val); | |
54 | + } | |
55 | + return out; | |
56 | +} | |
57 | + | |
58 | +/** | |
59 | + * @brief We use Cooley-Tukey FFT Algorithm if the size of the signal is a power of 2 otherwise you should DFT brut. In The future we will use bluestein algorithm instead of DFT. | |
60 | + * Cooley-Tukey FFT Algorithms: http://people.scs.carleton.ca/~maheshwa/courses/5703COMP/16Fall/FFT_Report.pdf | |
61 | + * | |
62 | + * @tparam T template type of input data | |
63 | + * @tparam E template type of output data | |
64 | + * @param sig the signal as an input | |
65 | + * @return std::vector<std::complex<E>> the phasors (array of complex number) | |
66 | + */ | |
67 | +template <class T, class E> | |
68 | +std::vector<std::complex<E>> DiscreteFourierTransform<T, E>::fft(std::vector<T> sig) | |
69 | +{ | |
70 | + const int N = sig.size(); | |
71 | + if (N == 1) | |
16 | 72 | { |
17 | - E xR = 0; | |
18 | - E yI = 0; | |
19 | - E fk = (E)(k * frequenceEchantillonnage) / (E)nbEchantillons; | |
20 | - // E fk = (E)(k * 1.0 / nbEchantillons); | |
21 | - for (int n = 0; n < signal.size(); n++) | |
73 | + std::vector<std::complex<E>> out; | |
74 | + const std::complex<E> temp((E)sig[0], (E)0); | |
75 | + out.push_back(temp); | |
76 | + return out; | |
77 | + } | |
78 | + | |
79 | + const std::complex<E> WN = (complex<E>)std::polar(1.0, 2 * M_PI / N); | |
80 | + std::complex<E> W((E)1, (E)0); | |
81 | + | |
82 | + // divide and conquer: | |
83 | + // Recurse: all even samples | |
84 | + std::vector<std::complex<E>> | |
85 | + x_evens = fft(getEven(sig)); | |
86 | + | |
87 | + // Recurse: all odd samples | |
88 | + std::vector<std::complex<E>> x_odds = fft(getOdd(sig)); | |
89 | + | |
90 | + // Now, combine and perform N/2 operations! | |
91 | + std::complex<E> zeroComplex((E)0, (E)0); | |
92 | + std::vector<std::complex<E>> x(N, zeroComplex); | |
93 | + for (int k = 0; k < N / 2; k++) | |
94 | + { | |
95 | + x[k] = x_evens[k] + W * x_odds[k]; | |
96 | + x[k + (N / 2)] = x_evens[k] - W * x_odds[k]; | |
97 | + W = W * WN; | |
98 | + } | |
99 | + return x; | |
100 | +} | |
101 | + | |
102 | +template <class T, class E> | |
103 | +std::vector<std::complex<E>> DiscreteFourierTransform<T, E>::dft(std::vector<T> x) | |
104 | +{ | |
105 | + const int N = x.size(); | |
106 | + std::complex<E> zeroComplex((E)0, (E)0); | |
107 | + std::vector<std::complex<E>> out(N, zeroComplex); | |
108 | + for (int k = 0; k < N; k++) | |
109 | + { | |
110 | + for (int n = 0; n < N; n++) | |
22 | 111 | { |
23 | - const T val = signal[n]; | |
24 | - if (!isNAN(val)) | |
25 | - { | |
26 | - const double angle = 2 * M_PI * n * fk; | |
27 | - xR += (E)cos(angle) * val; | |
28 | - yI += (E)sin(angle) * val; | |
29 | - } | |
112 | + const std::complex<E> expVal = (complex<E>)std::polar(1.0, -2 * k * n * M_PI / N); | |
113 | + out[k] += ((E)x[n]) * expVal; | |
30 | 114 | } |
115 | + } | |
116 | + return out; | |
117 | +} | |
118 | + | |
119 | +template <class T, class E> | |
120 | +std::vector<E> DiscreteFourierTransform<T, E>::computeDSP(std::vector<std::complex<E>> x) | |
121 | +{ | |
122 | + const int N = x.size(); | |
123 | + std::vector<E> out; | |
124 | + for (int k = 0; k < N / 2; k++) | |
125 | + { | |
126 | + const E magnitude = (E)pow(abs(x[k]), 1); | |
127 | + const E dsp = (E)(2.0 / N) * magnitude; | |
128 | + out.push_back(dsp); | |
129 | + } | |
31 | 130 | |
32 | - E amplitude = (E)sqrt(xR * xR + yI * yI); | |
33 | - E phase = (E)atan2(yI, xR); | |
131 | + return out; | |
132 | +} | |
34 | 133 | |
35 | - amplitudes.push_back(amplitude); | |
36 | - phases.push_back(phase); | |
37 | - frequences.push_back(fk); | |
38 | - if (fk == (E)0) | |
39 | - periodes.push_back((E)0); | |
40 | - else | |
41 | - periodes.push_back((E)(1.0 / fk)); | |
42 | - sort(periodes.begin(), periodes.end()); | |
134 | +template <class T, class E> | |
135 | +std::vector<E> DiscreteFourierTransform<T, E>::getFreq(std::vector<std::complex<E>> x, double d) | |
136 | +{ | |
137 | + const int N = x.size(); | |
138 | + const double stepFreq = 1.0 / (d * N); | |
139 | + const int N1 = (N - 1) / 2 + 1; | |
140 | + std::vector<E> out; | |
141 | + for (int k = 0; k < N / 2; k++) | |
142 | + { | |
143 | + const E freq = (E)k * stepFreq; | |
144 | + out.push_back(freq); | |
43 | 145 | } |
146 | + | |
147 | + return out; | |
44 | 148 | } |
149 | + | |
150 | +template <class T, class E> | |
151 | +std::vector<T> DiscreteFourierTransform<T, E>::getOdd(std::vector<T> x) | |
152 | +{ | |
153 | + std::vector<T> odd; | |
154 | + for (int i = 0; i < x.size(); i++) | |
155 | + { | |
156 | + if (i % 2 != 0) | |
157 | + odd.push_back(x[i]); | |
158 | + } | |
159 | + return odd; | |
160 | +} | |
161 | + | |
162 | +template <class T, class E> | |
163 | +std::vector<T> DiscreteFourierTransform<T, E>::getEven(std::vector<T> x) | |
164 | +{ | |
165 | + std::vector<T> even; | |
166 | + for (int i = 0; i < x.size(); i++) | |
167 | + { | |
168 | + if (i % 2 == 0) | |
169 | + even.push_back(x[i]); | |
170 | + } | |
171 | + return even; | |
172 | +} | |
173 | + | |
174 | +template <class T, class E> | |
175 | +bool DiscreteFourierTransform<T, E>::isPowerOfTwo(int N) | |
176 | +{ | |
177 | + return (N & (N - 1)) == 0; | |
178 | +} | |
45 | 179 | \ No newline at end of file | ... | ... |
src/Parameters/fonctions/fourier/DiscreteFourierTransform.hh
... | ... | @@ -3,7 +3,10 @@ |
3 | 3 | #define _DISCRETEFOURIERTRANSFORM_H |
4 | 4 | |
5 | 5 | #include "plplot/plplot.h" |
6 | + | |
7 | +#include <complex> | |
6 | 8 | #include <math.h> |
9 | + | |
7 | 10 | #include <vector> |
8 | 11 | |
9 | 12 | using namespace std; |
... | ... | @@ -36,6 +39,16 @@ public: |
36 | 39 | */ |
37 | 40 | DiscreteFourierTransform(int nbEchantillons_, vector<T> signal_, double frequenceEchantillonnage_); |
38 | 41 | |
42 | + std::vector<std::complex<E>> fft(std::vector<T> sig); | |
43 | + std::vector<std::complex<E>> dft(std::vector<T> sig); | |
44 | + std::vector<T> getEven(std::vector<T> x); | |
45 | + std::vector<T> getOdd(std::vector<T> x); | |
46 | + std::vector<E> computeDSP(std::vector<std::complex<E>> x); | |
47 | + std::vector<E> getFreq(std::vector<std::complex<E>> x, double d); | |
48 | + std::vector<E> createTestPoints(int N, double sampleSpacing); | |
49 | + std::vector<E> createTestFunction(std::vector<E> x); | |
50 | + bool isPowerOfTwo(int N); | |
51 | + | |
39 | 52 | /** |
40 | 53 | * @brief Calcul de la TFD |
41 | 54 | * |
... | ... | @@ -82,6 +95,16 @@ public: |
82 | 95 | return periodes; |
83 | 96 | } |
84 | 97 | |
98 | + std::vector<std::complex<E>> getPhasors() | |
99 | + { | |
100 | + return phasors; | |
101 | + } | |
102 | + | |
103 | + void setPhasors(std::vector<std::complex<E>> x) | |
104 | + { | |
105 | + phasors = x; | |
106 | + } | |
107 | + | |
85 | 108 | private: |
86 | 109 | /** |
87 | 110 | * @brief Le nombre total d’échantillons (points qu’on a mesurés) |
... | ... | @@ -118,6 +141,8 @@ private: |
118 | 141 | * |
119 | 142 | */ |
120 | 143 | vector<E> periodes; |
144 | + | |
145 | + std::vector<std::complex<E>> phasors; | |
121 | 146 | }; |
122 | 147 | |
123 | 148 | #endif |
124 | 149 | \ No newline at end of file | ... | ... |