##// END OF EJS Templates
Creates method to compute resolutions of a dataset...
Alexandre Leroux -
r1032:01201e853d86
parent child
Show More
@@ -1,80 +1,139
1 #ifndef SCIQLOP_DATASERIESUTILS_H
1 #ifndef SCIQLOP_DATASERIESUTILS_H
2 #define SCIQLOP_DATASERIESUTILS_H
2 #define SCIQLOP_DATASERIESUTILS_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7
7
8 Q_DECLARE_LOGGING_CATEGORY(LOG_DataSeriesUtils)
8 Q_DECLARE_LOGGING_CATEGORY(LOG_DataSeriesUtils)
9
9
10 /**
10 /**
11 * Utility class with methods for data series
11 * Utility class with methods for data series
12 */
12 */
13 struct SCIQLOP_CORE_EXPORT DataSeriesUtils {
13 struct SCIQLOP_CORE_EXPORT DataSeriesUtils {
14 /**
14 /**
15 * Represents a resolution used to generate the data of a mesh on the x-axis or in Y.
16 *
17 * A resolution is represented by a value and flag indicating if it's in the logarithmic scale
18 * @sa Mesh
19 */
20 struct Resolution {
21 double m_Val{std::numeric_limits<double>::quiet_NaN()};
22 bool m_Logarithmic{false};
23 };
24
25 /**
15 * Processes data from a data series to complete the data holes with a fill value.
26 * Processes data from a data series to complete the data holes with a fill value.
16 *
27 *
17 * A data hole is determined by the resolution passed in parameter: if, between two continuous
28 * A data hole is determined by the resolution passed in parameter: if, between two continuous
18 * data on the x-axis, the difference between these data is greater than the resolution, then
29 * data on the x-axis, the difference between these data is greater than the resolution, then
19 * there is one or more holes between them. The holes are filled by adding:
30 * there is one or more holes between them. The holes are filled by adding:
20 * - for the x-axis, new data corresponding to the 'step resolution' starting from the first
31 * - for the x-axis, new data corresponding to the 'step resolution' starting from the first
21 * data;
32 * data;
22 * - for values, a default value (fill value) for each new data added on the x-axis.
33 * - for values, a default value (fill value) for each new data added on the x-axis.
23 *
34 *
24 * For example, with :
35 * For example, with :
25 * - xAxisData = [0, 1, 5, 7, 14 ]
36 * - xAxisData = [0, 1, 5, 7, 14 ]
26 * - valuesData = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] (two components per x-axis data)
37 * - valuesData = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] (two components per x-axis data)
27 * - fillValue = NaN
38 * - fillValue = NaN
28 * - and resolution = 2;
39 * - and resolution = 2;
29 *
40 *
30 * For the x axis, we calculate as data holes: [3, 9, 11, 13]. These holes are added to the
41 * For the x axis, we calculate as data holes: [3, 9, 11, 13]. These holes are added to the
31 * x-axis data, and NaNs (two per x-axis data) are added to the values:
42 * x-axis data, and NaNs (two per x-axis data) are added to the values:
32 * => xAxisData = [0, 1, 3, 5, 7, 9, 11, 13, 14 ]
43 * => xAxisData = [0, 1, 3, 5, 7, 9, 11, 13, 14 ]
33 * => valuesData = [0, 1, 2, 3, NaN, NaN, 4, 5, 6, 7, NaN, NaN, NaN, NaN, NaN, NaN, 8, 9]
44 * => valuesData = [0, 1, 2, 3, NaN, NaN, 4, 5, 6, 7, NaN, NaN, NaN, NaN, NaN, NaN, 8, 9]
34 *
45 *
35 * It is also possible to set bounds for the data series. If these bounds are defined and exceed
46 * It is also possible to set bounds for the data series. If these bounds are defined and exceed
36 * the limits of the data series, data holes are added to the series at the beginning and/or the
47 * the limits of the data series, data holes are added to the series at the beginning and/or the
37 * end.
48 * end.
38 *
49 *
39 * The generation of data holes at the beginning/end of the data series is performed starting
50 * The generation of data holes at the beginning/end of the data series is performed starting
40 * from the x-axis series limit and adding data holes at each 'resolution step' as long as the
51 * from the x-axis series limit and adding data holes at each 'resolution step' as long as the
41 * new bound is not reached.
52 * new bound is not reached.
42 *
53 *
43 * For example, with :
54 * For example, with :
44 * - xAxisData = [3, 4, 5, 6, 7 ]
55 * - xAxisData = [3, 4, 5, 6, 7 ]
45 * - valuesData = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
56 * - valuesData = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
46 * - fillValue = NaN
57 * - fillValue = NaN
47 * - minBound = 0
58 * - minBound = 0
48 * - maxBound = 12
59 * - maxBound = 12
49 * - and resolution = 2;
60 * - and resolution = 2;
50 *
61 *
51 * => Starting from 3 and decreasing 2 by 2 until reaching 0 : a data hole at value 1 will be
62 * => Starting from 3 and decreasing 2 by 2 until reaching 0 : a data hole at value 1 will be
52 * added to the beginning of the series
63 * added to the beginning of the series
53 * => Starting from 7 and increasing 2 by 2 until reaching 12 : data holes at values 9 and 11
64 * => Starting from 7 and increasing 2 by 2 until reaching 12 : data holes at values 9 and 11
54 * will be added to the end of the series
65 * will be added to the end of the series
55 *
66 *
56 * So :
67 * So :
57 * => xAxisData = [1, 3, 4, 5, 6, 7, 9, 11 ]
68 * => xAxisData = [1, 3, 4, 5, 6, 7, 9, 11 ]
58 * => valuesData = [NaN, NaN, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, NaN, NaN, NaN, NaN]
69 * => valuesData = [NaN, NaN, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, NaN, NaN, NaN, NaN]
59 *
70 *
60 * @param xAxisData the x-axis data of the data series
71 * @param xAxisData the x-axis data of the data series
61 * @param valuesData the values data of the data series
72 * @param valuesData the values data of the data series
62 * @param resolution the resoultion (on x-axis) used to determinate data holes
73 * @param resolution the resoultion (on x-axis) used to determinate data holes
63 * @param fillValue the fill value used for data holes in the values data
74 * @param fillValue the fill value used for data holes in the values data
64 * @param minBound the limit at which to start filling data holes for the series. If set to NaN,
75 * @param minBound the limit at which to start filling data holes for the series. If set to NaN,
65 * the limit is not used
76 * the limit is not used
66 * @param maxBound the limit at which to end filling data holes for the series. If set to NaN,
77 * @param maxBound the limit at which to end filling data holes for the series. If set to NaN,
67 * the limit is not used
78 * the limit is not used
68 *
79 *
69 * @remarks There is no control over the consistency between x-axis data and values data. The
80 * @remarks There is no control over the consistency between x-axis data and values data. The
70 * method considers that the data is well formed (the total number of values data is a multiple
81 * method considers that the data is well formed (the total number of values data is a multiple
71 * of the number of x-axis data)
82 * of the number of x-axis data)
72 */
83 */
73 static void fillDataHoles(std::vector<double> &xAxisData, std::vector<double> &valuesData,
84 static void fillDataHoles(std::vector<double> &xAxisData, std::vector<double> &valuesData,
74 double resolution,
85 double resolution,
75 double fillValue = std::numeric_limits<double>::quiet_NaN(),
86 double fillValue = std::numeric_limits<double>::quiet_NaN(),
76 double minBound = std::numeric_limits<double>::quiet_NaN(),
87 double minBound = std::numeric_limits<double>::quiet_NaN(),
77 double maxBound = std::numeric_limits<double>::quiet_NaN());
88 double maxBound = std::numeric_limits<double>::quiet_NaN());
89 /**
90 * Computes the resolution of a dataset passed as a parameter.
91 *
92 * The resolution of a dataset is the minimum difference between two values that follow in the
93 * set.
94 * For example:
95 * - for the set [0, 2, 4, 8, 10, 11, 13] => the resolution is 1 (difference between 10 and 11).
96 *
97 * A resolution can be calculated on the logarithmic scale (base of 10). In this case, the
98 * dataset is first converted to logarithmic values.
99 * For example:
100 * - for the set [10, 100, 10000, 1000000], the values are converted to [1, 2, 4, 6] => the
101 * logarithmic resolution is 1 (difference between 1 and 2).
102 *
103 * @param begin the iterator pointing to the beginning of the dataset
104 * @param end the iterator pointing to the end of the dataset
105 * @param logarithmic computes a logarithmic resolution or not
106 * @return the resolution computed
107 * @warning the method considers the dataset as sorted and doesn't control it.
108 */
109 template <typename Iterator>
110 static Resolution resolution(Iterator begin, Iterator end, bool logarithmic = false);
78 };
111 };
79
112
113 template <typename Iterator>
114 DataSeriesUtils::Resolution DataSeriesUtils::resolution(Iterator begin, Iterator end,
115 bool logarithmic)
116 {
117 // Retrieves data into a work dataset
118 using ValueType = typename Iterator::value_type;
119 std::vector<ValueType> values{};
120 std::copy(begin, end, std::back_inserter(values));
121
122 // Converts data if logarithmic flag is activated
123 if (logarithmic) {
124 std::for_each(values.begin(), values.end(),
125 [logarithmic](auto &val) { val = std::log10(val); });
126 }
127
128 // Computes the differences between the values in the dataset
129 std::adjacent_difference(values.begin(), values.end(), values.begin());
130
131 // Retrieves the smallest difference
132 auto resolutionIt = std::min_element(values.begin(), values.end());
133 auto resolution
134 = resolutionIt != values.end() ? *resolutionIt : std::numeric_limits<double>::quiet_NaN();
135
136 return Resolution{resolution, logarithmic};
137 }
138
80 #endif // SCIQLOP_DATASERIESUTILS_H
139 #endif // SCIQLOP_DATASERIESUTILS_H
General Comments 0
You need to be logged in to leave comments. Login now