@@ -3,6 +3,8 | |||||
3 |
|
3 | |||
4 | #include "CoreGlobal.h" |
|
4 | #include "CoreGlobal.h" | |
5 |
|
5 | |||
|
6 | #include <Data/DataSeriesIterator.h> | |||
|
7 | ||||
6 | #include <QLoggingCategory> |
|
8 | #include <QLoggingCategory> | |
7 |
|
9 | |||
8 | Q_DECLARE_LOGGING_CATEGORY(LOG_DataSeriesUtils) |
|
10 | Q_DECLARE_LOGGING_CATEGORY(LOG_DataSeriesUtils) | |
@@ -154,6 +156,46 struct SCIQLOP_CORE_EXPORT DataSeriesUtils { | |||||
154 | */ |
|
156 | */ | |
155 | template <typename Iterator> |
|
157 | template <typename Iterator> | |
156 | static Resolution resolution(Iterator begin, Iterator end, bool logarithmic = false); |
|
158 | static Resolution resolution(Iterator begin, Iterator end, bool logarithmic = false); | |
|
159 | ||||
|
160 | /** | |||
|
161 | * Computes a regular mesh for a data series, according to resolutions for x-axis and y-axis | |||
|
162 | * passed as parameters. | |||
|
163 | * | |||
|
164 | * The mesh is created from the resolutions in x and y and the boundaries delimiting the data | |||
|
165 | * series. If the resolutions do not allow to obtain a regular mesh, they are recalculated. | |||
|
166 | * | |||
|
167 | * For example : | |||
|
168 | * Let x-axis data = [0, 1, 3, 5, 9], its associated values ββ= [0, 10, 30, 50, 90] and | |||
|
169 | * xResolution = 2. | |||
|
170 | * Based on the resolution, the mesh would be [0, 2, 4, 6, 8, 10] and would be invalid because | |||
|
171 | * it exceeds the maximum bound of the data. The resolution is thus recalculated so that the | |||
|
172 | * mesh holds between the data terminals. | |||
|
173 | * So => resolution is 1.8 and the mesh is [0, 1.8, 3.6, 5.4, 7.2, 9]. | |||
|
174 | * | |||
|
175 | * Once the mesh is generated in x and y, the values ββare associated with each mesh point, | |||
|
176 | * based on the data in the series, finding the existing data at which the mesh point would be | |||
|
177 | * or would be closest to, without exceeding it. | |||
|
178 | * | |||
|
179 | * In the example, we determine the value of each mesh point: | |||
|
180 | * - x = 0 => value = 0 (existing x in the data series) | |||
|
181 | * - x = 1.8 => value = 10 (the closest existing x: 1) | |||
|
182 | * - x = 3.6 => value = 30 (the closest existing x: 3) | |||
|
183 | * - x = 5.4 => value = 50 (the closest existing x: 5) | |||
|
184 | * - x = 7.2 => value = 50 (the closest existing x: 5) | |||
|
185 | * - x = 9 => value = 90 (existing x in the data series) | |||
|
186 | * | |||
|
187 | * Same algorithm is applied for y-axis. | |||
|
188 | * | |||
|
189 | * @param begin the iterator pointing to the beginning of the data series | |||
|
190 | * @param end the iterator pointing to the end of the data series | |||
|
191 | * @param xResolution the resolution expected for the mesh's x-axis | |||
|
192 | * @param yResolution the resolution expected for the mesh's y-axis | |||
|
193 | * @return the mesh created, an empty mesh if the input data do not allow to generate a regular | |||
|
194 | * mesh (empty data, null resolutions, logarithmic x-axis) | |||
|
195 | * @warning the method considers the dataset as sorted and doesn't control it. | |||
|
196 | */ | |||
|
197 | static Mesh regularMesh(DataSeriesIterator begin, DataSeriesIterator end, | |||
|
198 | Resolution xResolution, Resolution yResolution); | |||
157 | }; |
|
199 | }; | |
158 |
|
200 | |||
159 | template <typename Iterator> |
|
201 | template <typename Iterator> |
@@ -1,5 +1,7 | |||||
1 | #include "Data/DataSeriesUtils.h" |
|
1 | #include "Data/DataSeriesUtils.h" | |
2 |
|
2 | |||
|
3 | #include <cmath> | |||
|
4 | ||||
3 | Q_LOGGING_CATEGORY(LOG_DataSeriesUtils, "DataSeriesUtils") |
|
5 | Q_LOGGING_CATEGORY(LOG_DataSeriesUtils, "DataSeriesUtils") | |
4 |
|
6 | |||
5 | void DataSeriesUtils::fillDataHoles(std::vector<double> &xAxisData, std::vector<double> &valuesData, |
|
7 | void DataSeriesUtils::fillDataHoles(std::vector<double> &xAxisData, std::vector<double> &valuesData, | |
@@ -79,3 +81,36 void DataSeriesUtils::fillDataHoles(std::vector<double> &xAxisData, std::vector< | |||||
79 | } |
|
81 | } | |
80 | } |
|
82 | } | |
81 | } |
|
83 | } | |
|
84 | DataSeriesUtils::Mesh DataSeriesUtils::regularMesh(DataSeriesIterator begin, DataSeriesIterator end, | |||
|
85 | Resolution xResolution, Resolution yResolution) | |||
|
86 | { | |||
|
87 | // Checks preconditions | |||
|
88 | if (xResolution.m_Val == 0. || std::isnan(xResolution.m_Val) || yResolution.m_Val == 0. | |||
|
89 | || std::isnan(yResolution.m_Val)) { | |||
|
90 | qCWarning(LOG_DataSeriesUtils()) << "Can't generate mesh with a null resolution"; | |||
|
91 | return Mesh{}; | |||
|
92 | } | |||
|
93 | ||||
|
94 | if (xResolution.m_Logarithmic) { | |||
|
95 | qCWarning(LOG_DataSeriesUtils()) | |||
|
96 | << "Can't generate mesh with a logarithmic x-axis resolution"; | |||
|
97 | return Mesh{}; | |||
|
98 | } | |||
|
99 | ||||
|
100 | if (std::distance(begin, end) == 0) { | |||
|
101 | qCWarning(LOG_DataSeriesUtils()) << "Can't generate mesh for empty data"; | |||
|
102 | return Mesh{}; | |||
|
103 | } | |||
|
104 | ||||
|
105 | auto yData = begin->y(); | |||
|
106 | if (yData.empty()) { | |||
|
107 | qCWarning(LOG_DataSeriesUtils()) << "Can't generate mesh for data with no y-axis"; | |||
|
108 | return Mesh{}; | |||
|
109 | } | |||
|
110 | ||||
|
111 | // Converts y-axis and its resolution to logarithmic values | |||
|
112 | if (yResolution.m_Logarithmic) { | |||
|
113 | std::for_each(yData.begin(), yData.end(), [](auto &val) { val = std::log10(val); }); | |||
|
114 | } | |||
|
115 | ||||
|
116 | } |
General Comments 0
You need to be logged in to leave comments.
Login now