##// END OF EJS Templates
Parser refactoring (5)...
Alexandre Leroux -
r948:64a6137ab3a2
parent child
Show More
@@ -19,6 +19,11 extern const QString X_AXIS_UNIT_PROPERTY;
19 19 // /////////////////// //
20 20
21 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 27 // /// ... PARAMETER_UNITS : nT ...
23 28 // /// ... PARAMETER_UNITS:nT ...
24 29 // /// ... PARAMETER_UNITS: mΒ² ...
@@ -1,12 +1,8
1 1 #include "AmdaResultParser.h"
2 2
3 #include <Common/DateUtils.h>
4 #include <Data/ScalarSeries.h>
5 #include <Data/VectorSeries.h>
3 #include "AmdaResultParserHelper.h"
6 4
7 #include <QDateTime>
8 5 #include <QFile>
9 #include <QRegularExpression>
10 6
11 7 #include <cmath>
12 8
@@ -17,66 +13,24 namespace {
17 13 /// Message in result file when the file was not found on server
18 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 16 /// Checks if a line is a comment line
67 17 bool isCommentLine(const QString &line)
68 18 {
69 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
73 int nbValues(AmdaResultParser::ValueType valueType) noexcept
22 /**
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 29 switch (valueType) {
76 30 case AmdaResultParser::ValueType::SCALAR:
77 return 1;
31 return std::make_unique<ScalarParserHelper>();
78 32 case AmdaResultParser::ValueType::VECTOR:
79 return 3;
33 return std::make_unique<VectorParserHelper>();
80 34 case AmdaResultParser::ValueType::UNKNOWN:
81 35 // Invalid case
82 36 break;
@@ -84,48 +38,32 int nbValues(AmdaResultParser::ValueType valueType) noexcept
84 38
85 39 // Invalid cases
86 40 qCCritical(LOG_AmdaResultParser())
87 << QObject::tr("Can't get the number of values to read: unsupported type");
88 return 0;
41 << QObject::tr("Can't create helper to read result file: unsupported type");
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 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{};
100
101 // Searches unit in the comment lines (as long as the reading has not reached the data header)
52 // Searches properties in the comment lines (as long as the reading has not reached the data)
102 53 // AMDA V2: while (stream.readLineInto(&line) && !line.contains(DATA_HEADER_REGEX)) {
54 QString line{};
103 55 while (stream.readLineInto(&line) && isCommentLine(line)) {
104 auto match = UNIT_REGEX.match(line);
105 if (match.hasMatch()) {
106 return Unit{match.captured(1), true};
107 }
56 helper.readPropertyLine(line);
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 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> >
122 readResults(QTextStream &stream, AmdaResultParser::ValueType valueType)
65 void readResults(IAmdaResultParserHelper &helper, QTextStream &stream)
123 66 {
124 auto expectedNbValues = nbValues(valueType) + 1;
125
126 auto xData = std::vector<double>{};
127 auto valuesData = std::vector<double>{};
128
129 67 QString line{};
130 68
131 69 // Skip comment lines
@@ -134,47 +72,9 readResults(QTextStream &stream, AmdaResultParser::ValueType valueType)
134 72
135 73 if (!stream.atEnd()) {
136 74 do {
137 auto lineData = line.split(RESULT_LINE_SEPARATOR, QString::SkipEmptyParts);
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 }
75 helper.readResultLine(line);
174 76 } while (stream.readLineInto(&line));
175 77 }
176
177 return std::make_pair(std::move(xData), std::move(valuesData));
178 78 }
179 79
180 80 } // namespace
@@ -208,33 +108,24 std::shared_ptr<IDataSeries> AmdaResultParser::readTxt(const QString &filePath,
208 108 return nullptr;
209 109 }
210 110
211 // Reads x-axis unit
111 auto helper = createHelper(valueType);
112 Q_ASSERT(helper != nullptr);
113
114 // Reads header file to retrieve properties
212 115 stream.seek(0); // returns to the beginning of the file
213 auto xAxisUnit = readXAxisUnit(stream);
214 if (xAxisUnit.m_Name.isEmpty()) {
215 return nullptr;
216 }
116 readProperties(*helper, stream);
217 117
118 // Checks properties
119 if (helper->checkProperties()) {
218 120 // Reads results
219 121 // AMDA V2: remove line
220 122 stream.seek(0); // returns to the beginning of the file
221 auto results = readResults(stream, valueType);
123 readResults(*helper, stream);
222 124
223 125 // Creates data series
224 switch (valueType) {
225 case ValueType::SCALAR:
226 return std::make_shared<ScalarSeries>(std::move(results.first),
227 std::move(results.second), xAxisUnit, Unit{});
228 case ValueType::VECTOR:
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;
126 return helper->createSeries();
234 127 }
235
236 // Invalid cases
237 qCCritical(LOG_AmdaResultParser())
238 << QObject::tr("Can't create data series: unsupported value type");
128 else {
239 129 return nullptr;
240 130 }
131 }
General Comments 0
You need to be logged in to leave comments. Login now