##// END OF EJS Templates
Creates enum that represents the value types that can be read in AMDA...
Alexandre Leroux -
r563:a08e6992e146
parent child
Show More
@@ -1,19 +1,21
1 #ifndef SCIQLOP_AMDARESULTPARSER_H
1 #ifndef SCIQLOP_AMDARESULTPARSER_H
2 #define SCIQLOP_AMDARESULTPARSER_H
2 #define SCIQLOP_AMDARESULTPARSER_H
3
3
4 #include "AmdaGlobal.h"
4 #include "AmdaGlobal.h"
5
5
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7
7
8 #include <memory>
8 #include <memory>
9
9
10 class IDataSeries;
10 class IDataSeries;
11
11
12 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaResultParser)
12 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaResultParser)
13
13
14 struct SCIQLOP_AMDA_EXPORT AmdaResultParser {
14 struct SCIQLOP_AMDA_EXPORT AmdaResultParser {
15 enum class ValueType { SCALAR, VECTOR, UNKNOWN };
15
16
16 static std::shared_ptr<IDataSeries> readTxt(const QString &filePath) noexcept;
17 static std::shared_ptr<IDataSeries> readTxt(const QString &filePath,
18 ValueType valueType) noexcept;
17 };
19 };
18
20
19 #endif // SCIQLOP_AMDARESULTPARSER_H
21 #endif // SCIQLOP_AMDARESULTPARSER_H
@@ -1,160 +1,167
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
42 /// Checks if a line is a comment line
43 bool isCommentLine(const QString &line)
43 bool isCommentLine(const QString &line)
44 {
44 {
45 return line.startsWith("#");
45 return line.startsWith("#");
46 }
46 }
47
47
48 /**
48 /**
49 * Reads stream to retrieve x-axis unit
49 * Reads stream to retrieve x-axis unit
50 * @param stream the stream to read
50 * @param stream the stream to read
51 * @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
52 * error occured during reading
52 * error occured during reading
53 */
53 */
54 Unit readXAxisUnit(QTextStream &stream)
54 Unit readXAxisUnit(QTextStream &stream)
55 {
55 {
56 QString line{};
56 QString line{};
57
57
58 // Searches unit in the comment lines
58 // Searches unit in the comment lines
59 while (stream.readLineInto(&line) && isCommentLine(line)) {
59 while (stream.readLineInto(&line) && isCommentLine(line)) {
60 auto match = UNIT_REGEX.match(line);
60 auto match = UNIT_REGEX.match(line);
61 if (match.hasMatch()) {
61 if (match.hasMatch()) {
62 return Unit{match.captured(1), true};
62 return Unit{match.captured(1), true};
63 }
63 }
64 }
64 }
65
65
66 qCWarning(LOG_AmdaResultParser()) << QObject::tr("The unit could not be found in the file");
66 qCWarning(LOG_AmdaResultParser()) << QObject::tr("The unit could not be found in the file");
67
67
68 // Error cases
68 // Error cases
69 return Unit{{}, true};
69 return Unit{{}, true};
70 }
70 }
71
71
72 /**
72 /**
73 * Reads stream to retrieve results
73 * Reads stream to retrieve results
74 * @param stream the stream to read
74 * @param stream the stream to read
75 * @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
76 */
76 */
77 QPair<QVector<double>, QVector<double> > readResults(QTextStream &stream)
77 QPair<QVector<double>, QVector<double> > readResults(QTextStream &stream)
78 {
78 {
79 auto xData = QVector<double>{};
79 auto xData = QVector<double>{};
80 auto valuesData = QVector<double>{};
80 auto valuesData = QVector<double>{};
81
81
82 QString line{};
82 QString line{};
83
83
84 while (stream.readLineInto(&line)) {
84 while (stream.readLineInto(&line)) {
85 // Ignore comment lines
85 // Ignore comment lines
86 if (!isCommentLine(line)) {
86 if (!isCommentLine(line)) {
87 auto lineData = line.split(RESULT_LINE_SEPARATOR, QString::SkipEmptyParts);
87 auto lineData = line.split(RESULT_LINE_SEPARATOR, QString::SkipEmptyParts);
88 if (lineData.size() == 2) {
88 if (lineData.size() == 2) {
89 // X : the data is converted from date to double (in secs)
89 // X : the data is converted from date to double (in secs)
90 auto x = doubleDate(lineData.at(0));
90 auto x = doubleDate(lineData.at(0));
91
91
92 // Value
92 // Value
93 bool valueOk;
93 bool valueOk;
94 auto value = lineData.at(1).toDouble(&valueOk);
94 auto value = lineData.at(1).toDouble(&valueOk);
95
95
96 // Adds result only if x is valid. Then, if value is invalid, it is set to NaN
96 // Adds result only if x is valid. Then, if value is invalid, it is set to NaN
97 if (!std::isnan(x)) {
97 if (!std::isnan(x)) {
98 xData.push_back(x);
98 xData.push_back(x);
99
99
100 if (!valueOk) {
100 if (!valueOk) {
101 qCWarning(LOG_AmdaResultParser())
101 qCWarning(LOG_AmdaResultParser())
102 << QObject::tr(
102 << QObject::tr(
103 "Value from line %1 is invalid and will be converted to NaN")
103 "Value from line %1 is invalid and will be converted to NaN")
104 .arg(line);
104 .arg(line);
105 value = std::numeric_limits<double>::quiet_NaN();
105 value = std::numeric_limits<double>::quiet_NaN();
106 }
106 }
107
107
108 valuesData.push_back(value);
108 valuesData.push_back(value);
109 }
109 }
110 else {
110 else {
111 qCWarning(LOG_AmdaResultParser())
111 qCWarning(LOG_AmdaResultParser())
112 << QObject::tr("Can't retrieve results from line %1: x is invalid")
112 << QObject::tr("Can't retrieve results from line %1: x is invalid")
113 .arg(line);
113 .arg(line);
114 }
114 }
115 }
115 }
116 else {
116 else {
117 qCWarning(LOG_AmdaResultParser())
117 qCWarning(LOG_AmdaResultParser())
118 << QObject::tr("Can't retrieve results from line %1: invalid line").arg(line);
118 << QObject::tr("Can't retrieve results from line %1: invalid line").arg(line);
119 }
119 }
120 }
120 }
121 }
121 }
122
122
123 return qMakePair(std::move(xData), std::move(valuesData));
123 return qMakePair(std::move(xData), std::move(valuesData));
124 }
124 }
125
125
126 } // namespace
126 } // namespace
127
127
128 std::shared_ptr<IDataSeries> AmdaResultParser::readTxt(const QString &filePath) noexcept
128 std::shared_ptr<IDataSeries> AmdaResultParser::readTxt(const QString &filePath,
129 ValueType valueType) noexcept
129 {
130 {
131 if (valueType == ValueType::UNKNOWN) {
132 qCCritical(LOG_AmdaResultParser())
133 << QObject::tr("Can't retrieve AMDA data: the type of values to be read is unknown");
134 return nullptr;
135 }
136
130 QFile file{filePath};
137 QFile file{filePath};
131
138
132 if (!file.open(QFile::ReadOnly | QIODevice::Text)) {
139 if (!file.open(QFile::ReadOnly | QIODevice::Text)) {
133 qCCritical(LOG_AmdaResultParser())
140 qCCritical(LOG_AmdaResultParser())
134 << QObject::tr("Can't retrieve AMDA data from file %1: %2")
141 << QObject::tr("Can't retrieve AMDA data from file %1: %2")
135 .arg(filePath, file.errorString());
142 .arg(filePath, file.errorString());
136 return nullptr;
143 return nullptr;
137 }
144 }
138
145
139 QTextStream stream{&file};
146 QTextStream stream{&file};
140
147
141 // Checks if the file was found on the server
148 // Checks if the file was found on the server
142 auto firstLine = stream.readLine();
149 auto firstLine = stream.readLine();
143 if (firstLine.compare(FILE_NOT_FOUND_MESSAGE) == 0) {
150 if (firstLine.compare(FILE_NOT_FOUND_MESSAGE) == 0) {
144 qCCritical(LOG_AmdaResultParser())
151 qCCritical(LOG_AmdaResultParser())
145 << QObject::tr("Can't retrieve AMDA data from file %1: file was not found on server")
152 << QObject::tr("Can't retrieve AMDA data from file %1: file was not found on server")
146 .arg(filePath);
153 .arg(filePath);
147 return nullptr;
154 return nullptr;
148 }
155 }
149
156
150 // Reads x-axis unit
157 // Reads x-axis unit
151 stream.seek(0); // returns to the beginning of the file
158 stream.seek(0); // returns to the beginning of the file
152 auto xAxisUnit = readXAxisUnit(stream);
159 auto xAxisUnit = readXAxisUnit(stream);
153
160
154 // Reads results
161 // Reads results
155 stream.seek(0); // returns to the beginning of the file
162 stream.seek(0); // returns to the beginning of the file
156 auto results = readResults(stream);
163 auto results = readResults(stream);
157
164
158 return std::make_shared<ScalarSeries>(std::move(results.first), std::move(results.second),
165 return std::make_shared<ScalarSeries>(std::move(results.first), std::move(results.second),
159 xAxisUnit, Unit{});
166 xAxisUnit, Unit{});
160 }
167 }
General Comments 0
You need to be logged in to leave comments. Login now