##// END OF EJS Templates
Merge branch 'feature/AmdaProviderUpdate' into develop
Alexandre Leroux -
r398:6ff08786d807 merge
parent child
Show More
@@ -0,0 +1,6
1 #Sampling Time : 60
2 #Time Format : YYYY-MM-DDThh:mm:ss.mls
3 #imf(0) - Type : Local Parameter @ CDPP/AMDA - Name : bx_gse - Units : nT - Size : 1 - Frame : GSE - Mission : ACE - Instrument : MFI - Dataset : mfi_final-prelim
4 2013-09-23T09:00:30.000 NaN
5 2013-09-23T09:01:30.000 -2.71850
6 2013-09-23T09:02:30.000 -2.52150 No newline at end of file
@@ -0,0 +1,2
1 #Sampling Time : 60
2 #Time Format : YYYY-MM-DDThh:mm:ss.mls No newline at end of file
@@ -0,0 +1,6
1 #Sampling Time : 60
2 #Time Format : YYYY-MM-DDThh:mm:ss.mls
3 #imf(0) - Type : Local Parameter @ CDPP/AMDA - Name : bx_gse - Units : nT - Size : 1 - Frame : GSE - Mission : ACE - Instrument : MFI - Dataset : mfi_final-prelim
4 2013-09-23T09:00:30.000 -2.83950 1.05141 3.01547
5 2013-09-23T09:01:30.000 -2.71850
6 2013-09-23T09:02:30.000 -2.52150 No newline at end of file
@@ -0,0 +1,13
1 #Sampling Time : 60
2 #Time Format : YYYY-MM-DDThh:mm:ss.mls
3 #imf(0) - Type : Local Parameter @ CDPP/AMDA - Name : bx_gse - Units : nT - Size : 1 - Frame : GSE - Mission : ACE - Instrument : MFI - Dataset : mfi_final-prelim
4 2013-09-23T09:00:30.000 -2.83950
5 2013-09-23T09:01:30.000 -2.71850
6 2013-09-23T09:02:30.000 -2.52150
7 2013-09-23T09:03:30.000 -2.57633
8 2013-09-23T09:04:30.000 -2.58050
9 2013-09-23T09:05:30.000 -2.48325
10 2013-09-23T09:06:30.000 -2.63025
11 2013-09-23T09:07:30.000 -2.55800
12 2013-09-23T09:08:30.000 -2.43250
13 2013-09-23T09:09:30.000 -2.42200 No newline at end of file
@@ -0,0 +1,6
1 #Sampling Time : 60
2 #Time Format : YYYY-MM-DDThh:mm:ss.mls
3 #imf(0) - Type : Local Parameter @ CDPP/AMDA - Name : bx_gse - Units : nT - Size : 1 - Frame : GSE - Mission : ACE - Instrument : MFI - Dataset : mfi_final-prelim
4 23/09/2013 07:50:30 -2.83950
5 2013-09-23T09:01:30.000 -2.71850
6 2013-09-23T09:02:30.000 -2.52150 No newline at end of file
@@ -0,0 +1,6
1 #Sampling Time : 60
2 #Time Format : YYYY-MM-DDThh:mm:ss.mls
3 #Wrong unit comment
4 2013-09-23T09:00:30.000 -2.83950
5 2013-09-23T09:01:30.000 -2.71850
6 2013-09-23T09:02:30.000 -2.52150 No newline at end of file
@@ -0,0 +1,6
1 #Sampling Time : 60
2 #Time Format : YYYY-MM-DDThh:mm:ss.mls
3 #imf(0) - Type : Local Parameter @ CDPP/AMDA - Name : bx_gse - Units : nT - Size : 1 - Frame : GSE - Mission : ACE - Instrument : MFI - Dataset : mfi_final-prelim
4 2013-09-23T09:00:30.000 abc
5 2013-09-23T09:01:30.000 -2.71850
6 2013-09-23T09:02:30.000 -2.52150 No newline at end of file
@@ -0,0 +1,179
1 #include "AmdaResultParser.h"
2
3 #include <Data/ScalarSeries.h>
4
5 #include <QObject>
6 #include <QtTest>
7
8 namespace {
9
10 /// Path for the tests
11 const auto TESTS_RESOURCES_PATH
12 = QFileInfo{QString{AMDA_TESTS_RESOURCES_DIR}, "TestAmdaResultParser"}.absoluteFilePath();
13
14 QString inputFilePath(const QString &inputFileName)
15 {
16 return QFileInfo{TESTS_RESOURCES_PATH, inputFileName}.absoluteFilePath();
17 }
18
19 struct ExpectedResults {
20 explicit ExpectedResults() = default;
21
22 /// Ctor with QVector<QDateTime> as x-axis data. Datetimes are converted to doubles
23 explicit ExpectedResults(Unit xAxisUnit, Unit valuesUnit, const QVector<QDateTime> &xAxisData,
24 QVector<double> valuesData)
25 : m_ParsingOK{true},
26 m_XAxisUnit{xAxisUnit},
27 m_ValuesUnit{valuesUnit},
28 m_XAxisData{},
29 m_ValuesData{std::move(valuesData)}
30 {
31 // Converts QVector<QDateTime> to QVector<double>
32 std::transform(xAxisData.cbegin(), xAxisData.cend(), std::back_inserter(m_XAxisData),
33 [](const auto &dateTime) { return dateTime.toMSecsSinceEpoch() / 1000.; });
34 }
35
36 /**
37 * Validates a DataSeries compared to the expected results
38 * @param results the DataSeries to validate
39 */
40 void validate(std::shared_ptr<IDataSeries> results)
41 {
42 if (m_ParsingOK) {
43 auto scalarSeries = dynamic_cast<ScalarSeries *>(results.get());
44 QVERIFY(scalarSeries != nullptr);
45
46 // Checks units
47 QVERIFY(scalarSeries->xAxisUnit() == m_XAxisUnit);
48 QVERIFY(scalarSeries->valuesUnit() == m_ValuesUnit);
49
50 // Checks values
51 QVERIFY(scalarSeries->xAxisData()->data() == m_XAxisData);
52 QVERIFY(scalarSeries->valuesData()->data() == m_ValuesData);
53 }
54 else {
55 QVERIFY(results == nullptr);
56 }
57 }
58
59 // Parsing was successfully completed
60 bool m_ParsingOK{false};
61 // Expected x-axis unit
62 Unit m_XAxisUnit{};
63 // Expected values unit
64 Unit m_ValuesUnit{};
65 // Expected x-axis data
66 QVector<double> m_XAxisData{};
67 // Expected values data
68 QVector<double> m_ValuesData{};
69 };
70
71 } // namespace
72
73 Q_DECLARE_METATYPE(ExpectedResults)
74
75 class TestAmdaResultParser : public QObject {
76 Q_OBJECT
77 private slots:
78 /// Input test data
79 /// @sa testTxtJson()
80 void testReadTxt_data();
81
82 /// Tests parsing of a TXT file
83 void testReadTxt();
84 };
85
86 void TestAmdaResultParser::testReadTxt_data()
87 {
88 // ////////////// //
89 // Test structure //
90 // ////////////// //
91
92 // Name of TXT file to read
93 QTest::addColumn<QString>("inputFileName");
94 // Expected results
95 QTest::addColumn<ExpectedResults>("expectedResults");
96
97 // ////////// //
98 // Test cases //
99 // ////////// //
100
101 auto dateTime = [](int year, int month, int day, int hours, int minutes, int seconds) {
102 return QDateTime{{year, month, day}, {hours, minutes, seconds}};
103 };
104
105 // Valid file
106 QTest::newRow("Valid file")
107 << QStringLiteral("ValidScalar1.txt")
108 << ExpectedResults{
109 Unit{QStringLiteral("nT"), true}, Unit{},
110 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 0, 30), dateTime(2013, 9, 23, 9, 1, 30),
111 dateTime(2013, 9, 23, 9, 2, 30), dateTime(2013, 9, 23, 9, 3, 30),
112 dateTime(2013, 9, 23, 9, 4, 30), dateTime(2013, 9, 23, 9, 5, 30),
113 dateTime(2013, 9, 23, 9, 6, 30), dateTime(2013, 9, 23, 9, 7, 30),
114 dateTime(2013, 9, 23, 9, 8, 30), dateTime(2013, 9, 23, 9, 9, 30)},
115 QVector<double>{-2.83950, -2.71850, -2.52150, -2.57633, -2.58050, -2.48325, -2.63025,
116 -2.55800, -2.43250, -2.42200}};
117
118 // Valid files but with some invalid lines (wrong unit, wrong values, etc.)
119 QTest::newRow("No unit file") << QStringLiteral("NoUnit.txt")
120 << ExpectedResults{Unit{QStringLiteral(""), true}, Unit{},
121 QVector<QDateTime>{}, QVector<double>{}};
122 QTest::newRow("Wrong unit file")
123 << QStringLiteral("WrongUnit.txt")
124 << ExpectedResults{Unit{QStringLiteral(""), true}, Unit{},
125 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 0, 30),
126 dateTime(2013, 9, 23, 9, 1, 30),
127 dateTime(2013, 9, 23, 9, 2, 30)},
128 QVector<double>{-2.83950, -2.71850, -2.52150}};
129
130 QTest::newRow("Wrong results file (date of first line is invalid")
131 << QStringLiteral("WrongDate.txt")
132 << ExpectedResults{
133 Unit{QStringLiteral("nT"), true}, Unit{},
134 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)},
135 QVector<double>{-2.71850, -2.52150}};
136
137 QTest::newRow("Wrong results file (too many values for first line")
138 << QStringLiteral("TooManyValues.txt")
139 << ExpectedResults{
140 Unit{QStringLiteral("nT"), true}, Unit{},
141 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)},
142 QVector<double>{-2.71850, -2.52150}};
143
144 QTest::newRow("Wrong results file (value of first line is invalid")
145 << QStringLiteral("WrongValue.txt")
146 << ExpectedResults{
147 Unit{QStringLiteral("nT"), true}, Unit{},
148 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)},
149 QVector<double>{-2.71850, -2.52150}};
150
151 QTest::newRow("Wrong results file (value of first line is NaN")
152 << QStringLiteral("NaNValue.txt")
153 << ExpectedResults{
154 Unit{QStringLiteral("nT"), true}, Unit{},
155 QVector<QDateTime>{dateTime(2013, 9, 23, 9, 1, 30), dateTime(2013, 9, 23, 9, 2, 30)},
156 QVector<double>{-2.71850, -2.52150}};
157
158 // Invalid file
159 QTest::newRow("Invalid file (unexisting file)")
160 << QStringLiteral("UnexistingFile.txt") << ExpectedResults{};
161 }
162
163 void TestAmdaResultParser::testReadTxt()
164 {
165 QFETCH(QString, inputFileName);
166 QFETCH(ExpectedResults, expectedResults);
167
168 // Parses file
169 auto filePath = inputFilePath(inputFileName);
170 auto results = AmdaResultParser::readTxt(filePath);
171
172 // ///////////////// //
173 // Validates results //
174 // ///////////////// //
175 expectedResults.validate(results);
176 }
177
178 QTEST_MAIN(TestAmdaResultParser)
179 #include "TestAmdaResultParser.moc"
@@ -1,105 +1,116
1 1 #ifndef SCIQLOP_ARRAYDATA_H
2 2 #define SCIQLOP_ARRAYDATA_H
3 3
4 4 #include <QReadLocker>
5 5 #include <QReadWriteLock>
6 6 #include <QVector>
7 7 /**
8 8 * @brief The ArrayData class represents a dataset for a data series.
9 9 *
10 10 * A dataset can be unidimensional or two-dimensional. This property is determined by the Dim
11 11 * template-parameter.
12 12 *
13 13 * @tparam Dim the dimension of the ArrayData (one or two)
14 14 * @sa IDataSeries
15 15 */
16 16 template <int Dim>
17 17 class ArrayData {
18 18 public:
19 19 /**
20 20 * Ctor for a unidimensional ArrayData
21 21 * @param nbColumns the number of values the ArrayData will hold
22 22 */
23 23 template <int D = Dim, typename = std::enable_if_t<D == 1> >
24 24 explicit ArrayData(int nbColumns) : m_Data{1, QVector<double>{}}
25 25 {
26 26 QWriteLocker locker{&m_Lock};
27 27 m_Data[0].resize(nbColumns);
28 28 }
29 29
30 /**
31 * Ctor for a unidimensional ArrayData
32 * @param data the data the ArrayData will hold
33 */
34 template <int D = Dim, typename = std::enable_if_t<D == 1> >
35 explicit ArrayData(QVector<double> data) : m_Data{1, QVector<double>{}}
36 {
37 QWriteLocker locker{&m_Lock};
38 m_Data[0] = std::move(data);
39 }
40
30 41 /// Copy ctor
31 42 explicit ArrayData(const ArrayData &other)
32 43 {
33 44 QReadLocker otherLocker{&other.m_Lock};
34 45 QWriteLocker locker{&m_Lock};
35 46 m_Data = other.m_Data;
36 47 }
37 48
38 49 /**
39 50 * Sets a data at a specified index. The index has to be valid to be effective
40 51 * @param index the index to which the data will be set
41 52 * @param data the data to set
42 53 * @remarks this method is only available for a unidimensional ArrayData
43 54 */
44 55 template <int D = Dim, typename = std::enable_if_t<D == 1> >
45 56 void setData(int index, double data) noexcept
46 57 {
47 58 QWriteLocker locker{&m_Lock};
48 59 if (index >= 0 && index < m_Data.at(0).size()) {
49 60 m_Data[0].replace(index, data);
50 61 }
51 62 }
52 63
53 64 /**
54 65 * @return the data as a vector
55 66 * @remarks this method is only available for a unidimensional ArrayData
56 67 */
57 68 template <int D = Dim, typename = std::enable_if_t<D == 1> >
58 69 QVector<double> data() const noexcept
59 70 {
60 71 QReadLocker locker{&m_Lock};
61 72 return m_Data[0];
62 73 }
63 74
64 75 /**
65 76 * @return the data as a vector
66 77 * @remarks this method is only available for a unidimensional ArrayData
67 78 */
68 79 template <int D = Dim, typename = std::enable_if_t<D == 1> >
69 80 QVector<double> data(double tStart, double tEnd) const noexcept
70 81 {
71 82 QReadLocker locker{&m_Lock};
72 83 return m_Data.at(tStart);
73 84 }
74 85
75 86 // TODO Comment
76 87 template <int D = Dim, typename = std::enable_if_t<D == 1> >
77 88 void merge(const ArrayData<1> &arrayData)
78 89 {
79 90 QWriteLocker locker{&m_Lock};
80 91 if (!m_Data.empty()) {
81 92 QReadLocker otherLocker{&arrayData.m_Lock};
82 93 m_Data[0] += arrayData.data();
83 94 }
84 95 }
85 96
86 97 template <int D = Dim, typename = std::enable_if_t<D == 1> >
87 98 int size() const
88 99 {
89 100 QReadLocker locker{&m_Lock};
90 101 return m_Data[0].size();
91 102 }
92 103
93 104 void clear()
94 105 {
95 106 QWriteLocker locker{&m_Lock};
96 107 m_Data.clear();
97 108 }
98 109
99 110
100 111 private:
101 112 QVector<QVector<double> > m_Data;
102 113 mutable QReadWriteLock m_Lock;
103 114 };
104 115
105 116 #endif // SCIQLOP_ARRAYDATA_H
@@ -1,63 +1,69
1 1 #ifndef SCIQLOP_IDATASERIES_H
2 2 #define SCIQLOP_IDATASERIES_H
3 3
4 4 #include <Common/MetaTypes.h>
5 5
6 6 #include <memory>
7 7
8 8 #include <QString>
9 9
10 10 template <int Dim>
11 11 class ArrayData;
12 12
13 13 struct Unit {
14 14 explicit Unit(const QString &name = {}, bool timeUnit = false)
15 15 : m_Name{name}, m_TimeUnit{timeUnit}
16 16 {
17 17 }
18 18
19 inline bool operator==(const Unit &other) const
20 {
21 return std::tie(m_Name, m_TimeUnit) == std::tie(other.m_Name, other.m_TimeUnit);
22 }
23 inline bool operator!=(const Unit &other) const { return !(*this == other); }
24
19 25 QString m_Name; ///< Unit name
20 26 bool m_TimeUnit; ///< The unit is a unit of time
21 27 };
22 28
23 29 /**
24 30 * @brief The IDataSeries aims to declare a data series.
25 31 *
26 32 * A data series is an entity that contains at least :
27 33 * - one dataset representing the x-axis
28 34 * - one dataset representing the values
29 35 *
30 36 * Each dataset is represented by an ArrayData, and is associated with a unit.
31 37 *
32 38 * An ArrayData can be unidimensional or two-dimensional, depending on the implementation of the
33 39 * IDataSeries. The x-axis dataset is always unidimensional.
34 40 *
35 41 * @sa ArrayData
36 42 */
37 43 class IDataSeries {
38 44 public:
39 45 virtual ~IDataSeries() noexcept = default;
40 46
41 47 /// Returns the x-axis dataset
42 48 virtual std::shared_ptr<ArrayData<1> > xAxisData() = 0;
43 49
44 50 /// Returns the x-axis dataset (as const)
45 51 virtual const std::shared_ptr<ArrayData<1> > xAxisData() const = 0;
46 52
47 53 virtual Unit xAxisUnit() const = 0;
48 54
49 55 virtual Unit valuesUnit() const = 0;
50 56
51 57 virtual void merge(IDataSeries *dataSeries) = 0;
52 58
53 59 virtual std::unique_ptr<IDataSeries> clone() const = 0;
54 60
55 61 virtual void lockRead() = 0;
56 62 virtual void lockWrite() = 0;
57 63 virtual void unlock() = 0;
58 64 };
59 65
60 66 // Required for using shared_ptr in signals/slots
61 67 SCIQLOP_REGISTER_META_TYPE(IDATASERIES_PTR_REGISTRY, std::shared_ptr<IDataSeries>)
62 68
63 69 #endif // SCIQLOP_IDATASERIES_H
@@ -1,30 +1,39
1 1 #ifndef SCIQLOP_SCALARSERIES_H
2 2 #define SCIQLOP_SCALARSERIES_H
3 3
4 4 #include <Data/DataSeries.h>
5 5
6 6 /**
7 7 * @brief The ScalarSeries class is the implementation for a data series representing a scalar.
8 8 */
9 9 class ScalarSeries : public DataSeries<1> {
10 10 public:
11 11 /**
12 12 * Ctor
13 13 * @param size the number of data the series will hold
14 14 * @param xAxisUnit x-axis unit
15 15 * @param valuesUnit values unit
16 16 */
17 17 explicit ScalarSeries(int size, const Unit &xAxisUnit, const Unit &valuesUnit);
18 18
19 19 /**
20 * Ctor with two vectors. The vectors must have the same size, otherwise a ScalarSeries with no
21 * values will be created.
22 * @param xAxisData x-axis data
23 * @param valuesData values data
24 */
25 explicit ScalarSeries(QVector<double> xAxisData, QVector<double> valuesData,
26 const Unit &xAxisUnit, const Unit &valuesUnit);
27
28 /**
20 29 * Sets data for a specific index. The index has to be valid to be effective
21 30 * @param index the index to which the data will be set
22 31 * @param x the x-axis data
23 32 * @param value the value data
24 33 */
25 34 void setData(int index, double x, double value) noexcept;
26 35
27 36 std::unique_ptr<IDataSeries> clone() const;
28 37 };
29 38
30 39 #endif // SCIQLOP_SCALARSERIES_H
@@ -1,18 +1,25
1 1 #include <Data/ScalarSeries.h>
2 2
3 3 ScalarSeries::ScalarSeries(int size, const Unit &xAxisUnit, const Unit &valuesUnit)
4 4 : DataSeries{std::make_shared<ArrayData<1> >(size), xAxisUnit,
5 5 std::make_shared<ArrayData<1> >(size), valuesUnit}
6 6 {
7 7 }
8 8
9 ScalarSeries::ScalarSeries(QVector<double> xAxisData, QVector<double> valuesData,
10 const Unit &xAxisUnit, const Unit &valuesUnit)
11 : DataSeries{std::make_shared<ArrayData<1> >(std::move(xAxisData)), xAxisUnit,
12 std::make_shared<ArrayData<1> >(std::move(valuesData)), valuesUnit}
13 {
14 }
15
9 16 void ScalarSeries::setData(int index, double x, double value) noexcept
10 17 {
11 18 xAxisData()->setData(index, x);
12 19 valuesData()->setData(index, value);
13 20 }
14 21
15 22 std::unique_ptr<IDataSeries> ScalarSeries::clone() const
16 23 {
17 24 return std::make_unique<ScalarSeries>(*this);
18 25 }
@@ -1,70 +1,132
1 1 #include "AmdaResultParser.h"
2 2
3 3 #include <Data/ScalarSeries.h>
4 4
5 5 #include <QDateTime>
6 6 #include <QFile>
7 #include <QRegularExpression>
7 8
8 9 Q_LOGGING_CATEGORY(LOG_AmdaResultParser, "AmdaResultParser")
9 10
10 11 namespace {
11 12
12 13 /// Format for dates in result files
13 14 const auto DATE_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss.zzz");
14 15
15 /// @todo ALX
16 /// Separator between values in a result line
17 const auto RESULT_LINE_SEPARATOR = QRegularExpression{QStringLiteral("\\s+")};
18
19 /// Regex to find unit in a line. Examples of valid lines:
20 /// ... - Units : nT - ...
21 /// ... -Units:nT- ...
22 /// ... -Units: mΒ²- ...
23 /// ... - Units : m/s - ...
24 const auto UNIT_REGEX = QRegularExpression{QStringLiteral("-\\s*Units\\s*:\\s*(.+?)\\s*-")};
25
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
16 28 double doubleDate(const QString &stringDate) noexcept
17 29 {
18 30 auto dateTime = QDateTime::fromString(stringDate, DATE_FORMAT);
19 return dateTime.toMSecsSinceEpoch() / 1000.;
31 return dateTime.isValid() ? (dateTime.toMSecsSinceEpoch() / 1000.)
32 : std::numeric_limits<double>::quiet_NaN();
20 33 }
21 34
22 } // namespace
23
24 std::shared_ptr<IDataSeries> AmdaResultParser::readTxt(const QString &filePath) noexcept
35 /**
36 * Reads stream to retrieve x-axis unit
37 * @param stream the stream to read
38 * @return the unit that has been read in the stream, a default unit (time unit with no label) if an
39 * error occured during reading
40 */
41 Unit readXAxisUnit(QTextStream &stream)
25 42 {
26 QFile file{filePath};
43 QString line{};
27 44
28 if (!file.open(QFile::ReadOnly | QIODevice::Text)) {
29 qCCritical(LOG_AmdaResultParser())
30 << QObject::tr("Can't retrieve AMDA data from file %1: %2")
31 .arg(filePath, file.errorString());
32 return nullptr;
45 if (stream.readLineInto(&line)) {
46 auto match = UNIT_REGEX.match(line);
47 if (match.hasMatch()) {
48 return Unit{match.captured(1), true};
49 }
50 else {
51 qCWarning(LOG_AmdaResultParser())
52 << QObject::tr("Can't read unit: invalid line %1").arg(line);
53 }
54 }
55 else {
56 qCWarning(LOG_AmdaResultParser()) << QObject::tr("Can't read unit: end of file");
33 57 }
34 58
59 // Error cases
60 return Unit{{}, true};
61 }
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 {
35 70 auto xData = QVector<double>{};
36 71 auto valuesData = QVector<double>{};
37 72
38 QTextStream stream{&file};
39
40 // Ignore comment lines (3 lines)
41 stream.readLine();
42 stream.readLine();
43 stream.readLine();
44
45 73 QString line{};
46 auto lineRegex = QRegExp{QStringLiteral("\\s+")};
47 74 while (stream.readLineInto(&line)) {
48 auto lineData = line.split(lineRegex, QString::SkipEmptyParts);
75 auto lineData = line.split(RESULT_LINE_SEPARATOR, QString::SkipEmptyParts);
49 76 if (lineData.size() == 2) {
50 77 // X : the data is converted from date to double (in secs)
51 xData.push_back(doubleDate(lineData.at(0)));
78 auto x = doubleDate(lineData.at(0));
52 79
53 80 // Value
54 valuesData.push_back(lineData.at(1).toDouble());
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 }
55 95 }
56 96 else {
57 /// @todo ALX : log
97 qCWarning(LOG_AmdaResultParser())
98 << QObject::tr("Can't retrieve results from line %1: invalid line").arg(line);
58 99 }
59 100 }
60 101
61 /// @todo ALX : handle units
62 auto scalarSeries = std::make_shared<ScalarSeries>(xData.size(), Unit{"nT", true}, Unit{});
102 return qMakePair(std::move(xData), std::move(valuesData));
103 }
104
105 } // namespace
63 106
64 const auto count = xData.size();
65 for (auto i = 0; i < count; ++i) {
66 scalarSeries->setData(i, xData.at(i), valuesData.at(i));
107 std::shared_ptr<IDataSeries> AmdaResultParser::readTxt(const QString &filePath) noexcept
108 {
109 QFile file{filePath};
110
111 if (!file.open(QFile::ReadOnly | QIODevice::Text)) {
112 qCCritical(LOG_AmdaResultParser())
113 << QObject::tr("Can't retrieve AMDA data from file %1: %2")
114 .arg(filePath, file.errorString());
115 return nullptr;
67 116 }
68 117
69 return scalarSeries;
118 QTextStream stream{&file};
119
120 // Ignore first two lines (comments lines)
121 stream.readLine();
122 stream.readLine();
123
124 // Reads x-axis unit
125 auto xAxisUnit = readXAxisUnit(stream);
126
127 // Reads results
128 auto results = readResults(stream);
129
130 return std::make_shared<ScalarSeries>(std::move(results.first), std::move(results.second),
131 xAxisUnit, Unit{});
70 132 }
General Comments 0
You need to be logged in to leave comments. Login now