##// END OF EJS Templates
Spectrograms implementation (5)...
Alexandre Leroux -
r942:aa9146db2d67
parent child
Show More
@@ -1,101 +1,105
1 #ifndef SCIQLOP_AMDARESULTPARSERHELPER_H
1 #ifndef SCIQLOP_AMDARESULTPARSERHELPER_H
2 #define SCIQLOP_AMDARESULTPARSERHELPER_H
2 #define SCIQLOP_AMDARESULTPARSERHELPER_H
3
3
4 #include "AmdaResultParserDefs.h"
4 #include "AmdaResultParserDefs.h"
5
5
6 #include <QtCore/QLoggingCategory>
6 #include <QtCore/QLoggingCategory>
7 #include <QtCore/QString>
7 #include <QtCore/QString>
8
8
9 #include <memory>
9 #include <memory>
10
10
11 class IDataSeries;
11 class IDataSeries;
12
12
13 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaResultParserHelper)
13 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaResultParserHelper)
14
14
15 /**
15 /**
16 * Helper used to interpret the data of an AMDA result file and generate the corresponding data
16 * Helper used to interpret the data of an AMDA result file and generate the corresponding data
17 * series.
17 * series.
18 *
18 *
19 * It proposes methods allowing to read line by line an AMDA file and to extract the properties
19 * It proposes methods allowing to read line by line an AMDA file and to extract the properties
20 * (from the header) and the values corresponding to the data series
20 * (from the header) and the values corresponding to the data series
21 *
21 *
22 * @sa DataSeries
22 * @sa DataSeries
23 */
23 */
24 struct IAmdaResultParserHelper {
24 struct IAmdaResultParserHelper {
25 virtual ~IAmdaResultParserHelper() noexcept = default;
25 virtual ~IAmdaResultParserHelper() noexcept = default;
26
26
27 /// Verifies that the extracted properties are well formed and possibly applies other treatments
27 /// Verifies that the extracted properties are well formed and possibly applies other treatments
28 /// on them
28 /// on them
29 /// @return true if the properties are well formed, false otherwise
29 /// @return true if the properties are well formed, false otherwise
30 virtual bool checkProperties() = 0;
30 virtual bool checkProperties() = 0;
31
31
32 /// Creates the data series from the properties and values extracted from the AMDA file.
32 /// Creates the data series from the properties and values extracted from the AMDA file.
33 /// @warning as the data are moved in the data series, the helper shouldn't be used after
33 /// @warning as the data are moved in the data series, the helper shouldn't be used after
34 /// calling this method
34 /// calling this method
35 /// @return the data series created
35 /// @return the data series created
36 virtual std::shared_ptr<IDataSeries> createSeries() = 0;
36 virtual std::shared_ptr<IDataSeries> createSeries() = 0;
37
37
38 /// Reads a line from the AMDA file to extract a property that will be used to generate the data
38 /// Reads a line from the AMDA file to extract a property that will be used to generate the data
39 /// series
39 /// series
40 /// @param line tahe line to interpret
40 /// @param line tahe line to interpret
41 virtual void readPropertyLine(const QString &line) = 0;
41 virtual void readPropertyLine(const QString &line) = 0;
42
42
43 /// Reads a line from the AMDA file to extract a value that will be set in the data series
43 /// Reads a line from the AMDA file to extract a value that will be set in the data series
44 /// @param line the line to interpret
44 /// @param line the line to interpret
45 virtual void readResultLine(const QString &line) = 0;
45 virtual void readResultLine(const QString &line) = 0;
46 };
46 };
47
47
48 /**
48 /**
49 * Implementation of @sa IAmdaResultParserHelper for scalars
49 * Implementation of @sa IAmdaResultParserHelper for scalars
50 */
50 */
51 class ScalarParserHelper : public IAmdaResultParserHelper {
51 class ScalarParserHelper : public IAmdaResultParserHelper {
52 public:
52 public:
53 bool checkProperties() override;
53 bool checkProperties() override;
54 std::shared_ptr<IDataSeries> createSeries() override;
54 std::shared_ptr<IDataSeries> createSeries() override;
55 void readPropertyLine(const QString &line) override;
55 void readPropertyLine(const QString &line) override;
56 void readResultLine(const QString &line) override;
56 void readResultLine(const QString &line) override;
57
57
58 private:
58 private:
59 /// @return the reading order of the "value" columns for a result line of the AMDA file
59 /// @return the reading order of the "value" columns for a result line of the AMDA file
60 std::vector<int> valuesIndexes() const;
60 std::vector<int> valuesIndexes() const;
61
61
62 Properties m_Properties{};
62 Properties m_Properties{};
63 std::vector<double> m_XAxisData{};
63 std::vector<double> m_XAxisData{};
64 std::vector<double> m_ValuesData{};
64 std::vector<double> m_ValuesData{};
65 };
65 };
66
66
67 /**
67 /**
68 * Implementation of @sa IAmdaResultParserHelper for spectrograms
68 * Implementation of @sa IAmdaResultParserHelper for spectrograms
69 */
69 */
70 class SpectrogramParserHelper : public IAmdaResultParserHelper {
70 class SpectrogramParserHelper : public IAmdaResultParserHelper {
71 public:
71 public:
72 bool checkProperties() override;
72 bool checkProperties() override;
73 std::shared_ptr<IDataSeries> createSeries() override;
73 std::shared_ptr<IDataSeries> createSeries() override;
74 void readPropertyLine(const QString &line) override;
74 void readPropertyLine(const QString &line) override;
75 void readResultLine(const QString &line) override;
75 void readResultLine(const QString &line) override;
76
76
77 private:
77 private:
78 Properties m_Properties{};
78 Properties m_Properties{};
79 std::vector<double> m_XAxisData{};
79 std::vector<double> m_YAxisData{};
80 std::vector<double> m_YAxisData{};
81 std::vector<double> m_ValuesData{};
82 std::vector<int> m_ValuesIndexes{};
83 double m_FillValue{std::numeric_limits<double>::quiet_NaN()};
80 };
84 };
81
85
82 /**
86 /**
83 * Implementation of @sa IAmdaResultParserHelper for vectors
87 * Implementation of @sa IAmdaResultParserHelper for vectors
84 */
88 */
85 class VectorParserHelper : public IAmdaResultParserHelper {
89 class VectorParserHelper : public IAmdaResultParserHelper {
86 public:
90 public:
87 bool checkProperties() override;
91 bool checkProperties() override;
88 std::shared_ptr<IDataSeries> createSeries() override;
92 std::shared_ptr<IDataSeries> createSeries() override;
89 void readPropertyLine(const QString &line) override;
93 void readPropertyLine(const QString &line) override;
90 void readResultLine(const QString &line) override;
94 void readResultLine(const QString &line) override;
91
95
92 private:
96 private:
93 /// @return the reading order of the "value" columns for a result line of the AMDA file
97 /// @return the reading order of the "value" columns for a result line of the AMDA file
94 std::vector<int> valuesIndexes() const;
98 std::vector<int> valuesIndexes() const;
95
99
96 Properties m_Properties{};
100 Properties m_Properties{};
97 std::vector<double> m_XAxisData{};
101 std::vector<double> m_XAxisData{};
98 std::vector<double> m_ValuesData{};
102 std::vector<double> m_ValuesData{};
99 };
103 };
100
104
101 #endif // SCIQLOP_AMDARESULTPARSERHELPER_H
105 #endif // SCIQLOP_AMDARESULTPARSERHELPER_H
@@ -1,367 +1,385
1 #include "AmdaResultParserHelper.h"
1 #include "AmdaResultParserHelper.h"
2
2
3 #include <Common/DateUtils.h>
3 #include <Common/DateUtils.h>
4 #include <Common/SortUtils.h>
4
5
5 #include <Data/ScalarSeries.h>
6 #include <Data/ScalarSeries.h>
7 #include <Data/SpectrogramSeries.h>
6 #include <Data/Unit.h>
8 #include <Data/Unit.h>
7 #include <Data/VectorSeries.h>
9 #include <Data/VectorSeries.h>
8
10
9 #include <QtCore/QDateTime>
11 #include <QtCore/QDateTime>
10 #include <QtCore/QRegularExpression>
12 #include <QtCore/QRegularExpression>
11
13
12 Q_LOGGING_CATEGORY(LOG_AmdaResultParserHelper, "AmdaResultParserHelper")
14 Q_LOGGING_CATEGORY(LOG_AmdaResultParserHelper, "AmdaResultParserHelper")
13
15
14 namespace {
16 namespace {
15
17
16 // ///////// //
18 // ///////// //
17 // Constants //
19 // Constants //
18 // ///////// //
20 // ///////// //
19
21
20 /// Separator between values in a result line
22 /// Separator between values in a result line
21 const auto RESULT_LINE_SEPARATOR = QRegularExpression{QStringLiteral("\\s+")};
23 const auto RESULT_LINE_SEPARATOR = QRegularExpression{QStringLiteral("\\s+")};
22
24
23 /// Format for dates in result files
25 /// Format for dates in result files
24 const auto DATE_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss.zzz");
26 const auto DATE_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss.zzz");
25
27
26 // /////// //
28 // /////// //
27 // Methods //
29 // Methods //
28 // /////// //
30 // /////// //
29
31
30 /**
32 /**
31 * Checks that the properties contain a specific unit and that this unit is valid
33 * Checks that the properties contain a specific unit and that this unit is valid
32 * @param properties the properties map in which to search unit
34 * @param properties the properties map in which to search unit
33 * @param key the key to search for the unit in the properties
35 * @param key the key to search for the unit in the properties
34 * @param errorMessage the error message to log in case the unit is invalid
36 * @param errorMessage the error message to log in case the unit is invalid
35 * @return true if the unit is valid, false it it's invalid or was not found in the properties
37 * @return true if the unit is valid, false it it's invalid or was not found in the properties
36 */
38 */
37 bool checkUnit(const Properties &properties, const QString &key, const QString &errorMessage)
39 bool checkUnit(const Properties &properties, const QString &key, const QString &errorMessage)
38 {
40 {
39 auto unit = properties.value(key).value<Unit>();
41 auto unit = properties.value(key).value<Unit>();
40 if (unit.m_Name.isEmpty()) {
42 if (unit.m_Name.isEmpty()) {
41 qCWarning(LOG_AmdaResultParserHelper()) << errorMessage;
43 qCWarning(LOG_AmdaResultParserHelper()) << errorMessage;
42 return false;
44 return false;
43 }
45 }
44
46
45 return true;
47 return true;
46 }
48 }
47
49
48 QDateTime dateTimeFromString(const QString &stringDate) noexcept
50 QDateTime dateTimeFromString(const QString &stringDate) noexcept
49 {
51 {
50 #if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
52 #if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
51 return QDateTime::fromString(stringDate, Qt::ISODateWithMs);
53 return QDateTime::fromString(stringDate, Qt::ISODateWithMs);
52 #else
54 #else
53 return QDateTime::fromString(stringDate, DATE_FORMAT);
55 return QDateTime::fromString(stringDate, DATE_FORMAT);
54 #endif
56 #endif
55 }
57 }
56
58
57 /// Converts a string date to a double date
59 /// Converts a string date to a double date
58 /// @return a double that represents the date in seconds, NaN if the string date can't be converted
60 /// @return a double that represents the date in seconds, NaN if the string date can't be converted
59 double doubleDate(const QString &stringDate) noexcept
61 double doubleDate(const QString &stringDate) noexcept
60 {
62 {
61 // Format: yyyy-MM-ddThh:mm:ss.zzz
63 // Format: yyyy-MM-ddThh:mm:ss.zzz
62 auto dateTime = dateTimeFromString(stringDate);
64 auto dateTime = dateTimeFromString(stringDate);
63 dateTime.setTimeSpec(Qt::UTC);
65 dateTime.setTimeSpec(Qt::UTC);
64 return dateTime.isValid() ? DateUtils::secondsSinceEpoch(dateTime)
66 return dateTime.isValid() ? DateUtils::secondsSinceEpoch(dateTime)
65 : std::numeric_limits<double>::quiet_NaN();
67 : std::numeric_limits<double>::quiet_NaN();
66 }
68 }
67
69
68 /**
70 /**
69 * Reads a line from the AMDA file and tries to extract a x-axis data and value data from it
71 * Reads a line from the AMDA file and tries to extract a x-axis data and value data from it
70 * @param xAxisData the vector in which to store the x-axis data extracted
72 * @param xAxisData the vector in which to store the x-axis data extracted
71 * @param valuesData the vector in which to store the value extracted
73 * @param valuesData the vector in which to store the value extracted
72 * @param line the line to read to extract the property
74 * @param line the line to read to extract the property
73 * @param valuesIndexes indexes of insertion of read values. For example, if the line contains three
75 * @param valuesIndexes indexes of insertion of read values. For example, if the line contains three
74 * columns of values, and valuesIndexes are {2, 0, 1}, the value of the third column will be read
76 * columns of values, and valuesIndexes are {2, 0, 1}, the value of the third column will be read
75 * and inserted first, then the value of the first column, and finally the value of the second
77 * and inserted first, then the value of the first column, and finally the value of the second
76 * column.
78 * column.
77 * @param fillValue value that tags an invalid data. For example, if fillValue is -1 and a read
79 * @param fillValue value that tags an invalid data. For example, if fillValue is -1 and a read
78 * value is -1, then this value is considered as invalid and converted to NaN
80 * value is -1, then this value is considered as invalid and converted to NaN
79 */
81 */
80 void tryReadResult(std::vector<double> &xAxisData, std::vector<double> &valuesData,
82 void tryReadResult(std::vector<double> &xAxisData, std::vector<double> &valuesData,
81 const QString &line, const std::vector<int> &valuesIndexes,
83 const QString &line, const std::vector<int> &valuesIndexes,
82 double fillValue = std::numeric_limits<double>::quiet_NaN())
84 double fillValue = std::numeric_limits<double>::quiet_NaN())
83 {
85 {
84 auto lineData = line.split(RESULT_LINE_SEPARATOR, QString::SkipEmptyParts);
86 auto lineData = line.split(RESULT_LINE_SEPARATOR, QString::SkipEmptyParts);
85
87
86 // Checks that the line contains expected number of values + x-axis value
88 // Checks that the line contains expected number of values + x-axis value
87 if (lineData.size() == valuesIndexes.size() + 1) {
89 if (lineData.size() == valuesIndexes.size() + 1) {
88 // X : the data is converted from date to double (in secs)
90 // X : the data is converted from date to double (in secs)
89 auto x = doubleDate(lineData.at(0));
91 auto x = doubleDate(lineData.at(0));
90
92
91 // Adds result only if x is valid. Then, if value is invalid, it is set to NaN
93 // Adds result only if x is valid. Then, if value is invalid, it is set to NaN
92 if (!std::isnan(x)) {
94 if (!std::isnan(x)) {
93 xAxisData.push_back(x);
95 xAxisData.push_back(x);
94
96
95 // Values
97 // Values
96 for (auto valueIndex : valuesIndexes) {
98 for (auto valueIndex : valuesIndexes) {
97 bool valueOk;
99 bool valueOk;
98 // we use valueIndex + 1 to skip column 0 (x-axis value)
100 // we use valueIndex + 1 to skip column 0 (x-axis value)
99 auto value = lineData.at(valueIndex + 1).toDouble(&valueOk);
101 auto value = lineData.at(valueIndex + 1).toDouble(&valueOk);
100
102
101 if (!valueOk) {
103 if (!valueOk) {
102 qCWarning(LOG_AmdaResultParserHelper())
104 qCWarning(LOG_AmdaResultParserHelper())
103 << QObject::tr(
105 << QObject::tr(
104 "Value from (line %1, column %2) is invalid and will be "
106 "Value from (line %1, column %2) is invalid and will be "
105 "converted to NaN")
107 "converted to NaN")
106 .arg(line, valueIndex);
108 .arg(line, valueIndex);
107 value = std::numeric_limits<double>::quiet_NaN();
109 value = std::numeric_limits<double>::quiet_NaN();
108 }
110 }
109
111
110 // Handles fill value
112 // Handles fill value
111 if (!std::isnan(fillValue) && !std::isnan(value) && fillValue == value) {
113 if (!std::isnan(fillValue) && !std::isnan(value) && fillValue == value) {
112 value = std::numeric_limits<double>::quiet_NaN();
114 value = std::numeric_limits<double>::quiet_NaN();
113 }
115 }
114
116
115 valuesData.push_back(value);
117 valuesData.push_back(value);
116 }
118 }
117 }
119 }
118 else {
120 else {
119 qCWarning(LOG_AmdaResultParserHelper())
121 qCWarning(LOG_AmdaResultParserHelper())
120 << QObject::tr("Can't retrieve results from line %1: x is invalid").arg(line);
122 << QObject::tr("Can't retrieve results from line %1: x is invalid").arg(line);
121 }
123 }
122 }
124 }
123 else {
125 else {
124 qCWarning(LOG_AmdaResultParserHelper())
126 qCWarning(LOG_AmdaResultParserHelper())
125 << QObject::tr("Can't retrieve results from line %1: invalid line").arg(line);
127 << QObject::tr("Can't retrieve results from line %1: invalid line").arg(line);
126 }
128 }
127 }
129 }
128
130
129 /**
131 /**
130 * Reads a line from the AMDA file and tries to extract a property from it
132 * Reads a line from the AMDA file and tries to extract a property from it
131 * @param properties the properties map in which to put the property extracted from the line
133 * @param properties the properties map in which to put the property extracted from the line
132 * @param key the key to which the property is added in the properties map
134 * @param key the key to which the property is added in the properties map
133 * @param line the line to read to extract the property
135 * @param line the line to read to extract the property
134 * @param regex the expected regex to extract the property. If the line matches this regex, the
136 * @param regex the expected regex to extract the property. If the line matches this regex, the
135 * property is generated
137 * property is generated
136 * @param fun the function used to generate the property
138 * @param fun the function used to generate the property
137 * @return true if the property could be generated, false if the line does not match the regex, or
139 * @return true if the property could be generated, false if the line does not match the regex, or
138 * if a property has already been generated for the key
140 * if a property has already been generated for the key
139 */
141 */
140 template <typename GeneratePropertyFun>
142 template <typename GeneratePropertyFun>
141 bool tryReadProperty(Properties &properties, const QString &key, const QString &line,
143 bool tryReadProperty(Properties &properties, const QString &key, const QString &line,
142 const QRegularExpression &regex, GeneratePropertyFun fun)
144 const QRegularExpression &regex, GeneratePropertyFun fun)
143 {
145 {
144 if (properties.contains(key)) {
146 if (properties.contains(key)) {
145 return false;
147 return false;
146 }
148 }
147
149
148 auto match = regex.match(line);
150 auto match = regex.match(line);
149 if (match.hasMatch()) {
151 if (match.hasMatch()) {
150 properties.insert(key, fun(match));
152 properties.insert(key, fun(match));
151 }
153 }
152
154
153 return match.hasMatch();
155 return match.hasMatch();
154 }
156 }
155
157
156 /**
158 /**
157 * Reads a line from the AMDA file and tries to extract a double from it
159 * Reads a line from the AMDA file and tries to extract a double from it
158 * @sa tryReadProperty()
160 * @sa tryReadProperty()
159 */
161 */
160 bool tryReadDouble(Properties &properties, const QString &key, const QString &line,
162 bool tryReadDouble(Properties &properties, const QString &key, const QString &line,
161 const QRegularExpression &regex)
163 const QRegularExpression &regex)
162 {
164 {
163 return tryReadProperty(properties, key, line, regex, [](const auto &match) {
165 return tryReadProperty(properties, key, line, regex, [](const auto &match) {
164 bool ok;
166 bool ok;
165
167
166 // If the value can't be converted to double, it is set to NaN
168 // If the value can't be converted to double, it is set to NaN
167 auto doubleValue = match.captured(1).toDouble(&ok);
169 auto doubleValue = match.captured(1).toDouble(&ok);
168 if (!ok) {
170 if (!ok) {
169 doubleValue = std::numeric_limits<double>::quiet_NaN();
171 doubleValue = std::numeric_limits<double>::quiet_NaN();
170 }
172 }
171
173
172 return QVariant::fromValue(doubleValue);
174 return QVariant::fromValue(doubleValue);
173 });
175 });
174 }
176 }
175
177
176 /**
178 /**
177 * Reads a line from the AMDA file and tries to extract a vector of doubles from it
179 * Reads a line from the AMDA file and tries to extract a vector of doubles from it
178 * @param sep the separator of double values in the line
180 * @param sep the separator of double values in the line
179 * @sa tryReadProperty()
181 * @sa tryReadProperty()
180 */
182 */
181 bool tryReadDoubles(Properties &properties, const QString &key, const QString &line,
183 bool tryReadDoubles(Properties &properties, const QString &key, const QString &line,
182 const QRegularExpression &regex, const QString &sep = QStringLiteral(","))
184 const QRegularExpression &regex, const QString &sep = QStringLiteral(","))
183 {
185 {
184 return tryReadProperty(properties, key, line, regex, [sep](const auto &match) {
186 return tryReadProperty(properties, key, line, regex, [sep](const auto &match) {
185 std::vector<double> doubleValues{};
187 std::vector<double> doubleValues{};
186
188
187 // If the value can't be converted to double, it is set to NaN
189 // If the value can't be converted to double, it is set to NaN
188 auto values = match.captured(1).split(sep);
190 auto values = match.captured(1).split(sep);
189 for (auto value : values) {
191 for (auto value : values) {
190 bool ok;
192 bool ok;
191
193
192 auto doubleValue = value.toDouble(&ok);
194 auto doubleValue = value.toDouble(&ok);
193 if (!ok) {
195 if (!ok) {
194 doubleValue = std::numeric_limits<double>::quiet_NaN();
196 doubleValue = std::numeric_limits<double>::quiet_NaN();
195 }
197 }
196
198
197 doubleValues.push_back(doubleValue);
199 doubleValues.push_back(doubleValue);
198 }
200 }
199
201
200 return QVariant::fromValue(doubleValues);
202 return QVariant::fromValue(doubleValues);
201 });
203 });
202 }
204 }
203
205
204 /**
206 /**
205 * Reads a line from the AMDA file and tries to extract a unit from it
207 * Reads a line from the AMDA file and tries to extract a unit from it
206 * @sa tryReadProperty()
208 * @sa tryReadProperty()
207 */
209 */
208 bool tryReadUnit(Properties &properties, const QString &key, const QString &line,
210 bool tryReadUnit(Properties &properties, const QString &key, const QString &line,
209 const QRegularExpression &regex, bool timeUnit = false)
211 const QRegularExpression &regex, bool timeUnit = false)
210 {
212 {
211 return tryReadProperty(properties, key, line, regex, [timeUnit](const auto &match) {
213 return tryReadProperty(properties, key, line, regex, [timeUnit](const auto &match) {
212 return QVariant::fromValue(Unit{match.captured(1), timeUnit});
214 return QVariant::fromValue(Unit{match.captured(1), timeUnit});
213 });
215 });
214 }
216 }
215
217
216 } // namespace
218 } // namespace
217
219
218 // ////////////////// //
220 // ////////////////// //
219 // ScalarParserHelper //
221 // ScalarParserHelper //
220 // ////////////////// //
222 // ////////////////// //
221
223
222 bool ScalarParserHelper::checkProperties()
224 bool ScalarParserHelper::checkProperties()
223 {
225 {
224 return checkUnit(m_Properties, X_AXIS_UNIT_PROPERTY,
226 return checkUnit(m_Properties, X_AXIS_UNIT_PROPERTY,
225 QObject::tr("The x-axis unit could not be found in the file"));
227 QObject::tr("The x-axis unit could not be found in the file"));
226 }
228 }
227
229
228 std::shared_ptr<IDataSeries> ScalarParserHelper::createSeries()
230 std::shared_ptr<IDataSeries> ScalarParserHelper::createSeries()
229 {
231 {
230 return std::make_shared<ScalarSeries>(std::move(m_XAxisData), std::move(m_ValuesData),
232 return std::make_shared<ScalarSeries>(std::move(m_XAxisData), std::move(m_ValuesData),
231 m_Properties.value(X_AXIS_UNIT_PROPERTY).value<Unit>(),
233 m_Properties.value(X_AXIS_UNIT_PROPERTY).value<Unit>(),
232 m_Properties.value(VALUES_UNIT_PROPERTY).value<Unit>());
234 m_Properties.value(VALUES_UNIT_PROPERTY).value<Unit>());
233 }
235 }
234
236
235 void ScalarParserHelper::readPropertyLine(const QString &line)
237 void ScalarParserHelper::readPropertyLine(const QString &line)
236 {
238 {
237 tryReadUnit(m_Properties, X_AXIS_UNIT_PROPERTY, line, DEFAULT_X_AXIS_UNIT_REGEX, true);
239 tryReadUnit(m_Properties, X_AXIS_UNIT_PROPERTY, line, DEFAULT_X_AXIS_UNIT_REGEX, true);
238 }
240 }
239
241
240 void ScalarParserHelper::readResultLine(const QString &line)
242 void ScalarParserHelper::readResultLine(const QString &line)
241 {
243 {
242 tryReadResult(m_XAxisData, m_ValuesData, line, valuesIndexes());
244 tryReadResult(m_XAxisData, m_ValuesData, line, valuesIndexes());
243 }
245 }
244
246
245 std::vector<int> ScalarParserHelper::valuesIndexes() const
247 std::vector<int> ScalarParserHelper::valuesIndexes() const
246 {
248 {
247 // Only one value to read
249 // Only one value to read
248 static auto result = std::vector<int>{0};
250 static auto result = std::vector<int>{0};
249 return result;
251 return result;
250 }
252 }
251
253
252 // /////////////////////// //
254 // /////////////////////// //
253 // SpectrogramParserHelper //
255 // SpectrogramParserHelper //
254 // /////////////////////// //
256 // /////////////////////// //
255
257
256 bool SpectrogramParserHelper::checkProperties()
258 bool SpectrogramParserHelper::checkProperties()
257 {
259 {
258 // Generates y-axis data from bands extracted (take the middle of the intervals)
260 // Generates y-axis data from bands extracted (take the middle of the intervals)
259 auto minBands = m_Properties.value(MIN_BANDS_PROPERTY).value<std::vector<double> >();
261 auto minBands = m_Properties.value(MIN_BANDS_PROPERTY).value<std::vector<double> >();
260 auto maxBands = m_Properties.value(MAX_BANDS_PROPERTY).value<std::vector<double> >();
262 auto maxBands = m_Properties.value(MAX_BANDS_PROPERTY).value<std::vector<double> >();
261
263
262 if (minBands.size() != maxBands.size()) {
264 if (minBands.size() != maxBands.size()) {
263 qCWarning(LOG_AmdaResultParserHelper()) << QObject::tr(
265 qCWarning(LOG_AmdaResultParserHelper()) << QObject::tr(
264 "Can't generate y-axis data from bands extracted: bands intervals are invalid");
266 "Can't generate y-axis data from bands extracted: bands intervals are invalid");
265 return false;
267 return false;
266 }
268 }
267
269
268 std::transform(
270 std::transform(
269 minBands.begin(), minBands.end(), maxBands.begin(), std::back_inserter(m_YAxisData),
271 minBands.begin(), minBands.end(), maxBands.begin(), std::back_inserter(m_YAxisData),
270 [](const auto &minValue, const auto &maxValue) { return (minValue + maxValue) / 2.; });
272 [](const auto &minValue, const auto &maxValue) { return (minValue + maxValue) / 2.; });
271
273
274 // Generates values indexes, i.e. the order in which each value will be retrieved (in ascending
275 // order of the associated bands)
276 m_ValuesIndexes = SortUtils::sortPermutation(m_YAxisData, std::less<double>());
277
278 // Sorts y-axis data accoding to the ascending order
279 m_YAxisData = SortUtils::sort(m_YAxisData, 1, m_ValuesIndexes);
280
281 // Sets fill value
282 m_FillValue = m_Properties.value(FILL_VALUE_PROPERTY).value<double>();
283
284 /// @todo: handle min/max samplings?
285
272 return true;
286 return true;
273 }
287 }
274
288
275 std::shared_ptr<IDataSeries> SpectrogramParserHelper::createSeries()
289 std::shared_ptr<IDataSeries> SpectrogramParserHelper::createSeries()
276 {
290 {
277 /// @todo ALX
291 return std::make_shared<SpectrogramSeries>(
292 std::move(m_XAxisData), std::move(m_YAxisData), std::move(m_ValuesData),
293 Unit{"t", true}, // x-axis unit is always a time unit
294 m_Properties.value(Y_AXIS_UNIT_PROPERTY).value<Unit>(),
295 m_Properties.value(VALUES_UNIT_PROPERTY).value<Unit>());
278 }
296 }
279
297
280 void SpectrogramParserHelper::readPropertyLine(const QString &line)
298 void SpectrogramParserHelper::readPropertyLine(const QString &line)
281 {
299 {
282 // Set of functions to test on the line to generate a property. If a function is valid (i.e. a
300 // Set of functions to test on the line to generate a property. If a function is valid (i.e. a
283 // property has been generated for the line), the line is treated as processed and the other
301 // property has been generated for the line), the line is treated as processed and the other
284 // functions are not called
302 // functions are not called
285 std::vector<std::function<bool()> > functions{
303 std::vector<std::function<bool()> > functions{
286 // values unit
304 // values unit
287 [&] {
305 [&] {
288 return tryReadUnit(m_Properties, VALUES_UNIT_PROPERTY, line,
306 return tryReadUnit(m_Properties, VALUES_UNIT_PROPERTY, line,
289 SPECTROGRAM_VALUES_UNIT_REGEX);
307 SPECTROGRAM_VALUES_UNIT_REGEX);
290 },
308 },
291 // y-axis unit
309 // y-axis unit
292 [&] {
310 [&] {
293 return tryReadUnit(m_Properties, Y_AXIS_UNIT_PROPERTY, line,
311 return tryReadUnit(m_Properties, Y_AXIS_UNIT_PROPERTY, line,
294 SPECTROGRAM_Y_AXIS_UNIT_REGEX);
312 SPECTROGRAM_Y_AXIS_UNIT_REGEX);
295 },
313 },
296 // min sampling
314 // min sampling
297 [&] {
315 [&] {
298 return tryReadDouble(m_Properties, MIN_SAMPLING_PROPERTY, line,
316 return tryReadDouble(m_Properties, MIN_SAMPLING_PROPERTY, line,
299 SPECTROGRAM_MIN_SAMPLING_REGEX);
317 SPECTROGRAM_MIN_SAMPLING_REGEX);
300 },
318 },
301 // max sampling
319 // max sampling
302 [&] {
320 [&] {
303 return tryReadDouble(m_Properties, MAX_SAMPLING_PROPERTY, line,
321 return tryReadDouble(m_Properties, MAX_SAMPLING_PROPERTY, line,
304 SPECTROGRAM_MAX_SAMPLING_REGEX);
322 SPECTROGRAM_MAX_SAMPLING_REGEX);
305 },
323 },
306 // fill value
324 // fill value
307 [&] {
325 [&] {
308 return tryReadDouble(m_Properties, FILL_VALUE_PROPERTY, line,
326 return tryReadDouble(m_Properties, FILL_VALUE_PROPERTY, line,
309 SPECTROGRAM_FILL_VALUE_REGEX);
327 SPECTROGRAM_FILL_VALUE_REGEX);
310 },
328 },
311 // min bounds of each band
329 // min bounds of each band
312 [&] {
330 [&] {
313 return tryReadDoubles(m_Properties, MIN_BANDS_PROPERTY, line,
331 return tryReadDoubles(m_Properties, MIN_BANDS_PROPERTY, line,
314 SPECTROGRAM_MIN_BANDS_REGEX);
332 SPECTROGRAM_MIN_BANDS_REGEX);
315 },
333 },
316 // max bounds of each band
334 // max bounds of each band
317 [&] {
335 [&] {
318 return tryReadDoubles(m_Properties, MAX_BANDS_PROPERTY, line,
336 return tryReadDoubles(m_Properties, MAX_BANDS_PROPERTY, line,
319 SPECTROGRAM_MAX_BANDS_REGEX);
337 SPECTROGRAM_MAX_BANDS_REGEX);
320 }};
338 }};
321
339
322 for (auto function : functions) {
340 for (auto function : functions) {
323 // Stops at the first function that is valid
341 // Stops at the first function that is valid
324 if (function()) {
342 if (function()) {
325 return;
343 return;
326 }
344 }
327 }
345 }
328 }
346 }
329
347
330 void SpectrogramParserHelper::readResultLine(const QString &line)
348 void SpectrogramParserHelper::readResultLine(const QString &line)
331 {
349 {
332 /// @todo ALX
350 tryReadResult(m_XAxisData, m_ValuesData, line, m_ValuesIndexes, m_FillValue);
333 }
351 }
334
352
335 // ////////////////// //
353 // ////////////////// //
336 // VectorParserHelper //
354 // VectorParserHelper //
337 // ////////////////// //
355 // ////////////////// //
338
356
339 bool VectorParserHelper::checkProperties()
357 bool VectorParserHelper::checkProperties()
340 {
358 {
341 return checkUnit(m_Properties, X_AXIS_UNIT_PROPERTY,
359 return checkUnit(m_Properties, X_AXIS_UNIT_PROPERTY,
342 QObject::tr("The x-axis unit could not be found in the file"));
360 QObject::tr("The x-axis unit could not be found in the file"));
343 }
361 }
344
362
345 std::shared_ptr<IDataSeries> VectorParserHelper::createSeries()
363 std::shared_ptr<IDataSeries> VectorParserHelper::createSeries()
346 {
364 {
347 return std::make_shared<VectorSeries>(std::move(m_XAxisData), std::move(m_ValuesData),
365 return std::make_shared<VectorSeries>(std::move(m_XAxisData), std::move(m_ValuesData),
348 m_Properties.value(X_AXIS_UNIT_PROPERTY).value<Unit>(),
366 m_Properties.value(X_AXIS_UNIT_PROPERTY).value<Unit>(),
349 m_Properties.value(VALUES_UNIT_PROPERTY).value<Unit>());
367 m_Properties.value(VALUES_UNIT_PROPERTY).value<Unit>());
350 }
368 }
351
369
352 void VectorParserHelper::readPropertyLine(const QString &line)
370 void VectorParserHelper::readPropertyLine(const QString &line)
353 {
371 {
354 tryReadUnit(m_Properties, X_AXIS_UNIT_PROPERTY, line, DEFAULT_X_AXIS_UNIT_REGEX, true);
372 tryReadUnit(m_Properties, X_AXIS_UNIT_PROPERTY, line, DEFAULT_X_AXIS_UNIT_REGEX, true);
355 }
373 }
356
374
357 void VectorParserHelper::readResultLine(const QString &line)
375 void VectorParserHelper::readResultLine(const QString &line)
358 {
376 {
359 tryReadResult(m_XAxisData, m_ValuesData, line, valuesIndexes());
377 tryReadResult(m_XAxisData, m_ValuesData, line, valuesIndexes());
360 }
378 }
361
379
362 std::vector<int> VectorParserHelper::valuesIndexes() const
380 std::vector<int> VectorParserHelper::valuesIndexes() const
363 {
381 {
364 // 3 values to read, in order in the file (x, y, z)
382 // 3 values to read, in order in the file (x, y, z)
365 static auto result = std::vector<int>{0, 1, 2};
383 static auto result = std::vector<int>{0, 1, 2};
366 return result;
384 return result;
367 }
385 }
General Comments 0
You need to be logged in to leave comments. Login now