##// END OF EJS Templates
Improves AMDA result parsing...
Alexandre Leroux -
r492:41e897ecff03
parent child
Show More
@@ -1,147 +1,152
1 #include "AmdaResultParser.h"
1 #include "AmdaResultParser.h"
2
2
3 #include <Common/DateUtils.h>
3 #include <Common/DateUtils.h>
4 #include <Data/ScalarSeries.h>
4 #include <Data/ScalarSeries.h>
5
5
6 #include <QDateTime>
6 #include <QDateTime>
7 #include <QFile>
7 #include <QFile>
8 #include <QRegularExpression>
8 #include <QRegularExpression>
9
9
10 #include <cmath>
10 #include <cmath>
11
11
12 Q_LOGGING_CATEGORY(LOG_AmdaResultParser, "AmdaResultParser")
12 Q_LOGGING_CATEGORY(LOG_AmdaResultParser, "AmdaResultParser")
13
13
14 namespace {
14 namespace {
15
15
16 /// Message in result file when the file was not found on server
16 /// Message in result file when the file was not found on server
17 const auto FILE_NOT_FOUND_MESSAGE = QStringLiteral("Not Found");
17 const auto FILE_NOT_FOUND_MESSAGE = QStringLiteral("Not Found");
18
18
19 /// Format for dates in result files
19 /// Format for dates in result files
20 const auto DATE_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss.zzz");
20 const auto DATE_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss.zzz");
21
21
22 /// Separator between values in a result line
22 /// Separator between values in a result line
23 const auto RESULT_LINE_SEPARATOR = QRegularExpression{QStringLiteral("\\s+")};
23 const auto RESULT_LINE_SEPARATOR = QRegularExpression{QStringLiteral("\\s+")};
24
24
25 /// Regex to find unit in a line. Examples of valid lines:
25 /// Regex to find unit in a line. Examples of valid lines:
26 /// ... - Units : nT - ...
26 /// ... - Units : nT - ...
27 /// ... -Units:nT- ...
27 /// ... -Units:nT- ...
28 /// ... -Units: mΒ²- ...
28 /// ... -Units: mΒ²- ...
29 /// ... - Units : m/s - ...
29 /// ... - Units : m/s - ...
30 const auto UNIT_REGEX = QRegularExpression{QStringLiteral("-\\s*Units\\s*:\\s*(.+?)\\s*-")};
30 const auto UNIT_REGEX = QRegularExpression{QStringLiteral("-\\s*Units\\s*:\\s*(.+?)\\s*-")};
31
31
32 /// Converts a string date to a double date
32 /// Converts a string date to a double date
33 /// @return a double that represents the date in seconds, NaN if the string date can't be converted
33 /// @return a double that represents the date in seconds, NaN if the string date can't be converted
34 double doubleDate(const QString &stringDate) noexcept
34 double doubleDate(const QString &stringDate) noexcept
35 {
35 {
36 auto dateTime = QDateTime::fromString(stringDate, DATE_FORMAT);
36 auto dateTime = QDateTime::fromString(stringDate, DATE_FORMAT);
37 dateTime.setTimeSpec(Qt::UTC);
37 dateTime.setTimeSpec(Qt::UTC);
38 return dateTime.isValid() ? DateUtils::secondsSinceEpoch(dateTime)
38 return dateTime.isValid() ? DateUtils::secondsSinceEpoch(dateTime)
39 : std::numeric_limits<double>::quiet_NaN();
39 : std::numeric_limits<double>::quiet_NaN();
40 }
40 }
41
41
42 /// Checks if a line is a comment line
43 bool isCommentLine(const QString &line)
44 {
45 return line.startsWith("#");
46 }
47
42 /**
48 /**
43 * Reads stream to retrieve x-axis unit
49 * Reads stream to retrieve x-axis unit
44 * @param stream the stream to read
50 * @param stream the stream to read
45 * @return the unit that has been read in the stream, a default unit (time unit with no label) if an
51 * @return the unit that has been read in the stream, a default unit (time unit with no label) if an
46 * error occured during reading
52 * error occured during reading
47 */
53 */
48 Unit readXAxisUnit(QTextStream &stream)
54 Unit readXAxisUnit(QTextStream &stream)
49 {
55 {
50 QString line{};
56 QString line{};
51
57
52 if (stream.readLineInto(&line)) {
58 // Searches unit in the comment lines
59 while (stream.readLineInto(&line) && isCommentLine(line)) {
53 auto match = UNIT_REGEX.match(line);
60 auto match = UNIT_REGEX.match(line);
54 if (match.hasMatch()) {
61 if (match.hasMatch()) {
55 return Unit{match.captured(1), true};
62 return Unit{match.captured(1), true};
56 }
63 }
57 else {
58 qCWarning(LOG_AmdaResultParser())
59 << QObject::tr("Can't read unit: invalid line %1").arg(line);
60 }
61 }
62 else {
63 qCWarning(LOG_AmdaResultParser()) << QObject::tr("Can't read unit: end of file");
64 }
64 }
65
65
66 qCWarning(LOG_AmdaResultParser()) << QObject::tr("The unit could not be found in the file");
67
66 // Error cases
68 // Error cases
67 return Unit{{}, true};
69 return Unit{{}, true};
68 }
70 }
69
71
70 /**
72 /**
71 * Reads stream to retrieve results
73 * Reads stream to retrieve results
72 * @param stream the stream to read
74 * @param stream the stream to read
73 * @return the pair of vectors x-axis data/values data that has been read in the stream
75 * @return the pair of vectors x-axis data/values data that has been read in the stream
74 */
76 */
75 QPair<QVector<double>, QVector<double> > readResults(QTextStream &stream)
77 QPair<QVector<double>, QVector<double> > readResults(QTextStream &stream)
76 {
78 {
77 auto xData = QVector<double>{};
79 auto xData = QVector<double>{};
78 auto valuesData = QVector<double>{};
80 auto valuesData = QVector<double>{};
79
81
80 QString line{};
82 QString line{};
83
81 while (stream.readLineInto(&line)) {
84 while (stream.readLineInto(&line)) {
82 auto lineData = line.split(RESULT_LINE_SEPARATOR, QString::SkipEmptyParts);
85 // Ignore comment lines
83 if (lineData.size() == 2) {
86 if (!isCommentLine(line)) {
84 // X : the data is converted from date to double (in secs)
87 auto lineData = line.split(RESULT_LINE_SEPARATOR, QString::SkipEmptyParts);
85 auto x = doubleDate(lineData.at(0));
88 if (lineData.size() == 2) {
86
89 // X : the data is converted from date to double (in secs)
87 // Value
90 auto x = doubleDate(lineData.at(0));
88 bool valueOk;
91
89 auto value = lineData.at(1).toDouble(&valueOk);
92 // Value
90
93 bool valueOk;
91 // Adds result only if x and value are valid
94 auto value = lineData.at(1).toDouble(&valueOk);
92 if (!std::isnan(x) && !std::isnan(value) && valueOk) {
95
93 xData.push_back(x);
96 // Adds result only if x and value are valid
94 valuesData.push_back(value);
97 if (!std::isnan(x) && !std::isnan(value) && valueOk) {
98 xData.push_back(x);
99 valuesData.push_back(value);
100 }
101 else {
102 qCWarning(LOG_AmdaResultParser())
103 << QObject::tr(
104 "Can't retrieve results from line %1: x and/or value are invalid")
105 .arg(line);
106 }
95 }
107 }
96 else {
108 else {
97 qCWarning(LOG_AmdaResultParser())
109 qCWarning(LOG_AmdaResultParser())
98 << QObject::tr(
110 << QObject::tr("Can't retrieve results from line %1: invalid line").arg(line);
99 "Can't retrieve results from line %1: x and/or value are invalid")
100 .arg(line);
101 }
111 }
102 }
112 }
103 else {
104 qCWarning(LOG_AmdaResultParser())
105 << QObject::tr("Can't retrieve results from line %1: invalid line").arg(line);
106 }
107 }
113 }
108
114
109 return qMakePair(std::move(xData), std::move(valuesData));
115 return qMakePair(std::move(xData), std::move(valuesData));
110 }
116 }
111
117
112 } // namespace
118 } // namespace
113
119
114 std::shared_ptr<IDataSeries> AmdaResultParser::readTxt(const QString &filePath) noexcept
120 std::shared_ptr<IDataSeries> AmdaResultParser::readTxt(const QString &filePath) noexcept
115 {
121 {
116 QFile file{filePath};
122 QFile file{filePath};
117
123
118 if (!file.open(QFile::ReadOnly | QIODevice::Text)) {
124 if (!file.open(QFile::ReadOnly | QIODevice::Text)) {
119 qCCritical(LOG_AmdaResultParser())
125 qCCritical(LOG_AmdaResultParser())
120 << QObject::tr("Can't retrieve AMDA data from file %1: %2")
126 << QObject::tr("Can't retrieve AMDA data from file %1: %2")
121 .arg(filePath, file.errorString());
127 .arg(filePath, file.errorString());
122 return nullptr;
128 return nullptr;
123 }
129 }
124
130
125 QTextStream stream{&file};
131 QTextStream stream{&file};
126
132
127 // Checks if the file was found on the server
133 // Checks if the file was found on the server
128 auto firstLine = stream.readLine();
134 auto firstLine = stream.readLine();
129 if (firstLine.compare(FILE_NOT_FOUND_MESSAGE) == 0) {
135 if (firstLine.compare(FILE_NOT_FOUND_MESSAGE) == 0) {
130 qCCritical(LOG_AmdaResultParser())
136 qCCritical(LOG_AmdaResultParser())
131 << QObject::tr("Can't retrieve AMDA data from file %1: file was not found on server")
137 << QObject::tr("Can't retrieve AMDA data from file %1: file was not found on server")
132 .arg(filePath);
138 .arg(filePath);
133 return nullptr;
139 return nullptr;
134 }
140 }
135
141
136 // Ignore comments lines
137 stream.readLine();
138
139 // Reads x-axis unit
142 // Reads x-axis unit
143 stream.seek(0); // returns to the beginning of the file
140 auto xAxisUnit = readXAxisUnit(stream);
144 auto xAxisUnit = readXAxisUnit(stream);
141
145
142 // Reads results
146 // Reads results
147 stream.seek(0); // returns to the beginning of the file
143 auto results = readResults(stream);
148 auto results = readResults(stream);
144
149
145 return std::make_shared<ScalarSeries>(std::move(results.first), std::move(results.second),
150 return std::make_shared<ScalarSeries>(std::move(results.first), std::move(results.second),
146 xAxisUnit, Unit{});
151 xAxisUnit, Unit{});
147 }
152 }
General Comments 0
You need to be logged in to leave comments. Login now