##// END OF EJS Templates
Fixes compilation warning
Alexandre Leroux -
r1014:a57177af4c0c
parent child
Show More
@@ -1,228 +1,228
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 <Data/DataSeriesIterator.h>
6 #include <Data/DataSeriesIterator.h>
7
7
8 #include <cmath>
9 #include <QLoggingCategory>
8 #include <QLoggingCategory>
9 #include <cmath>
10
10
11 Q_DECLARE_LOGGING_CATEGORY(LOG_DataSeriesUtils)
11 Q_DECLARE_LOGGING_CATEGORY(LOG_DataSeriesUtils)
12
12
13 /**
13 /**
14 * Utility class with methods for data series
14 * Utility class with methods for data series
15 */
15 */
16 struct SCIQLOP_CORE_EXPORT DataSeriesUtils {
16 struct SCIQLOP_CORE_EXPORT DataSeriesUtils {
17 /**
17 /**
18 * Define a meshs.
18 * Define a meshs.
19 *
19 *
20 * A mesh is a regular grid representing cells of the same width (in x) and of the same height
20 * A mesh is a regular grid representing cells of the same width (in x) and of the same height
21 * (in y). At each mesh point is associated a value.
21 * (in y). At each mesh point is associated a value.
22 *
22 *
23 * Each axis of the mesh is defined by a minimum value, a number of values is a mesh step.
23 * Each axis of the mesh is defined by a minimum value, a number of values is a mesh step.
24 * For example: if min = 1, nbValues = 5 and step = 2 => the axis of the mesh will be [1, 3, 5,
24 * For example: if min = 1, nbValues = 5 and step = 2 => the axis of the mesh will be [1, 3, 5,
25 * 7, 9].
25 * 7, 9].
26 *
26 *
27 * The values are defined in an array of size {nbX * nbY}. The data is stored along the X axis.
27 * The values are defined in an array of size {nbX * nbY}. The data is stored along the X axis.
28 *
28 *
29 * For example, the mesh:
29 * For example, the mesh:
30 * Y = 2 [ 7 ; 8 ; 9
30 * Y = 2 [ 7 ; 8 ; 9
31 * Y = 1 4 ; 5 ; 6
31 * Y = 1 4 ; 5 ; 6
32 * Y = 0 1 ; 2 ; 3 ]
32 * Y = 0 1 ; 2 ; 3 ]
33 * X = 0 X = 1 X = 2
33 * X = 0 X = 1 X = 2
34 *
34 *
35 * will be represented by data [1, 2, 3, 4, 5, 6, 7, 8, 9]
35 * will be represented by data [1, 2, 3, 4, 5, 6, 7, 8, 9]
36 */
36 */
37 struct Mesh {
37 struct Mesh {
38 explicit Mesh() = default;
38 explicit Mesh() = default;
39 explicit Mesh(int nbX, double xMin, double xStep, int nbY, double yMin, double yStep)
39 explicit Mesh(int nbX, double xMin, double xStep, int nbY, double yMin, double yStep)
40 : m_NbX{nbX},
40 : m_NbX{nbX},
41 m_XMin{xMin},
41 m_XMin{xMin},
42 m_XStep{xStep},
42 m_XStep{xStep},
43 m_NbY{nbY},
43 m_NbY{nbY},
44 m_YMin{yMin},
44 m_YMin{yMin},
45 m_YStep{yStep},
45 m_YStep{yStep},
46 m_Data(nbX * nbY)
46 m_Data(nbX * nbY)
47 {
47 {
48 }
48 }
49
49
50 inline bool isEmpty() const { return m_Data.size() == 0; }
50 inline bool isEmpty() const { return m_Data.size() == 0; }
51 inline double xMax() const { return m_XMin + (m_NbX - 1) * m_XStep; }
51 inline double xMax() const { return m_XMin + (m_NbX - 1) * m_XStep; }
52 inline double yMax() const { return m_YMin + (m_NbY - 1) * m_YStep; }
52 inline double yMax() const { return m_YMin + (m_NbY - 1) * m_YStep; }
53
53
54 int m_NbX{0};
54 int m_NbX{0};
55 double m_XMin{};
55 double m_XMin{};
56 double m_XStep{};
56 double m_XStep{};
57 int m_NbY{0};
57 int m_NbY{0};
58 double m_YMin{};
58 double m_YMin{};
59 double m_YStep{};
59 double m_YStep{};
60 std::vector<double> m_Data{};
60 std::vector<double> m_Data{};
61 };
61 };
62
62
63 /**
63 /**
64 * Represents a resolution used to generate the data of a mesh on the x-axis or in Y.
64 * Represents a resolution used to generate the data of a mesh on the x-axis or in Y.
65 *
65 *
66 * A resolution is represented by a value and flag indicating if it's in the logarithmic scale
66 * A resolution is represented by a value and flag indicating if it's in the logarithmic scale
67 * @sa Mesh
67 * @sa Mesh
68 */
68 */
69 struct Resolution {
69 struct Resolution {
70 double m_Val{std::numeric_limits<double>::quiet_NaN()};
70 double m_Val{std::numeric_limits<double>::quiet_NaN()};
71 bool m_Logarithmic{false};
71 bool m_Logarithmic{false};
72 };
72 };
73
73
74 /**
74 /**
75 * Processes data from a data series to complete the data holes with a fill value.
75 * Processes data from a data series to complete the data holes with a fill value.
76 *
76 *
77 * A data hole is determined by the resolution passed in parameter: if, between two continuous
77 * A data hole is determined by the resolution passed in parameter: if, between two continuous
78 * data on the x-axis, the difference between these data is greater than the resolution, then
78 * data on the x-axis, the difference between these data is greater than the resolution, then
79 * there is one or more holes between them. The holes are filled by adding:
79 * there is one or more holes between them. The holes are filled by adding:
80 * - for the x-axis, new data corresponding to the 'step resolution' starting from the first
80 * - for the x-axis, new data corresponding to the 'step resolution' starting from the first
81 * data;
81 * data;
82 * - for values, a default value (fill value) for each new data added on the x-axis.
82 * - for values, a default value (fill value) for each new data added on the x-axis.
83 *
83 *
84 * For example, with :
84 * For example, with :
85 * - xAxisData = [0, 1, 5, 7, 14 ]
85 * - xAxisData = [0, 1, 5, 7, 14 ]
86 * - valuesData = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] (two components per x-axis data)
86 * - valuesData = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] (two components per x-axis data)
87 * - fillValue = NaN
87 * - fillValue = NaN
88 * - and resolution = 2;
88 * - and resolution = 2;
89 *
89 *
90 * For the x axis, we calculate as data holes: [3, 9, 11, 13]. These holes are added to the
90 * For the x axis, we calculate as data holes: [3, 9, 11, 13]. These holes are added to the
91 * x-axis data, and NaNs (two per x-axis data) are added to the values:
91 * x-axis data, and NaNs (two per x-axis data) are added to the values:
92 * => xAxisData = [0, 1, 3, 5, 7, 9, 11, 13, 14 ]
92 * => xAxisData = [0, 1, 3, 5, 7, 9, 11, 13, 14 ]
93 * => valuesData = [0, 1, 2, 3, NaN, NaN, 4, 5, 6, 7, NaN, NaN, NaN, NaN, NaN, NaN, 8, 9]
93 * => valuesData = [0, 1, 2, 3, NaN, NaN, 4, 5, 6, 7, NaN, NaN, NaN, NaN, NaN, NaN, 8, 9]
94 *
94 *
95 * It is also possible to set bounds for the data series. If these bounds are defined and exceed
95 * It is also possible to set bounds for the data series. If these bounds are defined and exceed
96 * the limits of the data series, data holes are added to the series at the beginning and/or the
96 * the limits of the data series, data holes are added to the series at the beginning and/or the
97 * end.
97 * end.
98 *
98 *
99 * The generation of data holes at the beginning/end of the data series is performed starting
99 * The generation of data holes at the beginning/end of the data series is performed starting
100 * from the x-axis series limit and adding data holes at each 'resolution step' as long as the
100 * from the x-axis series limit and adding data holes at each 'resolution step' as long as the
101 * new bound is not reached.
101 * new bound is not reached.
102 *
102 *
103 * For example, with :
103 * For example, with :
104 * - xAxisData = [3, 4, 5, 6, 7 ]
104 * - xAxisData = [3, 4, 5, 6, 7 ]
105 * - valuesData = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
105 * - valuesData = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
106 * - fillValue = NaN
106 * - fillValue = NaN
107 * - minBound = 0
107 * - minBound = 0
108 * - maxBound = 12
108 * - maxBound = 12
109 * - and resolution = 2;
109 * - and resolution = 2;
110 *
110 *
111 * => Starting from 3 and decreasing 2 by 2 until reaching 0 : a data hole at value 1 will be
111 * => Starting from 3 and decreasing 2 by 2 until reaching 0 : a data hole at value 1 will be
112 * added to the beginning of the series
112 * added to the beginning of the series
113 * => Starting from 7 and increasing 2 by 2 until reaching 12 : data holes at values 9 and 11
113 * => Starting from 7 and increasing 2 by 2 until reaching 12 : data holes at values 9 and 11
114 * will be added to the end of the series
114 * will be added to the end of the series
115 *
115 *
116 * So :
116 * So :
117 * => xAxisData = [1, 3, 4, 5, 6, 7, 9, 11 ]
117 * => xAxisData = [1, 3, 4, 5, 6, 7, 9, 11 ]
118 * => valuesData = [NaN, NaN, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, NaN, NaN, NaN, NaN]
118 * => valuesData = [NaN, NaN, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, NaN, NaN, NaN, NaN]
119 *
119 *
120 * @param xAxisData the x-axis data of the data series
120 * @param xAxisData the x-axis data of the data series
121 * @param valuesData the values data of the data series
121 * @param valuesData the values data of the data series
122 * @param resolution the resoultion (on x-axis) used to determinate data holes
122 * @param resolution the resoultion (on x-axis) used to determinate data holes
123 * @param fillValue the fill value used for data holes in the values data
123 * @param fillValue the fill value used for data holes in the values data
124 * @param minBound the limit at which to start filling data holes for the series. If set to NaN,
124 * @param minBound the limit at which to start filling data holes for the series. If set to NaN,
125 * the limit is not used
125 * the limit is not used
126 * @param maxBound the limit at which to end filling data holes for the series. If set to NaN,
126 * @param maxBound the limit at which to end filling data holes for the series. If set to NaN,
127 * the limit is not used
127 * the limit is not used
128 *
128 *
129 * @remarks There is no control over the consistency between x-axis data and values data. The
129 * @remarks There is no control over the consistency between x-axis data and values data. The
130 * method considers that the data is well formed (the total number of values data is a multiple
130 * method considers that the data is well formed (the total number of values data is a multiple
131 * of the number of x-axis data)
131 * of the number of x-axis data)
132 */
132 */
133 static void fillDataHoles(std::vector<double> &xAxisData, std::vector<double> &valuesData,
133 static void fillDataHoles(std::vector<double> &xAxisData, std::vector<double> &valuesData,
134 double resolution,
134 double resolution,
135 double fillValue = std::numeric_limits<double>::quiet_NaN(),
135 double fillValue = std::numeric_limits<double>::quiet_NaN(),
136 double minBound = std::numeric_limits<double>::quiet_NaN(),
136 double minBound = std::numeric_limits<double>::quiet_NaN(),
137 double maxBound = std::numeric_limits<double>::quiet_NaN());
137 double maxBound = std::numeric_limits<double>::quiet_NaN());
138 /**
138 /**
139 * Computes the resolution of a dataset passed as a parameter.
139 * Computes the resolution of a dataset passed as a parameter.
140 *
140 *
141 * The resolution of a dataset is the minimum difference between two values that follow in the
141 * The resolution of a dataset is the minimum difference between two values that follow in the
142 * set.
142 * set.
143 * For example:
143 * For example:
144 * - for the set [0, 2, 4, 8, 10, 11, 13] => the resolution is 1 (difference between 10 and 11).
144 * - for the set [0, 2, 4, 8, 10, 11, 13] => the resolution is 1 (difference between 10 and 11).
145 *
145 *
146 * A resolution can be calculated on the logarithmic scale (base of 10). In this case, the
146 * A resolution can be calculated on the logarithmic scale (base of 10). In this case, the
147 * dataset is first converted to logarithmic values.
147 * dataset is first converted to logarithmic values.
148 * For example:
148 * For example:
149 * - for the set [10, 100, 10000, 1000000], the values are converted to [1, 2, 4, 6] => the
149 * - for the set [10, 100, 10000, 1000000], the values are converted to [1, 2, 4, 6] => the
150 * logarithmic resolution is 1 (difference between 1 and 2).
150 * logarithmic resolution is 1 (difference between 1 and 2).
151 *
151 *
152 * @param begin the iterator pointing to the beginning of the dataset
152 * @param begin the iterator pointing to the beginning of the dataset
153 * @param end the iterator pointing to the end of the dataset
153 * @param end the iterator pointing to the end of the dataset
154 * @param logarithmic computes a logarithmic resolution or not
154 * @param logarithmic computes a logarithmic resolution or not
155 * @return the resolution computed
155 * @return the resolution computed
156 * @warning the method considers the dataset as sorted and doesn't control it.
156 * @warning the method considers the dataset as sorted and doesn't control it.
157 */
157 */
158 template <typename Iterator>
158 template <typename Iterator>
159 static Resolution resolution(Iterator begin, Iterator end, bool logarithmic = false);
159 static Resolution resolution(Iterator begin, Iterator end, bool logarithmic = false);
160
160
161 /**
161 /**
162 * Computes a regular mesh for a data series, according to resolutions for x-axis and y-axis
162 * Computes a regular mesh for a data series, according to resolutions for x-axis and y-axis
163 * passed as parameters.
163 * passed as parameters.
164 *
164 *
165 * The mesh is created from the resolutions in x and y and the boundaries delimiting the data
165 * The mesh is created from the resolutions in x and y and the boundaries delimiting the data
166 * series. If the resolutions do not allow to obtain a regular mesh, they are recalculated.
166 * series. If the resolutions do not allow to obtain a regular mesh, they are recalculated.
167 *
167 *
168 * For example :
168 * For example :
169 * Let x-axis data = [0, 1, 3, 5, 9], its associated values ​​= [0, 10, 30, 50, 90] and
169 * Let x-axis data = [0, 1, 3, 5, 9], its associated values ​​= [0, 10, 30, 50, 90] and
170 * xResolution = 2.
170 * xResolution = 2.
171 * Based on the resolution, the mesh would be [0, 2, 4, 6, 8, 10] and would be invalid because
171 * Based on the resolution, the mesh would be [0, 2, 4, 6, 8, 10] and would be invalid because
172 * it exceeds the maximum bound of the data. The resolution is thus recalculated so that the
172 * it exceeds the maximum bound of the data. The resolution is thus recalculated so that the
173 * mesh holds between the data terminals.
173 * mesh holds between the data terminals.
174 * So => resolution is 1.8 and the mesh is [0, 1.8, 3.6, 5.4, 7.2, 9].
174 * So => resolution is 1.8 and the mesh is [0, 1.8, 3.6, 5.4, 7.2, 9].
175 *
175 *
176 * Once the mesh is generated in x and y, the values ​​are associated with each mesh point,
176 * Once the mesh is generated in x and y, the values ​​are associated with each mesh point,
177 * based on the data in the series, finding the existing data at which the mesh point would be
177 * based on the data in the series, finding the existing data at which the mesh point would be
178 * or would be closest to, without exceeding it.
178 * or would be closest to, without exceeding it.
179 *
179 *
180 * In the example, we determine the value of each mesh point:
180 * In the example, we determine the value of each mesh point:
181 * - x = 0 => value = 0 (existing x in the data series)
181 * - x = 0 => value = 0 (existing x in the data series)
182 * - x = 1.8 => value = 10 (the closest existing x: 1)
182 * - x = 1.8 => value = 10 (the closest existing x: 1)
183 * - x = 3.6 => value = 30 (the closest existing x: 3)
183 * - x = 3.6 => value = 30 (the closest existing x: 3)
184 * - x = 5.4 => value = 50 (the closest existing x: 5)
184 * - x = 5.4 => value = 50 (the closest existing x: 5)
185 * - x = 7.2 => value = 50 (the closest existing x: 5)
185 * - x = 7.2 => value = 50 (the closest existing x: 5)
186 * - x = 9 => value = 90 (existing x in the data series)
186 * - x = 9 => value = 90 (existing x in the data series)
187 *
187 *
188 * Same algorithm is applied for y-axis.
188 * Same algorithm is applied for y-axis.
189 *
189 *
190 * @param begin the iterator pointing to the beginning of the data series
190 * @param begin the iterator pointing to the beginning of the data series
191 * @param end the iterator pointing to the end of the data series
191 * @param end the iterator pointing to the end of the data series
192 * @param xResolution the resolution expected for the mesh's x-axis
192 * @param xResolution the resolution expected for the mesh's x-axis
193 * @param yResolution the resolution expected for the mesh's y-axis
193 * @param yResolution the resolution expected for the mesh's y-axis
194 * @return the mesh created, an empty mesh if the input data do not allow to generate a regular
194 * @return the mesh created, an empty mesh if the input data do not allow to generate a regular
195 * mesh (empty data, null resolutions, logarithmic x-axis)
195 * mesh (empty data, null resolutions, logarithmic x-axis)
196 * @warning the method considers the dataset as sorted and doesn't control it.
196 * @warning the method considers the dataset as sorted and doesn't control it.
197 */
197 */
198 static Mesh regularMesh(DataSeriesIterator begin, DataSeriesIterator end,
198 static Mesh regularMesh(DataSeriesIterator begin, DataSeriesIterator end,
199 Resolution xResolution, Resolution yResolution);
199 Resolution xResolution, Resolution yResolution);
200 };
200 };
201
201
202 template <typename Iterator>
202 template <typename Iterator>
203 DataSeriesUtils::Resolution DataSeriesUtils::resolution(Iterator begin, Iterator end,
203 DataSeriesUtils::Resolution DataSeriesUtils::resolution(Iterator begin, Iterator end,
204 bool logarithmic)
204 bool logarithmic)
205 {
205 {
206 // Retrieves data into a work dataset
206 // Retrieves data into a work dataset
207 using ValueType = typename Iterator::value_type;
207 using ValueType = typename Iterator::value_type;
208 std::vector<ValueType> values{};
208 std::vector<ValueType> values{};
209 std::copy(begin, end, std::back_inserter(values));
209 std::copy(begin, end, std::back_inserter(values));
210
210
211 // Converts data if logarithmic flag is activated
211 // Converts data if logarithmic flag is activated
212 if (logarithmic) {
212 if (logarithmic) {
213 std::for_each(values.begin(), values.end(),
213 std::for_each(values.begin(), values.end(),
214 [logarithmic](auto &val) { val = std::log10(val); });
214 [logarithmic](auto &val) { val = std::log10(val); });
215 }
215 }
216
216
217 // Computes the differences between the values in the dataset
217 // Computes the differences between the values in the dataset
218 std::adjacent_difference(values.begin(), values.end(), values.begin());
218 std::adjacent_difference(values.begin(), values.end(), values.begin());
219
219
220 // Retrieves the smallest difference
220 // Retrieves the smallest difference
221 auto resolutionIt = std::min_element(values.begin(), values.end());
221 auto resolutionIt = std::min_element(values.begin(), values.end());
222 auto resolution
222 auto resolution
223 = resolutionIt != values.end() ? *resolutionIt : std::numeric_limits<double>::quiet_NaN();
223 = resolutionIt != values.end() ? *resolutionIt : std::numeric_limits<double>::quiet_NaN();
224
224
225 return Resolution{resolution, logarithmic};
225 return Resolution{resolution, logarithmic};
226 }
226 }
227
227
228 #endif // SCIQLOP_DATASERIESUTILS_H
228 #endif // SCIQLOP_DATASERIESUTILS_H
@@ -1,100 +1,100
1
1
2 gui_moc_headers = [
2 gui_moc_headers = [
3 'include/DataSource/DataSourceWidget.h',
3 'include/DataSource/DataSourceWidget.h',
4 'include/Settings/SqpSettingsDialog.h',
4 'include/Settings/SqpSettingsDialog.h',
5 'include/Settings/SqpSettingsGeneralWidget.h',
5 'include/Settings/SqpSettingsGeneralWidget.h',
6 'include/SidePane/SqpSidePane.h',
6 'include/SidePane/SqpSidePane.h',
7 'include/SqpApplication.h',
7 'include/SqpApplication.h',
8 'include/DragAndDrop/DragDropScroller.h',
8 'include/DragAndDrop/DragDropScroller.h',
9 'include/DragAndDrop/DragDropTabSwitcher.h',
9 'include/DragAndDrop/DragDropTabSwitcher.h',
10 'include/TimeWidget/TimeWidget.h',
10 'include/TimeWidget/TimeWidget.h',
11 'include/Variable/VariableInspectorWidget.h',
11 'include/Variable/VariableInspectorWidget.h',
12 'include/Variable/RenameVariableDialog.h',
12 'include/Variable/RenameVariableDialog.h',
13 'include/Visualization/qcustomplot.h',
13 'include/Visualization/qcustomplot.h',
14 'include/Visualization/VisualizationGraphWidget.h',
14 'include/Visualization/VisualizationGraphWidget.h',
15 'include/Visualization/VisualizationTabWidget.h',
15 'include/Visualization/VisualizationTabWidget.h',
16 'include/Visualization/VisualizationWidget.h',
16 'include/Visualization/VisualizationWidget.h',
17 'include/Visualization/VisualizationZoneWidget.h',
17 'include/Visualization/VisualizationZoneWidget.h',
18 'include/Visualization/VisualizationDragDropContainer.h',
18 'include/Visualization/VisualizationDragDropContainer.h',
19 'include/Visualization/VisualizationDragWidget.h',
19 'include/Visualization/VisualizationDragWidget.h',
20 'include/Visualization/ColorScaleWidget.h'
20 'include/Visualization/ColorScaleEditor.h'
21 ]
21 ]
22
22
23 gui_ui_files = [
23 gui_ui_files = [
24 'ui/DataSource/DataSourceWidget.ui',
24 'ui/DataSource/DataSourceWidget.ui',
25 'ui/Settings/SqpSettingsDialog.ui',
25 'ui/Settings/SqpSettingsDialog.ui',
26 'ui/Settings/SqpSettingsGeneralWidget.ui',
26 'ui/Settings/SqpSettingsGeneralWidget.ui',
27 'ui/SidePane/SqpSidePane.ui',
27 'ui/SidePane/SqpSidePane.ui',
28 'ui/TimeWidget/TimeWidget.ui',
28 'ui/TimeWidget/TimeWidget.ui',
29 'ui/Variable/VariableInspectorWidget.ui',
29 'ui/Variable/VariableInspectorWidget.ui',
30 'ui/Variable/RenameVariableDialog.ui',
30 'ui/Variable/RenameVariableDialog.ui',
31 'ui/Variable/VariableMenuHeaderWidget.ui',
31 'ui/Variable/VariableMenuHeaderWidget.ui',
32 'ui/Visualization/VisualizationGraphWidget.ui',
32 'ui/Visualization/VisualizationGraphWidget.ui',
33 'ui/Visualization/VisualizationTabWidget.ui',
33 'ui/Visualization/VisualizationTabWidget.ui',
34 'ui/Visualization/VisualizationWidget.ui',
34 'ui/Visualization/VisualizationWidget.ui',
35 'ui/Visualization/VisualizationZoneWidget.ui',
35 'ui/Visualization/VisualizationZoneWidget.ui',
36 'ui/Visualization/ColorScaleWidget.ui'
36 'ui/Visualization/ColorScaleEditor.ui'
37 ]
37 ]
38
38
39 gui_qresources = ['resources/sqpguiresources.qrc']
39 gui_qresources = ['resources/sqpguiresources.qrc']
40
40
41 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
41 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
42 ui_files : gui_ui_files,
42 ui_files : gui_ui_files,
43 qresources : gui_qresources)
43 qresources : gui_qresources)
44
44
45 gui_sources = [
45 gui_sources = [
46 'src/SqpApplication.cpp',
46 'src/SqpApplication.cpp',
47 'src/DragAndDrop/DragDropHelper.cpp',
47 'src/DragAndDrop/DragDropHelper.cpp',
48 'src/DragAndDrop/DragDropScroller.cpp',
48 'src/DragAndDrop/DragDropScroller.cpp',
49 'src/DragAndDrop/DragDropTabSwitcher.cpp',
49 'src/DragAndDrop/DragDropTabSwitcher.cpp',
50 'src/Common/ColorUtils.cpp',
50 'src/Common/ColorUtils.cpp',
51 'src/Common/VisualizationDef.cpp',
51 'src/Common/VisualizationDef.cpp',
52 'src/DataSource/DataSourceTreeWidgetItem.cpp',
52 'src/DataSource/DataSourceTreeWidgetItem.cpp',
53 'src/DataSource/DataSourceTreeWidgetHelper.cpp',
53 'src/DataSource/DataSourceTreeWidgetHelper.cpp',
54 'src/DataSource/DataSourceWidget.cpp',
54 'src/DataSource/DataSourceWidget.cpp',
55 'src/DataSource/DataSourceTreeWidget.cpp',
55 'src/DataSource/DataSourceTreeWidget.cpp',
56 'src/Settings/SqpSettingsDialog.cpp',
56 'src/Settings/SqpSettingsDialog.cpp',
57 'src/Settings/SqpSettingsGeneralWidget.cpp',
57 'src/Settings/SqpSettingsGeneralWidget.cpp',
58 'src/SidePane/SqpSidePane.cpp',
58 'src/SidePane/SqpSidePane.cpp',
59 'src/TimeWidget/TimeWidget.cpp',
59 'src/TimeWidget/TimeWidget.cpp',
60 'src/Variable/VariableInspectorWidget.cpp',
60 'src/Variable/VariableInspectorWidget.cpp',
61 'src/Variable/VariableInspectorTableView.cpp',
61 'src/Variable/VariableInspectorTableView.cpp',
62 'src/Variable/VariableMenuHeaderWidget.cpp',
62 'src/Variable/VariableMenuHeaderWidget.cpp',
63 'src/Variable/RenameVariableDialog.cpp',
63 'src/Variable/RenameVariableDialog.cpp',
64 'src/Visualization/VisualizationGraphHelper.cpp',
64 'src/Visualization/VisualizationGraphHelper.cpp',
65 'src/Visualization/VisualizationGraphRenderingDelegate.cpp',
65 'src/Visualization/VisualizationGraphRenderingDelegate.cpp',
66 'src/Visualization/VisualizationGraphWidget.cpp',
66 'src/Visualization/VisualizationGraphWidget.cpp',
67 'src/Visualization/VisualizationTabWidget.cpp',
67 'src/Visualization/VisualizationTabWidget.cpp',
68 'src/Visualization/VisualizationWidget.cpp',
68 'src/Visualization/VisualizationWidget.cpp',
69 'src/Visualization/VisualizationZoneWidget.cpp',
69 'src/Visualization/VisualizationZoneWidget.cpp',
70 'src/Visualization/qcustomplot.cpp',
70 'src/Visualization/qcustomplot.cpp',
71 'src/Visualization/QCustomPlotSynchronizer.cpp',
71 'src/Visualization/QCustomPlotSynchronizer.cpp',
72 'src/Visualization/operations/FindVariableOperation.cpp',
72 'src/Visualization/operations/FindVariableOperation.cpp',
73 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
73 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
74 'src/Visualization/operations/MenuBuilder.cpp',
74 'src/Visualization/operations/MenuBuilder.cpp',
75 'src/Visualization/operations/RemoveVariableOperation.cpp',
75 'src/Visualization/operations/RemoveVariableOperation.cpp',
76 'src/Visualization/operations/RescaleAxeOperation.cpp',
76 'src/Visualization/operations/RescaleAxeOperation.cpp',
77 'src/Visualization/VisualizationDragDropContainer.cpp',
77 'src/Visualization/VisualizationDragDropContainer.cpp',
78 'src/Visualization/VisualizationDragWidget.cpp',
78 'src/Visualization/VisualizationDragWidget.cpp',
79 'src/Visualization/AxisRenderingUtils.cpp',
79 'src/Visualization/AxisRenderingUtils.cpp',
80 'src/Visualization/PlottablesRenderingUtils.cpp',
80 'src/Visualization/PlottablesRenderingUtils.cpp',
81 'src/Visualization/MacScrollBarStyle.cpp',
81 'src/Visualization/MacScrollBarStyle.cpp',
82 'src/Visualization/VisualizationCursorItem.cpp',
82 'src/Visualization/VisualizationCursorItem.cpp',
83 'src/Visualization/ColorScaleWidget.cpp',
83 'src/Visualization/ColorScaleEditor.cpp',
84 'src/Visualization/SqpColorScale.cpp'
84 'src/Visualization/SqpColorScale.cpp'
85 ]
85 ]
86
86
87 gui_inc = include_directories(['include'])
87 gui_inc = include_directories(['include'])
88
88
89 sciqlop_gui_lib = library('sciqlopgui',
89 sciqlop_gui_lib = library('sciqlopgui',
90 gui_sources,
90 gui_sources,
91 gui_moc_files,
91 gui_moc_files,
92 include_directories : [gui_inc],
92 include_directories : [gui_inc],
93 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core],
93 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core],
94 install : true
94 install : true
95 )
95 )
96
96
97 sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib,
97 sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib,
98 include_directories : gui_inc,
98 include_directories : gui_inc,
99 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core])
99 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core])
100
100
@@ -1,164 +1,164
1 #include "Visualization/ColorScaleEditor.h"
1 #include "Visualization/ColorScaleEditor.h"
2 #include "Visualization/SqpColorScale.h"
2 #include "Visualization/SqpColorScale.h"
3
3
4 #include "ui_ColorScaleEditor.h"
4 #include "ui_ColorScaleEditor.h"
5
5
6 namespace {
6 namespace {
7
7
8 const auto GRADIENTS = QVariantMap{{"Candy", QCPColorGradient::gpCandy},
8 const auto GRADIENTS = QVariantMap{{"Candy", QCPColorGradient::gpCandy},
9 {"Cold", QCPColorGradient::gpCold},
9 {"Cold", QCPColorGradient::gpCold},
10 {"Geography", QCPColorGradient::gpGeography},
10 {"Geography", QCPColorGradient::gpGeography},
11 {"Grayscale", QCPColorGradient::gpGrayscale},
11 {"Grayscale", QCPColorGradient::gpGrayscale},
12 {"Hot", QCPColorGradient::gpHot},
12 {"Hot", QCPColorGradient::gpHot},
13 {"Hues", QCPColorGradient::gpHues},
13 {"Hues", QCPColorGradient::gpHues},
14 {"Ion", QCPColorGradient::gpIon},
14 {"Ion", QCPColorGradient::gpIon},
15 {"Jet", QCPColorGradient::gpJet},
15 {"Jet", QCPColorGradient::gpJet},
16 {"Night", QCPColorGradient::gpNight},
16 {"Night", QCPColorGradient::gpNight},
17 {"Polar", QCPColorGradient::gpPolar},
17 {"Polar", QCPColorGradient::gpPolar},
18 {"Spectrum", QCPColorGradient::gpSpectrum},
18 {"Spectrum", QCPColorGradient::gpSpectrum},
19 {"Thermal", QCPColorGradient::gpThermal}};
19 {"Thermal", QCPColorGradient::gpThermal}};
20
20
21 } // namespace
21 } // namespace
22
22
23 ColorScaleEditor::ColorScaleEditor(SqpColorScale &scale, QWidget *parent)
23 ColorScaleEditor::ColorScaleEditor(SqpColorScale &scale, QWidget *parent)
24 : QDialog{parent},
24 : QDialog{parent},
25 ui{new Ui::ColorScaleEditor},
25 ui{new Ui::ColorScaleEditor},
26 m_Scale{scale},
26 m_ThresholdGroup{new QButtonGroup{this}},
27 m_ThresholdGroup{new QButtonGroup{this}}
27 m_Scale{scale}
28 {
28 {
29 ui->setupUi(this);
29 ui->setupUi(this);
30
30
31 // Inits gradient combobox content
31 // Inits gradient combobox content
32 for (auto it = GRADIENTS.begin(), end = GRADIENTS.end(); it != end; ++it) {
32 for (auto it = GRADIENTS.begin(), end = GRADIENTS.end(); it != end; ++it) {
33 ui->gradientComboBox->addItem(it.key(), it.value());
33 ui->gradientComboBox->addItem(it.key(), it.value());
34 }
34 }
35
35
36 // Creates threshold group
36 // Creates threshold group
37 m_ThresholdGroup->addButton(ui->thresholdAutoButton);
37 m_ThresholdGroup->addButton(ui->thresholdAutoButton);
38 m_ThresholdGroup->addButton(ui->thresholdManualButton);
38 m_ThresholdGroup->addButton(ui->thresholdManualButton);
39
39
40 // Inits min/max spinboxes' properties
40 // Inits min/max spinboxes' properties
41 auto setSpinBoxProperties = [](auto &spinBox) {
41 auto setSpinBoxProperties = [](auto &spinBox) {
42 spinBox.setDecimals(3);
42 spinBox.setDecimals(3);
43 spinBox.setMinimum(-std::numeric_limits<double>::max());
43 spinBox.setMinimum(-std::numeric_limits<double>::max());
44 spinBox.setMaximum(std::numeric_limits<double>::max());
44 spinBox.setMaximum(std::numeric_limits<double>::max());
45 };
45 };
46 setSpinBoxProperties(*ui->minSpinBox);
46 setSpinBoxProperties(*ui->minSpinBox);
47 setSpinBoxProperties(*ui->maxSpinBox);
47 setSpinBoxProperties(*ui->maxSpinBox);
48
48
49 // Creates color scale preview
49 // Creates color scale preview
50 m_PreviewScale = new QCPColorScale{ui->plot};
50 m_PreviewScale = new QCPColorScale{ui->plot};
51 m_PreviewScale->setType(QCPAxis::atTop);
51 m_PreviewScale->setType(QCPAxis::atTop);
52 m_PreviewScale->setMinimumMargins(QMargins{5, 5, 5, 5});
52 m_PreviewScale->setMinimumMargins(QMargins{5, 5, 5, 5});
53 m_PreviewScale->axis()->setScaleType(QCPAxis::stLogarithmic);
53 m_PreviewScale->axis()->setScaleType(QCPAxis::stLogarithmic);
54 m_PreviewScale->axis()->setNumberPrecision(0);
54 m_PreviewScale->axis()->setNumberPrecision(0);
55 m_PreviewScale->axis()->setNumberFormat("eb");
55 m_PreviewScale->axis()->setNumberFormat("eb");
56 m_PreviewScale->axis()->setTicker(QSharedPointer<QCPAxisTickerLog>::create());
56 m_PreviewScale->axis()->setTicker(QSharedPointer<QCPAxisTickerLog>::create());
57 m_PreviewScale->setGradient(QCPColorGradient{QCPColorGradient::gpJet});
57 m_PreviewScale->setGradient(QCPColorGradient{QCPColorGradient::gpJet});
58
58
59 ui->plot->plotLayout()->clear();
59 ui->plot->plotLayout()->clear();
60 ui->plot->plotLayout()->insertRow(0);
60 ui->plot->plotLayout()->insertRow(0);
61 ui->plot->plotLayout()->addElement(0, 0, m_PreviewScale);
61 ui->plot->plotLayout()->addElement(0, 0, m_PreviewScale);
62
62
63 // Inits connections
63 // Inits connections
64 connect(ui->gradientComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updatePreview()));
64 connect(ui->gradientComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updatePreview()));
65 connect(ui->thresholdAutoButton, SIGNAL(toggled(bool)), this, SLOT(onThresholdChanged(bool)));
65 connect(ui->thresholdAutoButton, SIGNAL(toggled(bool)), this, SLOT(onThresholdChanged(bool)));
66 connect(ui->thresholdManualButton, SIGNAL(toggled(bool)), this, SLOT(onThresholdChanged(bool)));
66 connect(ui->thresholdManualButton, SIGNAL(toggled(bool)), this, SLOT(onThresholdChanged(bool)));
67 connect(ui->minSpinBox, SIGNAL(editingFinished()), this, SLOT(onMinChanged()));
67 connect(ui->minSpinBox, SIGNAL(editingFinished()), this, SLOT(onMinChanged()));
68 connect(ui->maxSpinBox, SIGNAL(editingFinished()), this, SLOT(onMaxChanged()));
68 connect(ui->maxSpinBox, SIGNAL(editingFinished()), this, SLOT(onMaxChanged()));
69
69
70 // OK/cancel buttons
70 // OK/cancel buttons
71 connect(ui->okButton, SIGNAL(clicked(bool)), this, SLOT(accept()));
71 connect(ui->okButton, SIGNAL(clicked(bool)), this, SLOT(accept()));
72 connect(ui->cancelButton, SIGNAL(clicked(bool)), this, SLOT(reject()));
72 connect(ui->cancelButton, SIGNAL(clicked(bool)), this, SLOT(reject()));
73
73
74 // Loads color scale
74 // Loads color scale
75 loadScale();
75 loadScale();
76 }
76 }
77
77
78 ColorScaleEditor::~ColorScaleEditor() noexcept
78 ColorScaleEditor::~ColorScaleEditor() noexcept
79 {
79 {
80 delete ui;
80 delete ui;
81 }
81 }
82
82
83 void ColorScaleEditor::loadScale()
83 void ColorScaleEditor::loadScale()
84 {
84 {
85 // Gradient
85 // Gradient
86 auto gradientPresetIndex = ui->gradientComboBox->findData(m_Scale.m_GradientPreset);
86 auto gradientPresetIndex = ui->gradientComboBox->findData(m_Scale.m_GradientPreset);
87 ui->gradientComboBox->setCurrentIndex(gradientPresetIndex);
87 ui->gradientComboBox->setCurrentIndex(gradientPresetIndex);
88
88
89 // Threshold mode
89 // Threshold mode
90 (m_Scale.m_AutomaticThreshold ? ui->thresholdAutoButton : ui->thresholdManualButton)
90 (m_Scale.m_AutomaticThreshold ? ui->thresholdAutoButton : ui->thresholdManualButton)
91 ->setChecked(true);
91 ->setChecked(true);
92
92
93 // Min/max
93 // Min/max
94 auto qcpColorScale = m_Scale.m_Scale;
94 auto qcpColorScale = m_Scale.m_Scale;
95 auto range = qcpColorScale->dataRange();
95 auto range = qcpColorScale->dataRange();
96 ui->minSpinBox->setValue(range.lower);
96 ui->minSpinBox->setValue(range.lower);
97 ui->maxSpinBox->setValue(range.upper);
97 ui->maxSpinBox->setValue(range.upper);
98
98
99 updatePreview();
99 updatePreview();
100 }
100 }
101
101
102 void ColorScaleEditor::saveScale()
102 void ColorScaleEditor::saveScale()
103 {
103 {
104 auto qcpColorScale = m_Scale.m_Scale;
104 auto qcpColorScale = m_Scale.m_Scale;
105
105
106 // Gradient
106 // Gradient
107 auto gradientPreset
107 auto gradientPreset
108 = ui->gradientComboBox->currentData().value<QCPColorGradient::GradientPreset>();
108 = ui->gradientComboBox->currentData().value<QCPColorGradient::GradientPreset>();
109 qcpColorScale->setGradient(gradientPreset);
109 qcpColorScale->setGradient(gradientPreset);
110 m_Scale.m_GradientPreset = gradientPreset;
110 m_Scale.m_GradientPreset = gradientPreset;
111
111
112 // Threshold mode
112 // Threshold mode
113 m_Scale.m_AutomaticThreshold = ui->thresholdAutoButton->isChecked();
113 m_Scale.m_AutomaticThreshold = ui->thresholdAutoButton->isChecked();
114
114
115 // Min/max
115 // Min/max
116 qcpColorScale->setDataRange(QCPRange{ui->minSpinBox->value(), ui->maxSpinBox->value()});
116 qcpColorScale->setDataRange(QCPRange{ui->minSpinBox->value(), ui->maxSpinBox->value()});
117 }
117 }
118
118
119 void ColorScaleEditor::accept()
119 void ColorScaleEditor::accept()
120 {
120 {
121 saveScale();
121 saveScale();
122 QDialog::accept();
122 QDialog::accept();
123 }
123 }
124
124
125 void ColorScaleEditor::onMaxChanged()
125 void ColorScaleEditor::onMaxChanged()
126 {
126 {
127 // Ensures that max >= min
127 // Ensures that max >= min
128 auto maxValue = ui->maxSpinBox->value();
128 auto maxValue = ui->maxSpinBox->value();
129 if (maxValue < ui->minSpinBox->value()) {
129 if (maxValue < ui->minSpinBox->value()) {
130 ui->minSpinBox->setValue(maxValue);
130 ui->minSpinBox->setValue(maxValue);
131 }
131 }
132
132
133 updatePreview();
133 updatePreview();
134 }
134 }
135
135
136 void ColorScaleEditor::onMinChanged()
136 void ColorScaleEditor::onMinChanged()
137 {
137 {
138 // Ensures that min <= max
138 // Ensures that min <= max
139 auto minValue = ui->minSpinBox->value();
139 auto minValue = ui->minSpinBox->value();
140 if (minValue > ui->maxSpinBox->value()) {
140 if (minValue > ui->maxSpinBox->value()) {
141 ui->maxSpinBox->setValue(minValue);
141 ui->maxSpinBox->setValue(minValue);
142 }
142 }
143
143
144 updatePreview();
144 updatePreview();
145 }
145 }
146
146
147 void ColorScaleEditor::onThresholdChanged(bool checked)
147 void ColorScaleEditor::onThresholdChanged(bool checked)
148 {
148 {
149 if (checked) {
149 if (checked) {
150 auto isAutomatic = ui->thresholdAutoButton == m_ThresholdGroup->checkedButton();
150 auto isAutomatic = ui->thresholdAutoButton == m_ThresholdGroup->checkedButton();
151
151
152 ui->minSpinBox->setEnabled(!isAutomatic);
152 ui->minSpinBox->setEnabled(!isAutomatic);
153 ui->maxSpinBox->setEnabled(!isAutomatic);
153 ui->maxSpinBox->setEnabled(!isAutomatic);
154 }
154 }
155 }
155 }
156
156
157 void ColorScaleEditor::updatePreview()
157 void ColorScaleEditor::updatePreview()
158 {
158 {
159 m_PreviewScale->setDataRange(QCPRange{ui->minSpinBox->value(), ui->maxSpinBox->value()});
159 m_PreviewScale->setDataRange(QCPRange{ui->minSpinBox->value(), ui->maxSpinBox->value()});
160 m_PreviewScale->setGradient(
160 m_PreviewScale->setGradient(
161 ui->gradientComboBox->currentData().value<QCPColorGradient::GradientPreset>());
161 ui->gradientComboBox->currentData().value<QCPColorGradient::GradientPreset>());
162
162
163 ui->plot->replot();
163 ui->plot->replot();
164 }
164 }
General Comments 0
You need to be logged in to leave comments. Login now