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