##// END OF EJS Templates
Parser refactoring (5)...
Alexandre Leroux -
r989:64a6137ab3a2
parent child
Show More
@@ -19,6 +19,11 extern const QString X_AXIS_UNIT_PROPERTY;
19 // /////////////////// //
19 // /////////////////// //
20
20
21 // AMDA V2
21 // AMDA V2
22 // /// Regex to find the header of the data in the file. This header indicates the end of comments
23 // in the file
24 // const auto DATA_HEADER_REGEX = QRegularExpression{QStringLiteral("#\\s*DATA\\s*:")};
25
26 // AMDA V2
22 // /// ... PARAMETER_UNITS : nT ...
27 // /// ... PARAMETER_UNITS : nT ...
23 // /// ... PARAMETER_UNITS:nT ...
28 // /// ... PARAMETER_UNITS:nT ...
24 // /// ... PARAMETER_UNITS: mΒ² ...
29 // /// ... PARAMETER_UNITS: mΒ² ...
@@ -1,12 +1,8
1 #include "AmdaResultParser.h"
1 #include "AmdaResultParser.h"
2
2
3 #include <Common/DateUtils.h>
3 #include "AmdaResultParserHelper.h"
4 #include <Data/ScalarSeries.h>
5 #include <Data/VectorSeries.h>
6
4
7 #include <QDateTime>
8 #include <QFile>
5 #include <QFile>
9 #include <QRegularExpression>
10
6
11 #include <cmath>
7 #include <cmath>
12
8
@@ -17,66 +13,24 namespace {
17 /// Message in result file when the file was not found on server
13 /// Message in result file when the file was not found on server
18 const auto FILE_NOT_FOUND_MESSAGE = QStringLiteral("Not Found");
14 const auto FILE_NOT_FOUND_MESSAGE = QStringLiteral("Not Found");
19
15
20 /// Separator between values in a result line
21 const auto RESULT_LINE_SEPARATOR = QRegularExpression{QStringLiteral("\\s+")};
22
23 // AMDA V2
24 // /// Regex to find the header of the data in the file. This header indicates the end of comments
25 // in
26 // /// the file
27 // const auto DATA_HEADER_REGEX = QRegularExpression{QStringLiteral("#\\s*DATA\\s*:")};
28
29 /// Format for dates in result files
30 const auto DATE_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss.zzz");
31
32 // AMDA V2
33 // /// Regex to find unit in a line. Examples of valid lines:
34 // /// ... PARAMETER_UNITS : nT ...
35 // /// ... PARAMETER_UNITS:nT ...
36 // /// ... PARAMETER_UNITS: mΒ² ...
37 // /// ... PARAMETER_UNITS : m/s ...
38 // const auto UNIT_REGEX = QRegularExpression{QStringLiteral("\\s*PARAMETER_UNITS\\s*:\\s*(.+)")};
39
40 /// ... - Units : nT - ...
41 /// ... -Units:nT- ...
42 /// ... -Units: mΒ²- ...
43 /// ... - Units : m/s - ...
44 const auto UNIT_REGEX = QRegularExpression{QStringLiteral("-\\s*Units\\s*:\\s*(.+?)\\s*-")};
45
46 QDateTime dateTimeFromString(const QString &stringDate) noexcept
47 {
48 #if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
49 return QDateTime::fromString(stringDate, Qt::ISODateWithMs);
50 #else
51 return QDateTime::fromString(stringDate, DATE_FORMAT);
52 #endif
53 }
54
55 /// Converts a string date to a double date
56 /// @return a double that represents the date in seconds, NaN if the string date can't be converted
57 double doubleDate(const QString &stringDate) noexcept
58 {
59 // Format: yyyy-MM-ddThh:mm:ss.zzz
60 auto dateTime = dateTimeFromString(stringDate);
61 dateTime.setTimeSpec(Qt::UTC);
62 return dateTime.isValid() ? DateUtils::secondsSinceEpoch(dateTime)
63 : std::numeric_limits<double>::quiet_NaN();
64 }
65
66 /// Checks if a line is a comment line
16 /// Checks if a line is a comment line
67 bool isCommentLine(const QString &line)
17 bool isCommentLine(const QString &line)
68 {
18 {
69 return line.startsWith("#");
19 return line.startsWith("#");
70 }
20 }
71
21
72 /// @return the number of lines to be read depending on the type of value passed in parameter
22 /**
73 int nbValues(AmdaResultParser::ValueType valueType) noexcept
23 * Creates helper that will be used to read AMDA file, according to the type passed as parameter
24 * @param valueType the type of values expected in the AMDA file (scalars, vectors, spectrograms...)
25 * @return the helper created
26 */
27 std::unique_ptr<IAmdaResultParserHelper> createHelper(AmdaResultParser::ValueType valueType)
74 {
28 {
75 switch (valueType) {
29 switch (valueType) {
76 case AmdaResultParser::ValueType::SCALAR:
30 case AmdaResultParser::ValueType::SCALAR:
77 return 1;
31 return std::make_unique<ScalarParserHelper>();
78 case AmdaResultParser::ValueType::VECTOR:
32 case AmdaResultParser::ValueType::VECTOR:
79 return 3;
33 return std::make_unique<VectorParserHelper>();
80 case AmdaResultParser::ValueType::UNKNOWN:
34 case AmdaResultParser::ValueType::UNKNOWN:
81 // Invalid case
35 // Invalid case
82 break;
36 break;
@@ -84,48 +38,32 int nbValues(AmdaResultParser::ValueType valueType) noexcept
84
38
85 // Invalid cases
39 // Invalid cases
86 qCCritical(LOG_AmdaResultParser())
40 qCCritical(LOG_AmdaResultParser())
87 << QObject::tr("Can't get the number of values to read: unsupported type");
41 << QObject::tr("Can't create helper to read result file: unsupported type");
88 return 0;
42 return nullptr;
89 }
43 }
90
44
91 /**
45 /**
92 * Reads stream to retrieve x-axis unit
46 * Reads properties of the stream passed as parameter
47 * @param helper the helper used to read properties line by line
93 * @param stream the stream to read
48 * @param stream the stream to read
94 * @return the unit that has been read in the stream, a default unit (time unit with no label) if an
95 * error occured during reading
96 */
49 */
97 Unit readXAxisUnit(QTextStream &stream)
50 void readProperties(IAmdaResultParserHelper &helper, QTextStream &stream)
98 {
51 {
99 QString line{};
52 // Searches properties in the comment lines (as long as the reading has not reached the data)
100
101 // Searches unit in the comment lines (as long as the reading has not reached the data header)
102 // AMDA V2: while (stream.readLineInto(&line) && !line.contains(DATA_HEADER_REGEX)) {
53 // AMDA V2: while (stream.readLineInto(&line) && !line.contains(DATA_HEADER_REGEX)) {
54 QString line{};
103 while (stream.readLineInto(&line) && isCommentLine(line)) {
55 while (stream.readLineInto(&line) && isCommentLine(line)) {
104 auto match = UNIT_REGEX.match(line);
56 helper.readPropertyLine(line);
105 if (match.hasMatch()) {
106 return Unit{match.captured(1), true};
107 }
108 }
57 }
109
110 qCWarning(LOG_AmdaResultParser()) << QObject::tr("The unit could not be found in the file");
111
112 // Error cases
113 return Unit{{}, true};
114 }
58 }
115
59
116 /**
60 /**
117 * Reads stream to retrieve results
61 * Reads results of the stream passed as parameter
62 * @param helper the helper used to read results line by line
118 * @param stream the stream to read
63 * @param stream the stream to read
119 * @return the pair of vectors x-axis data/values data that has been read in the stream
120 */
64 */
121 std::pair<std::vector<double>, std::vector<double> >
65 void readResults(IAmdaResultParserHelper &helper, QTextStream &stream)
122 readResults(QTextStream &stream, AmdaResultParser::ValueType valueType)
123 {
66 {
124 auto expectedNbValues = nbValues(valueType) + 1;
125
126 auto xData = std::vector<double>{};
127 auto valuesData = std::vector<double>{};
128
129 QString line{};
67 QString line{};
130
68
131 // Skip comment lines
69 // Skip comment lines
@@ -134,47 +72,9 readResults(QTextStream &stream, AmdaResultParser::ValueType valueType)
134
72
135 if (!stream.atEnd()) {
73 if (!stream.atEnd()) {
136 do {
74 do {
137 auto lineData = line.split(RESULT_LINE_SEPARATOR, QString::SkipEmptyParts);
75 helper.readResultLine(line);
138 if (lineData.size() == expectedNbValues) {
139 // X : the data is converted from date to double (in secs)
140 auto x = doubleDate(lineData.at(0));
141
142 // Adds result only if x is valid. Then, if value is invalid, it is set to NaN
143 if (!std::isnan(x)) {
144 xData.push_back(x);
145
146 // Values
147 for (auto valueIndex = 1; valueIndex < expectedNbValues; ++valueIndex) {
148 auto column = valueIndex;
149
150 bool valueOk;
151 auto value = lineData.at(column).toDouble(&valueOk);
152
153 if (!valueOk) {
154 qCWarning(LOG_AmdaResultParser())
155 << QObject::tr(
156 "Value from (line %1, column %2) is invalid and will be "
157 "converted to NaN")
158 .arg(line, column);
159 value = std::numeric_limits<double>::quiet_NaN();
160 }
161 valuesData.push_back(value);
162 }
163 }
164 else {
165 qCWarning(LOG_AmdaResultParser())
166 << QObject::tr("Can't retrieve results from line %1: x is invalid")
167 .arg(line);
168 }
169 }
170 else {
171 qCWarning(LOG_AmdaResultParser())
172 << QObject::tr("Can't retrieve results from line %1: invalid line").arg(line);
173 }
174 } while (stream.readLineInto(&line));
76 } while (stream.readLineInto(&line));
175 }
77 }
176
177 return std::make_pair(std::move(xData), std::move(valuesData));
178 }
78 }
179
79
180 } // namespace
80 } // namespace
@@ -208,33 +108,24 std::shared_ptr<IDataSeries> AmdaResultParser::readTxt(const QString &filePath,
208 return nullptr;
108 return nullptr;
209 }
109 }
210
110
211 // Reads x-axis unit
111 auto helper = createHelper(valueType);
212 stream.seek(0); // returns to the beginning of the file
112 Q_ASSERT(helper != nullptr);
213 auto xAxisUnit = readXAxisUnit(stream);
214 if (xAxisUnit.m_Name.isEmpty()) {
215 return nullptr;
216 }
217
113
218 // Reads results
114 // Reads header file to retrieve properties
219 // AMDA V2: remove line
220 stream.seek(0); // returns to the beginning of the file
115 stream.seek(0); // returns to the beginning of the file
221 auto results = readResults(stream, valueType);
116 readProperties(*helper, stream);
222
117
223 // Creates data series
118 // Checks properties
224 switch (valueType) {
119 if (helper->checkProperties()) {
225 case ValueType::SCALAR:
120 // Reads results
226 return std::make_shared<ScalarSeries>(std::move(results.first),
121 // AMDA V2: remove line
227 std::move(results.second), xAxisUnit, Unit{});
122 stream.seek(0); // returns to the beginning of the file
228 case ValueType::VECTOR:
123 readResults(*helper, stream);
229 return std::make_shared<VectorSeries>(std::move(results.first),
230 std::move(results.second), xAxisUnit, Unit{});
231 case ValueType::UNKNOWN:
232 // Invalid case
233 break;
234 }
235
124
236 // Invalid cases
125 // Creates data series
237 qCCritical(LOG_AmdaResultParser())
126 return helper->createSeries();
238 << QObject::tr("Can't create data series: unsupported value type");
127 }
239 return nullptr;
128 else {
129 return nullptr;
130 }
240 }
131 }
General Comments 0
You need to be logged in to leave comments. Login now