@@ -0,0 +1,35 | |||||
|
1 | #ifndef SCIQLOP_AMDARESULTPARSERDEFS_H | |||
|
2 | #define SCIQLOP_AMDARESULTPARSERDEFS_H | |||
|
3 | ||||
|
4 | #include <QtCore/QRegularExpression> | |||
|
5 | #include <QtCore/QString> | |||
|
6 | #include <QtCore/QVariantHash> | |||
|
7 | ||||
|
8 | // ////////// // | |||
|
9 | // Properties // | |||
|
10 | // ////////// // | |||
|
11 | ||||
|
12 | /// Alias to represent properties read in the header of AMDA file | |||
|
13 | using Properties = QVariantHash; | |||
|
14 | ||||
|
15 | extern const QString X_AXIS_UNIT_PROPERTY; | |||
|
16 | ||||
|
17 | // /////////////////// // | |||
|
18 | // Regular expressions // | |||
|
19 | // /////////////////// // | |||
|
20 | ||||
|
21 | // AMDA V2 | |||
|
22 | // /// ... PARAMETER_UNITS : nT ... | |||
|
23 | // /// ... PARAMETER_UNITS:nT ... | |||
|
24 | // /// ... PARAMETER_UNITS: mΒ² ... | |||
|
25 | // /// ... PARAMETER_UNITS : m/s ... | |||
|
26 | // const auto UNIT_REGEX = QRegularExpression{QStringLiteral("\\s*PARAMETER_UNITS\\s*:\\s*(.+)")}; | |||
|
27 | ||||
|
28 | /// Regex to find x-axis unit in a line. Examples of valid lines: | |||
|
29 | /// ... - Units : nT - ... | |||
|
30 | /// ... -Units:nT- ... | |||
|
31 | /// ... -Units: mΒ²- ... | |||
|
32 | /// ... - Units : m/s - ... | |||
|
33 | extern const QRegularExpression DEFAULT_X_AXIS_UNIT_REGEX; | |||
|
34 | ||||
|
35 | #endif // SCIQLOP_AMDARESULTPARSERDEFS_H |
@@ -0,0 +1,6 | |||||
|
1 | #include "AmdaResultParserDefs.h" | |||
|
2 | ||||
|
3 | const QString X_AXIS_UNIT_PROPERTY = QStringLiteral("xAxisUnit"); | |||
|
4 | ||||
|
5 | const QRegularExpression DEFAULT_X_AXIS_UNIT_REGEX | |||
|
6 | = QRegularExpression{QStringLiteral("-\\s*Units\\s*:\\s*(.+?)\\s*-")}; |
@@ -1,23 +1,27 | |||||
1 | #ifndef SCIQLOP_UNIT_H |
|
1 | #ifndef SCIQLOP_UNIT_H | |
2 | #define SCIQLOP_UNIT_H |
|
2 | #define SCIQLOP_UNIT_H | |
3 |
|
3 | |||
|
4 | #include <Common/MetaTypes.h> | |||
|
5 | ||||
4 | #include <QString> |
|
6 | #include <QString> | |
5 | #include <tuple> |
|
7 | #include <tuple> | |
6 |
|
8 | |||
7 | struct Unit { |
|
9 | struct Unit { | |
8 | explicit Unit(const QString &name = {}, bool timeUnit = false) |
|
10 | explicit Unit(const QString &name = {}, bool timeUnit = false) | |
9 | : m_Name{name}, m_TimeUnit{timeUnit} |
|
11 | : m_Name{name}, m_TimeUnit{timeUnit} | |
10 | { |
|
12 | { | |
11 | } |
|
13 | } | |
12 |
|
14 | |||
13 | inline bool operator==(const Unit &other) const |
|
15 | inline bool operator==(const Unit &other) const | |
14 | { |
|
16 | { | |
15 | return std::tie(m_Name, m_TimeUnit) == std::tie(other.m_Name, other.m_TimeUnit); |
|
17 | return std::tie(m_Name, m_TimeUnit) == std::tie(other.m_Name, other.m_TimeUnit); | |
16 | } |
|
18 | } | |
17 | inline bool operator!=(const Unit &other) const { return !(*this == other); } |
|
19 | inline bool operator!=(const Unit &other) const { return !(*this == other); } | |
18 |
|
20 | |||
19 | QString m_Name; ///< Unit name |
|
21 | QString m_Name; ///< Unit name | |
20 | bool m_TimeUnit; ///< The unit is a unit of time (UTC) |
|
22 | bool m_TimeUnit; ///< The unit is a unit of time (UTC) | |
21 | }; |
|
23 | }; | |
22 |
|
24 | |||
|
25 | SCIQLOP_REGISTER_META_TYPE(UNIT_REGISTRY, Unit) | |||
|
26 | ||||
23 | #endif // SCIQLOP_UNIT_H |
|
27 | #endif // SCIQLOP_UNIT_H |
@@ -1,151 +1,150 | |||||
1 | #include <Data/ArrayData.h> |
|
1 | #include <Data/ArrayData.h> | |
2 | #include <Data/OptionalAxis.h> |
|
2 | #include <Data/OptionalAxis.h> | |
3 |
|
3 | |||
4 | #include <QObject> |
|
4 | #include <QObject> | |
5 | #include <QtTest> |
|
5 | #include <QtTest> | |
6 |
|
6 | |||
7 | Q_DECLARE_METATYPE(OptionalAxis) |
|
7 | Q_DECLARE_METATYPE(OptionalAxis) | |
8 | Q_DECLARE_METATYPE(Unit) |
|
|||
9 |
|
8 | |||
10 | class TestOptionalAxis : public QObject { |
|
9 | class TestOptionalAxis : public QObject { | |
11 | Q_OBJECT |
|
10 | Q_OBJECT | |
12 |
|
11 | |||
13 | private slots: |
|
12 | private slots: | |
14 | /// Tests the creation of a undefined axis |
|
13 | /// Tests the creation of a undefined axis | |
15 | void testNotDefinedAxisCtor(); |
|
14 | void testNotDefinedAxisCtor(); | |
16 |
|
15 | |||
17 | /// Tests the creation of a undefined axis |
|
16 | /// Tests the creation of a undefined axis | |
18 | void testDefinedAxisCtor_data(); |
|
17 | void testDefinedAxisCtor_data(); | |
19 | void testDefinedAxisCtor(); |
|
18 | void testDefinedAxisCtor(); | |
20 |
|
19 | |||
21 | /// Tests @sa OptionalAxis::at() method |
|
20 | /// Tests @sa OptionalAxis::at() method | |
22 | void testAt_data(); |
|
21 | void testAt_data(); | |
23 | void testAt(); |
|
22 | void testAt(); | |
24 |
|
23 | |||
25 | /// Tests @sa OptionalAxis::size() method |
|
24 | /// Tests @sa OptionalAxis::size() method | |
26 | void testSize_data(); |
|
25 | void testSize_data(); | |
27 | void testSize(); |
|
26 | void testSize(); | |
28 |
|
27 | |||
29 | /// Tests @sa OptionalAxis::unit() method |
|
28 | /// Tests @sa OptionalAxis::unit() method | |
30 | void testUnit_data(); |
|
29 | void testUnit_data(); | |
31 | void testUnit(); |
|
30 | void testUnit(); | |
32 | }; |
|
31 | }; | |
33 |
|
32 | |||
34 | void TestOptionalAxis::testNotDefinedAxisCtor() |
|
33 | void TestOptionalAxis::testNotDefinedAxisCtor() | |
35 | { |
|
34 | { | |
36 | OptionalAxis notDefinedAxis{}; |
|
35 | OptionalAxis notDefinedAxis{}; | |
37 | QVERIFY(!notDefinedAxis.isDefined()); |
|
36 | QVERIFY(!notDefinedAxis.isDefined()); | |
38 | } |
|
37 | } | |
39 |
|
38 | |||
40 | void TestOptionalAxis::testDefinedAxisCtor_data() |
|
39 | void TestOptionalAxis::testDefinedAxisCtor_data() | |
41 | { |
|
40 | { | |
42 | QTest::addColumn<bool>("noData"); // If set to true, nullptr is passed as data of the axis |
|
41 | QTest::addColumn<bool>("noData"); // If set to true, nullptr is passed as data of the axis | |
43 | QTest::addColumn<std::vector<double> >( |
|
42 | QTest::addColumn<std::vector<double> >( | |
44 | "data"); // Values assigned to the axis when 'noData' flag is set to false |
|
43 | "data"); // Values assigned to the axis when 'noData' flag is set to false | |
45 | QTest::addColumn<Unit>("unit"); // Unit assigned to the axis |
|
44 | QTest::addColumn<Unit>("unit"); // Unit assigned to the axis | |
46 |
|
45 | |||
47 | QTest::newRow("validData") << false << std::vector<double>{1, 2, 3} << Unit{"Hz"}; |
|
46 | QTest::newRow("validData") << false << std::vector<double>{1, 2, 3} << Unit{"Hz"}; | |
48 | QTest::newRow("invalidData") << true << std::vector<double>{} << Unit{"Hz"}; |
|
47 | QTest::newRow("invalidData") << true << std::vector<double>{} << Unit{"Hz"}; | |
49 | } |
|
48 | } | |
50 |
|
49 | |||
51 | void TestOptionalAxis::testDefinedAxisCtor() |
|
50 | void TestOptionalAxis::testDefinedAxisCtor() | |
52 | { |
|
51 | { | |
53 | QFETCH(bool, noData); |
|
52 | QFETCH(bool, noData); | |
54 | QFETCH(Unit, unit); |
|
53 | QFETCH(Unit, unit); | |
55 |
|
54 | |||
56 | // When there is no data, we expect that the constructor returns exception |
|
55 | // When there is no data, we expect that the constructor returns exception | |
57 | if (noData) { |
|
56 | if (noData) { | |
58 | QVERIFY_EXCEPTION_THROWN(OptionalAxis(nullptr, unit), std::invalid_argument); |
|
57 | QVERIFY_EXCEPTION_THROWN(OptionalAxis(nullptr, unit), std::invalid_argument); | |
59 | } |
|
58 | } | |
60 | else { |
|
59 | else { | |
61 | QFETCH(std::vector<double>, data); |
|
60 | QFETCH(std::vector<double>, data); | |
62 |
|
61 | |||
63 | OptionalAxis axis{std::make_shared<ArrayData<1> >(data), unit}; |
|
62 | OptionalAxis axis{std::make_shared<ArrayData<1> >(data), unit}; | |
64 | QVERIFY(axis.isDefined()); |
|
63 | QVERIFY(axis.isDefined()); | |
65 | } |
|
64 | } | |
66 | } |
|
65 | } | |
67 |
|
66 | |||
68 | void TestOptionalAxis::testAt_data() |
|
67 | void TestOptionalAxis::testAt_data() | |
69 | { |
|
68 | { | |
70 | QTest::addColumn<OptionalAxis>("axis"); // Axis used for test case (defined or not) |
|
69 | QTest::addColumn<OptionalAxis>("axis"); // Axis used for test case (defined or not) | |
71 | QTest::addColumn<int>("index"); // Index to test in the axis |
|
70 | QTest::addColumn<int>("index"); // Index to test in the axis | |
72 | QTest::addColumn<double>("expectedValue"); // Expected axis value for the index |
|
71 | QTest::addColumn<double>("expectedValue"); // Expected axis value for the index | |
73 |
|
72 | |||
74 | OptionalAxis definedAxis{std::make_shared<ArrayData<1> >(std::vector<double>{1, 2, 3}), |
|
73 | OptionalAxis definedAxis{std::make_shared<ArrayData<1> >(std::vector<double>{1, 2, 3}), | |
75 | Unit{"Hz"}}; |
|
74 | Unit{"Hz"}}; | |
76 |
|
75 | |||
77 | QTest::newRow("data1") << definedAxis << 0 << 1.; |
|
76 | QTest::newRow("data1") << definedAxis << 0 << 1.; | |
78 | QTest::newRow("data2") << definedAxis << 1 << 2.; |
|
77 | QTest::newRow("data2") << definedAxis << 1 << 2.; | |
79 | QTest::newRow("data3") << definedAxis << 2 << 3.; |
|
78 | QTest::newRow("data3") << definedAxis << 2 << 3.; | |
80 | QTest::newRow("data4 (index out of bounds)") |
|
79 | QTest::newRow("data4 (index out of bounds)") | |
81 | << definedAxis << 3 |
|
80 | << definedAxis << 3 | |
82 | << std::numeric_limits<double>::quiet_NaN(); // Expects NaN for out of bounds index |
|
81 | << std::numeric_limits<double>::quiet_NaN(); // Expects NaN for out of bounds index | |
83 | QTest::newRow("data5 (index out of bounds)") |
|
82 | QTest::newRow("data5 (index out of bounds)") | |
84 | << definedAxis << -1 |
|
83 | << definedAxis << -1 | |
85 | << std::numeric_limits<double>::quiet_NaN(); // Expects NaN for out of bounds index |
|
84 | << std::numeric_limits<double>::quiet_NaN(); // Expects NaN for out of bounds index | |
86 | QTest::newRow("data6 (axis not defined)") |
|
85 | QTest::newRow("data6 (axis not defined)") | |
87 | << OptionalAxis{} << 0 |
|
86 | << OptionalAxis{} << 0 | |
88 | << std::numeric_limits<double>::quiet_NaN(); // Expects NaN for undefined axis |
|
87 | << std::numeric_limits<double>::quiet_NaN(); // Expects NaN for undefined axis | |
89 | } |
|
88 | } | |
90 |
|
89 | |||
91 | void TestOptionalAxis::testAt() |
|
90 | void TestOptionalAxis::testAt() | |
92 | { |
|
91 | { | |
93 | QFETCH(OptionalAxis, axis); |
|
92 | QFETCH(OptionalAxis, axis); | |
94 | QFETCH(int, index); |
|
93 | QFETCH(int, index); | |
95 | QFETCH(double, expectedValue); |
|
94 | QFETCH(double, expectedValue); | |
96 |
|
95 | |||
97 | auto value = axis.at(index); |
|
96 | auto value = axis.at(index); | |
98 | QVERIFY((std::isnan(value) && std::isnan(expectedValue)) || value == expectedValue); |
|
97 | QVERIFY((std::isnan(value) && std::isnan(expectedValue)) || value == expectedValue); | |
99 | } |
|
98 | } | |
100 |
|
99 | |||
101 | void TestOptionalAxis::testSize_data() |
|
100 | void TestOptionalAxis::testSize_data() | |
102 | { |
|
101 | { | |
103 | QTest::addColumn<OptionalAxis>("axis"); // Axis used for test case (defined or not) |
|
102 | QTest::addColumn<OptionalAxis>("axis"); // Axis used for test case (defined or not) | |
104 | QTest::addColumn<int>("expectedSize"); // Expected number of data in the axis |
|
103 | QTest::addColumn<int>("expectedSize"); // Expected number of data in the axis | |
105 |
|
104 | |||
106 | // Lambda that creates default defined axis (with the values passed in parameter) |
|
105 | // Lambda that creates default defined axis (with the values passed in parameter) | |
107 | auto axis = [](std::vector<double> values) { |
|
106 | auto axis = [](std::vector<double> values) { | |
108 | return OptionalAxis{std::make_shared<ArrayData<1> >(std::move(values)), Unit{"Hz"}}; |
|
107 | return OptionalAxis{std::make_shared<ArrayData<1> >(std::move(values)), Unit{"Hz"}}; | |
109 | }; |
|
108 | }; | |
110 |
|
109 | |||
111 | QTest::newRow("data1") << axis({}) << 0; |
|
110 | QTest::newRow("data1") << axis({}) << 0; | |
112 | QTest::newRow("data2") << axis({1, 2, 3}) << 3; |
|
111 | QTest::newRow("data2") << axis({1, 2, 3}) << 3; | |
113 | QTest::newRow("data3") << axis({1, 2, 3, 4}) << 4; |
|
112 | QTest::newRow("data3") << axis({1, 2, 3, 4}) << 4; | |
114 | QTest::newRow("data4 (axis not defined)") << OptionalAxis{} |
|
113 | QTest::newRow("data4 (axis not defined)") << OptionalAxis{} | |
115 | << 0; // Expects 0 for undefined axis |
|
114 | << 0; // Expects 0 for undefined axis | |
116 | } |
|
115 | } | |
117 |
|
116 | |||
118 | void TestOptionalAxis::testSize() |
|
117 | void TestOptionalAxis::testSize() | |
119 | { |
|
118 | { | |
120 | QFETCH(OptionalAxis, axis); |
|
119 | QFETCH(OptionalAxis, axis); | |
121 | QFETCH(int, expectedSize); |
|
120 | QFETCH(int, expectedSize); | |
122 |
|
121 | |||
123 | QCOMPARE(axis.size(), expectedSize); |
|
122 | QCOMPARE(axis.size(), expectedSize); | |
124 | } |
|
123 | } | |
125 |
|
124 | |||
126 | void TestOptionalAxis::testUnit_data() |
|
125 | void TestOptionalAxis::testUnit_data() | |
127 | { |
|
126 | { | |
128 | QTest::addColumn<OptionalAxis>("axis"); // Axis used for test case (defined or not) |
|
127 | QTest::addColumn<OptionalAxis>("axis"); // Axis used for test case (defined or not) | |
129 | QTest::addColumn<Unit>("expectedUnit"); // Expected unit for the axis |
|
128 | QTest::addColumn<Unit>("expectedUnit"); // Expected unit for the axis | |
130 |
|
129 | |||
131 | // Lambda that creates default defined axis (with the unit passed in parameter) |
|
130 | // Lambda that creates default defined axis (with the unit passed in parameter) | |
132 | auto axis = [](Unit unit) { |
|
131 | auto axis = [](Unit unit) { | |
133 | return OptionalAxis{std::make_shared<ArrayData<1> >(std::vector<double>{1, 2, 3}), unit}; |
|
132 | return OptionalAxis{std::make_shared<ArrayData<1> >(std::vector<double>{1, 2, 3}), unit}; | |
134 | }; |
|
133 | }; | |
135 |
|
134 | |||
136 | QTest::newRow("data1") << axis(Unit{"Hz"}) << Unit{"Hz"}; |
|
135 | QTest::newRow("data1") << axis(Unit{"Hz"}) << Unit{"Hz"}; | |
137 | QTest::newRow("data2") << axis(Unit{"t", true}) << Unit{"t", true}; |
|
136 | QTest::newRow("data2") << axis(Unit{"t", true}) << Unit{"t", true}; | |
138 | QTest::newRow("data3 (axis not defined)") << OptionalAxis{} |
|
137 | QTest::newRow("data3 (axis not defined)") << OptionalAxis{} | |
139 | << Unit{}; // Expects default unit for undefined axis |
|
138 | << Unit{}; // Expects default unit for undefined axis | |
140 | } |
|
139 | } | |
141 |
|
140 | |||
142 | void TestOptionalAxis::testUnit() |
|
141 | void TestOptionalAxis::testUnit() | |
143 | { |
|
142 | { | |
144 | QFETCH(OptionalAxis, axis); |
|
143 | QFETCH(OptionalAxis, axis); | |
145 | QFETCH(Unit, expectedUnit); |
|
144 | QFETCH(Unit, expectedUnit); | |
146 |
|
145 | |||
147 | QCOMPARE(axis.unit(), expectedUnit); |
|
146 | QCOMPARE(axis.unit(), expectedUnit); | |
148 | } |
|
147 | } | |
149 |
|
148 | |||
150 | QTEST_MAIN(TestOptionalAxis) |
|
149 | QTEST_MAIN(TestOptionalAxis) | |
151 | #include "TestOptionalAxis.moc" |
|
150 | #include "TestOptionalAxis.moc" |
@@ -1,68 +1,76 | |||||
1 | #ifndef SCIQLOP_AMDARESULTPARSERHELPER_H |
|
1 | #ifndef SCIQLOP_AMDARESULTPARSERHELPER_H | |
2 | #define SCIQLOP_AMDARESULTPARSERHELPER_H |
|
2 | #define SCIQLOP_AMDARESULTPARSERHELPER_H | |
3 |
|
3 | |||
|
4 | #include "AmdaResultParserDefs.h" | |||
|
5 | ||||
4 | #include <QtCore/QLoggingCategory> |
|
6 | #include <QtCore/QLoggingCategory> | |
5 | #include <QtCore/QString> |
|
7 | #include <QtCore/QString> | |
6 |
|
8 | |||
7 | #include <memory> |
|
9 | #include <memory> | |
8 |
|
10 | |||
9 | class IDataSeries; |
|
11 | class IDataSeries; | |
10 |
|
12 | |||
11 | Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaResultParserHelper) |
|
13 | Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaResultParserHelper) | |
12 |
|
14 | |||
13 | /** |
|
15 | /** | |
14 | * Helper used to interpret the data of an AMDA result file and generate the corresponding data |
|
16 | * Helper used to interpret the data of an AMDA result file and generate the corresponding data | |
15 | * series. |
|
17 | * series. | |
16 | * |
|
18 | * | |
17 | * It proposes methods allowing to read line by line an AMDA file and to extract the properties |
|
19 | * It proposes methods allowing to read line by line an AMDA file and to extract the properties | |
18 | * (from the header) and the values corresponding to the data series |
|
20 | * (from the header) and the values corresponding to the data series | |
19 | * |
|
21 | * | |
20 | * @sa DataSeries |
|
22 | * @sa DataSeries | |
21 | */ |
|
23 | */ | |
22 | struct IAmdaResultParserHelper { |
|
24 | struct IAmdaResultParserHelper { | |
23 | virtual ~IAmdaResultParserHelper() noexcept = default; |
|
25 | virtual ~IAmdaResultParserHelper() noexcept = default; | |
24 |
|
26 | |||
25 | /// Verifies that the extracted properties are well formed and possibly applies other treatments |
|
27 | /// Verifies that the extracted properties are well formed and possibly applies other treatments | |
26 | /// on them |
|
28 | /// on them | |
27 | /// @return true if the properties are well formed, false otherwise |
|
29 | /// @return true if the properties are well formed, false otherwise | |
28 | virtual bool checkProperties() = 0; |
|
30 | virtual bool checkProperties() = 0; | |
29 |
|
31 | |||
30 | /// Creates the data series from the properties and values extracted from the AMDA file. |
|
32 | /// Creates the data series from the properties and values extracted from the AMDA file. | |
31 | /// @warning as the data are moved in the data series, the helper shouldn't be used after |
|
33 | /// @warning as the data are moved in the data series, the helper shouldn't be used after | |
32 | /// calling this method |
|
34 | /// calling this method | |
33 | /// @return the data series created |
|
35 | /// @return the data series created | |
34 | virtual std::shared_ptr<IDataSeries> createSeries() = 0; |
|
36 | virtual std::shared_ptr<IDataSeries> createSeries() = 0; | |
35 |
|
37 | |||
36 | /// Reads a line from the AMDA file to extract a property that will be used to generate the data |
|
38 | /// Reads a line from the AMDA file to extract a property that will be used to generate the data | |
37 | /// series |
|
39 | /// series | |
38 | /// @param line tahe line to interpret |
|
40 | /// @param line tahe line to interpret | |
39 | virtual void readPropertyLine(const QString &line) = 0; |
|
41 | virtual void readPropertyLine(const QString &line) = 0; | |
40 |
|
42 | |||
41 | /// Reads a line from the AMDA file to extract a value that will be set in the data series |
|
43 | /// Reads a line from the AMDA file to extract a value that will be set in the data series | |
42 | /// @param line the line to interpret |
|
44 | /// @param line the line to interpret | |
43 | virtual void readResultLine(const QString &line) = 0; |
|
45 | virtual void readResultLine(const QString &line) = 0; | |
44 | }; |
|
46 | }; | |
45 |
|
47 | |||
46 | /** |
|
48 | /** | |
47 | * Implementation of @sa IAmdaResultParserHelper for scalars |
|
49 | * Implementation of @sa IAmdaResultParserHelper for scalars | |
48 | */ |
|
50 | */ | |
49 | class ScalarParserHelper : public IAmdaResultParserHelper { |
|
51 | class ScalarParserHelper : public IAmdaResultParserHelper { | |
50 | public: |
|
52 | public: | |
51 | bool checkProperties() override; |
|
53 | bool checkProperties() override; | |
52 | std::shared_ptr<IDataSeries> createSeries() override; |
|
54 | std::shared_ptr<IDataSeries> createSeries() override; | |
53 | void readPropertyLine(const QString &line) override; |
|
55 | void readPropertyLine(const QString &line) override; | |
54 | void readResultLine(const QString &line) override; |
|
56 | void readResultLine(const QString &line) override; | |
|
57 | ||||
|
58 | private: | |||
|
59 | Properties m_Properties{}; | |||
55 | }; |
|
60 | }; | |
56 |
|
61 | |||
57 | /** |
|
62 | /** | |
58 | * Implementation of @sa IAmdaResultParserHelper for vectors |
|
63 | * Implementation of @sa IAmdaResultParserHelper for vectors | |
59 | */ |
|
64 | */ | |
60 | class VectorParserHelper : public IAmdaResultParserHelper { |
|
65 | class VectorParserHelper : public IAmdaResultParserHelper { | |
61 | public: |
|
66 | public: | |
62 | bool checkProperties() override; |
|
67 | bool checkProperties() override; | |
63 | std::shared_ptr<IDataSeries> createSeries() override; |
|
68 | std::shared_ptr<IDataSeries> createSeries() override; | |
64 | void readPropertyLine(const QString &line) override; |
|
69 | void readPropertyLine(const QString &line) override; | |
65 | void readResultLine(const QString &line) override; |
|
70 | void readResultLine(const QString &line) override; | |
|
71 | ||||
|
72 | private: | |||
|
73 | Properties m_Properties{}; | |||
66 | }; |
|
74 | }; | |
67 |
|
75 | |||
68 | #endif // SCIQLOP_AMDARESULTPARSERHELPER_H |
|
76 | #endif // SCIQLOP_AMDARESULTPARSERHELPER_H |
@@ -1,74 +1,75 | |||||
1 |
|
1 | |||
2 | amdaplugin_moc_headers = [ |
|
2 | amdaplugin_moc_headers = [ | |
3 | 'include/AmdaPlugin.h', |
|
3 | 'include/AmdaPlugin.h', | |
4 | 'include/AmdaProvider.h' |
|
4 | 'include/AmdaProvider.h' | |
5 | ] |
|
5 | ] | |
6 |
|
6 | |||
7 | amdaplugin_sources = [ |
|
7 | amdaplugin_sources = [ | |
8 | 'src/AmdaDefs.cpp', |
|
8 | 'src/AmdaDefs.cpp', | |
9 | 'src/AmdaParser.cpp', |
|
9 | 'src/AmdaParser.cpp', | |
10 | 'src/AmdaPlugin.cpp', |
|
10 | 'src/AmdaPlugin.cpp', | |
11 | 'src/AmdaProvider.cpp', |
|
11 | 'src/AmdaProvider.cpp', | |
12 | 'src/AmdaResultParser.cpp' |
|
12 | 'src/AmdaResultParser.cpp' | |
|
13 | 'src/AmdaResultParserDefs.cpp' | |||
13 | 'src/AmdaResultParserHelper.cpp' |
|
14 | 'src/AmdaResultParserHelper.cpp' | |
14 | ] |
|
15 | ] | |
15 |
|
16 | |||
16 | amdaplugin_ui_files = [] |
|
17 | amdaplugin_ui_files = [] | |
17 | amdaplugin_resources_files = [ |
|
18 | amdaplugin_resources_files = [ | |
18 | 'resources/amdaresources.qrc' |
|
19 | 'resources/amdaresources.qrc' | |
19 | ] |
|
20 | ] | |
20 |
|
21 | |||
21 | amdaplugin_inc = include_directories(['include', '../../plugin/include']) |
|
22 | amdaplugin_inc = include_directories(['include', '../../plugin/include']) | |
22 |
|
23 | |||
23 | moc_gen = generator(moc, |
|
24 | moc_gen = generator(moc, | |
24 | output : 'moc_@BASENAME@.cpp', |
|
25 | output : 'moc_@BASENAME@.cpp', | |
25 | arguments : ['@INPUT@', |
|
26 | arguments : ['@INPUT@', | |
26 | '-DPLUGIN_JSON_FILE_PATH="'+meson.source_root()+'/plugins/amda/resources/amda.json"', |
|
27 | '-DPLUGIN_JSON_FILE_PATH="'+meson.source_root()+'/plugins/amda/resources/amda.json"', | |
27 | '-I', meson.current_source_dir()+'/include', |
|
28 | '-I', meson.current_source_dir()+'/include', | |
28 | '-I', meson.current_source_dir()+'/../../plugin/include', |
|
29 | '-I', meson.current_source_dir()+'/../../plugin/include', | |
29 | '-o', '@OUTPUT@']) |
|
30 | '-o', '@OUTPUT@']) | |
30 |
|
31 | |||
31 | rcc_gen = generator(rcc, |
|
32 | rcc_gen = generator(rcc, | |
32 | output : 'qrc_@BASENAME@.cpp', |
|
33 | output : 'qrc_@BASENAME@.cpp', | |
33 | arguments : ['--name=@BASENAME@"', |
|
34 | arguments : ['--name=@BASENAME@"', | |
34 | '--output', |
|
35 | '--output', | |
35 | '@OUTPUT@', |
|
36 | '@OUTPUT@', | |
36 | '@INPUT@']) |
|
37 | '@INPUT@']) | |
37 |
|
38 | |||
38 | amdaplugin_moc_plugin_files = moc_gen.process(amdaplugin_moc_headers) |
|
39 | amdaplugin_moc_plugin_files = moc_gen.process(amdaplugin_moc_headers) | |
39 |
|
40 | |||
40 | amdaplugin_rcc_plugin_files = rcc_gen.process(amdaplugin_resources_files) |
|
41 | amdaplugin_rcc_plugin_files = rcc_gen.process(amdaplugin_resources_files) | |
41 |
|
42 | |||
42 | #amdaplugin_rcc_plugin_files = qt5.preprocess( |
|
43 | #amdaplugin_rcc_plugin_files = qt5.preprocess( | |
43 | # qresources : amdaplugin_resources_files) |
|
44 | # qresources : amdaplugin_resources_files) | |
44 |
|
45 | |||
45 | amdaplugin_moc_files = qt5.preprocess( |
|
46 | amdaplugin_moc_files = qt5.preprocess( | |
46 | ui_files : amdaplugin_ui_files) |
|
47 | ui_files : amdaplugin_ui_files) | |
47 |
|
48 | |||
48 | sciqlop_amdaplugin = library('amdaplugin', |
|
49 | sciqlop_amdaplugin = library('amdaplugin', | |
49 | amdaplugin_sources, |
|
50 | amdaplugin_sources, | |
50 | amdaplugin_moc_files, |
|
51 | amdaplugin_moc_files, | |
51 | amdaplugin_rcc_plugin_files, |
|
52 | amdaplugin_rcc_plugin_files, | |
52 | amdaplugin_moc_plugin_files, |
|
53 | amdaplugin_moc_plugin_files, | |
53 | cpp_args : ['-DAMDA_LIB','-DQT_PLUGIN'], |
|
54 | cpp_args : ['-DAMDA_LIB','-DQT_PLUGIN'], | |
54 | include_directories : [amdaplugin_inc], |
|
55 | include_directories : [amdaplugin_inc], | |
55 | dependencies : [sciqlop_core, sciqlop_gui], |
|
56 | dependencies : [sciqlop_core, sciqlop_gui], | |
56 | install : true |
|
57 | install : true | |
57 | ) |
|
58 | ) | |
58 |
|
59 | |||
59 |
|
60 | |||
60 | tests = [ |
|
61 | tests = [ | |
61 | [['tests/TestAmdaParser.cpp'],'test_amda_parser','AMDA parser test'], |
|
62 | [['tests/TestAmdaParser.cpp'],'test_amda_parser','AMDA parser test'], | |
62 | [['tests/TestAmdaResultParser.cpp'],'test_amda_result_parser','AMDA result parser test'], |
|
63 | [['tests/TestAmdaResultParser.cpp'],'test_amda_result_parser','AMDA result parser test'], | |
63 | [['tests/TestAmdaAcquisition.cpp'],'test_amda_acquisition','AMDA Acquisition test'] |
|
64 | [['tests/TestAmdaAcquisition.cpp'],'test_amda_acquisition','AMDA Acquisition test'] | |
64 | ] |
|
65 | ] | |
65 |
|
66 | |||
66 | foreach unit_test : tests |
|
67 | foreach unit_test : tests | |
67 | test_moc_files = qt5.preprocess(moc_sources : unit_test[0]) |
|
68 | test_moc_files = qt5.preprocess(moc_sources : unit_test[0]) | |
68 | test_exe = executable(unit_test[1],unit_test[0] , test_moc_files, |
|
69 | test_exe = executable(unit_test[1],unit_test[0] , test_moc_files, | |
69 | link_with : [sciqlop_amdaplugin], |
|
70 | link_with : [sciqlop_amdaplugin], | |
70 | include_directories : [amdaplugin_inc], |
|
71 | include_directories : [amdaplugin_inc], | |
71 | cpp_args : ['-DAMDA_TESTS_RESOURCES_DIR="'+meson.current_source_dir()+'/tests-resources"'], |
|
72 | cpp_args : ['-DAMDA_TESTS_RESOURCES_DIR="'+meson.current_source_dir()+'/tests-resources"'], | |
72 | dependencies : [sciqlop_core, sciqlop_gui, qt5test]) |
|
73 | dependencies : [sciqlop_core, sciqlop_gui, qt5test]) | |
73 | test(unit_test[2], test_exe, args: ['-teamcity', '-o', '@0@.teamcity.txt'.format(unit_test[1])], timeout: 3 * 60) |
|
74 | test(unit_test[2], test_exe, args: ['-teamcity', '-o', '@0@.teamcity.txt'.format(unit_test[1])], timeout: 3 * 60) | |
74 | endforeach |
|
75 | endforeach |
@@ -1,51 +1,120 | |||||
1 | #include "AmdaResultParserHelper.h" |
|
1 | #include "AmdaResultParserHelper.h" | |
2 |
|
2 | |||
|
3 | #include <Data/Unit.h> | |||
|
4 | ||||
3 | Q_LOGGING_CATEGORY(LOG_AmdaResultParserHelper, "AmdaResultParserHelper") |
|
5 | Q_LOGGING_CATEGORY(LOG_AmdaResultParserHelper, "AmdaResultParserHelper") | |
4 |
|
6 | |||
|
7 | namespace { | |||
|
8 | ||||
|
9 | // /////// // | |||
|
10 | // Methods // | |||
|
11 | // /////// // | |||
|
12 | ||||
|
13 | /** | |||
|
14 | * Checks that the properties contain a specific unit and that this unit is valid | |||
|
15 | * @param properties the properties map in which to search unit | |||
|
16 | * @param key the key to search for the unit in the properties | |||
|
17 | * @param errorMessage the error message to log in case the unit is invalid | |||
|
18 | * @return true if the unit is valid, false it it's invalid or was not found in the properties | |||
|
19 | */ | |||
|
20 | bool checkUnit(const Properties &properties, const QString &key, const QString &errorMessage) | |||
|
21 | { | |||
|
22 | auto unit = properties.value(key).value<Unit>(); | |||
|
23 | if (unit.m_Name.isEmpty()) { | |||
|
24 | qCWarning(LOG_AmdaResultParserHelper()) << errorMessage; | |||
|
25 | return false; | |||
|
26 | } | |||
|
27 | ||||
|
28 | return true; | |||
|
29 | } | |||
|
30 | ||||
|
31 | /** | |||
|
32 | * Reads a line from the AMDA file and tries to extract a property from it | |||
|
33 | * @param properties the properties map in which to put the property extracted from the line | |||
|
34 | * @param key the key to which the property is added in the properties map | |||
|
35 | * @param line the line to read to extract the property | |||
|
36 | * @param regex the expected regex to extract the property. If the line matches this regex, the | |||
|
37 | * property is generated | |||
|
38 | * @param fun the function used to generate the property | |||
|
39 | * @return true if the property could be generated, false if the line does not match the regex, or | |||
|
40 | * if a property has already been generated for the key | |||
|
41 | */ | |||
|
42 | template <typename GeneratePropertyFun> | |||
|
43 | bool tryReadProperty(Properties &properties, const QString &key, const QString &line, | |||
|
44 | const QRegularExpression ®ex, GeneratePropertyFun fun) | |||
|
45 | { | |||
|
46 | if (properties.contains(key)) { | |||
|
47 | return false; | |||
|
48 | } | |||
|
49 | ||||
|
50 | auto match = regex.match(line); | |||
|
51 | if (match.hasMatch()) { | |||
|
52 | properties.insert(key, fun(match)); | |||
|
53 | } | |||
|
54 | ||||
|
55 | return match.hasMatch(); | |||
|
56 | } | |||
|
57 | ||||
|
58 | /** | |||
|
59 | * Reads a line from the AMDA file and tries to extract a unit from it | |||
|
60 | * @sa tryReadProperty() | |||
|
61 | */ | |||
|
62 | bool tryReadUnit(Properties &properties, const QString &key, const QString &line, | |||
|
63 | const QRegularExpression ®ex, bool timeUnit = false) | |||
|
64 | { | |||
|
65 | return tryReadProperty(properties, key, line, regex, [timeUnit](const auto &match) { | |||
|
66 | return QVariant::fromValue(Unit{match.captured(1), timeUnit}); | |||
|
67 | }); | |||
|
68 | } | |||
|
69 | ||||
|
70 | } // namespace | |||
|
71 | ||||
5 | // ////////////////// // |
|
72 | // ////////////////// // | |
6 | // ScalarParserHelper // |
|
73 | // ScalarParserHelper // | |
7 | // ////////////////// // |
|
74 | // ////////////////// // | |
8 |
|
75 | |||
9 | bool ScalarParserHelper::checkProperties() |
|
76 | bool ScalarParserHelper::checkProperties() | |
10 | { |
|
77 | { | |
11 | /// @todo ALX |
|
78 | return checkUnit(m_Properties, X_AXIS_UNIT_PROPERTY, | |
|
79 | QObject::tr("The x-axis unit could not be found in the file")); | |||
12 | } |
|
80 | } | |
13 |
|
81 | |||
14 | std::shared_ptr<IDataSeries> ScalarParserHelper::createSeries() |
|
82 | std::shared_ptr<IDataSeries> ScalarParserHelper::createSeries() | |
15 | { |
|
83 | { | |
16 | /// @todo ALX |
|
84 | /// @todo ALX | |
17 | } |
|
85 | } | |
18 |
|
86 | |||
19 | void ScalarParserHelper::readPropertyLine(const QString &line) |
|
87 | void ScalarParserHelper::readPropertyLine(const QString &line) | |
20 | { |
|
88 | { | |
21 | /// @todo ALX |
|
89 | tryReadUnit(m_Properties, X_AXIS_UNIT_PROPERTY, line, DEFAULT_X_AXIS_UNIT_REGEX, true); | |
22 | } |
|
90 | } | |
23 |
|
91 | |||
24 | void ScalarParserHelper::readResultLine(const QString &line) |
|
92 | void ScalarParserHelper::readResultLine(const QString &line) | |
25 | { |
|
93 | { | |
26 | /// @todo ALX |
|
94 | /// @todo ALX | |
27 | } |
|
95 | } | |
28 |
|
96 | |||
29 | // ////////////////// // |
|
97 | // ////////////////// // | |
30 | // VectorParserHelper // |
|
98 | // VectorParserHelper // | |
31 | // ////////////////// // |
|
99 | // ////////////////// // | |
32 |
|
100 | |||
33 | bool VectorParserHelper::checkProperties() |
|
101 | bool VectorParserHelper::checkProperties() | |
34 | { |
|
102 | { | |
35 | /// @todo ALX |
|
103 | return checkUnit(m_Properties, X_AXIS_UNIT_PROPERTY, | |
|
104 | QObject::tr("The x-axis unit could not be found in the file")); | |||
36 | } |
|
105 | } | |
37 |
|
106 | |||
38 | std::shared_ptr<IDataSeries> VectorParserHelper::createSeries() |
|
107 | std::shared_ptr<IDataSeries> VectorParserHelper::createSeries() | |
39 | { |
|
108 | { | |
40 | /// @todo ALX |
|
109 | /// @todo ALX | |
41 | } |
|
110 | } | |
42 |
|
111 | |||
43 | void VectorParserHelper::readPropertyLine(const QString &line) |
|
112 | void VectorParserHelper::readPropertyLine(const QString &line) | |
44 | { |
|
113 | { | |
45 | /// @todo ALX |
|
114 | tryReadUnit(m_Properties, X_AXIS_UNIT_PROPERTY, line, DEFAULT_X_AXIS_UNIT_REGEX, true); | |
46 | } |
|
115 | } | |
47 |
|
116 | |||
48 | void VectorParserHelper::readResultLine(const QString &line) |
|
117 | void VectorParserHelper::readResultLine(const QString &line) | |
49 | { |
|
118 | { | |
50 | /// @todo ALX |
|
119 | /// @todo ALX | |
51 | } |
|
120 | } |
General Comments 0
You need to be logged in to leave comments.
Login now