@@ -0,0 +1,106 | |||
|
1 | #include <QObject> | |
|
2 | #include <QtTest> | |
|
3 | #include <QUuid> | |
|
4 | #include <limits> | |
|
5 | ||
|
6 | ||
|
7 | #include <Data/DateTimeRange.h> | |
|
8 | #include <Common/Numeric.h> | |
|
9 | ||
|
10 | Q_DECLARE_METATYPE(Seconds<double>); | |
|
11 | ||
|
12 | DateTimeRange computeZoom(QDateTime start, QDateTime stop, double zoom) | |
|
13 | { | |
|
14 | double start_epoch = start.toMSecsSinceEpoch(); | |
|
15 | double stop_epoch = stop.toMSecsSinceEpoch(); | |
|
16 | auto delta = stop_epoch - start_epoch; | |
|
17 | auto dt_ms = (zoom-1.)*(double(delta))/2.; | |
|
18 | return DateTimeRange{(start_epoch - dt_ms)/1000., (stop_epoch + dt_ms)/1000.}; | |
|
19 | } | |
|
20 | ||
|
21 | class TestDateTimeRange: public QObject { | |
|
22 | Q_OBJECT | |
|
23 | ||
|
24 | private slots: | |
|
25 | void testRangeDelta_data() | |
|
26 | { | |
|
27 | QTest::addColumn<QDateTime>("tstart"); | |
|
28 | QTest::addColumn<QDateTime>("tend"); | |
|
29 | QTest::addColumn<double>("expected"); | |
|
30 | auto now = QDateTime::currentDateTime(); | |
|
31 | auto yesterday = QDateTime::currentDateTime().addDays(-1); | |
|
32 | QTest::newRow("No delta") << now << now << 0.; | |
|
33 | QTest::newRow("One day delta") << yesterday << now << 60.*60.*24.; | |
|
34 | QTest::newRow("Minus one day delta") << now << yesterday << -60.*60.*24.; | |
|
35 | } | |
|
36 | ||
|
37 | void testRangeDelta() | |
|
38 | { | |
|
39 | QFETCH(QDateTime,tstart); | |
|
40 | QFETCH(QDateTime,tend); | |
|
41 | QFETCH(double,expected); | |
|
42 | auto range = DateTimeRange::fromDateTime(tstart, tend); | |
|
43 | double delta = range.delta(); | |
|
44 | // Since it is built from QDateTime don't expect better resolution | |
|
45 | QVERIFY((delta-expected) <= 0.002); | |
|
46 | } | |
|
47 | ||
|
48 | void testRangeShift_data() | |
|
49 | { | |
|
50 | QTest::addColumn<DateTimeRange>("initial"); | |
|
51 | QTest::addColumn<Seconds<double>>("shift"); | |
|
52 | QTest::addColumn<DateTimeRange>("expected"); | |
|
53 | auto now = QDateTime::currentDateTime(); | |
|
54 | auto yestd = QDateTime::currentDateTime().addDays(-1); | |
|
55 | auto range = DateTimeRange::fromDateTime(yestd, now); | |
|
56 | QTest::newRow("No shift") << range << Seconds<double>{0.} << range; | |
|
57 | ||
|
58 | QTest::newRow("One milisecond left") << range << Seconds<double>{-.001} << | |
|
59 | DateTimeRange::fromDateTime(yestd.addMSecs(-1.), now.addMSecs(-1.)); | |
|
60 | QTest::newRow("One milisecond right") << range << Seconds<double>{.001} << | |
|
61 | DateTimeRange::fromDateTime(yestd.addMSecs(1.), now.addMSecs(1.)); | |
|
62 | QTest::newRow("One second left") << range << Seconds<double>{-1.} << | |
|
63 | DateTimeRange::fromDateTime(yestd.addSecs(-1.), now.addSecs(-1.)); | |
|
64 | QTest::newRow("One second right") << range << Seconds<double>{1.} << | |
|
65 | DateTimeRange::fromDateTime(yestd.addSecs(1.), now.addSecs(1.)); | |
|
66 | QTest::newRow("One year left") << range << Seconds<double>{-365.*24.*60.*60.} << | |
|
67 | DateTimeRange::fromDateTime(yestd.addYears(-1.), now.addYears(-1.)); | |
|
68 | QTest::newRow("One year right") << range << Seconds<double>{365.*24.*60.*60.} << | |
|
69 | DateTimeRange::fromDateTime(yestd.addYears(1.), now.addYears(1.)); | |
|
70 | } | |
|
71 | void testRangeShift() | |
|
72 | { | |
|
73 | QFETCH(DateTimeRange,initial); | |
|
74 | QFETCH(Seconds<double>,shift); | |
|
75 | QFETCH(DateTimeRange,expected); | |
|
76 | QCOMPARE(initial+shift, expected); | |
|
77 | } | |
|
78 | ||
|
79 | void testRangeZoom_data() | |
|
80 | { | |
|
81 | QTest::addColumn<DateTimeRange>("initial"); | |
|
82 | QTest::addColumn<double>("zoom"); | |
|
83 | QTest::addColumn<DateTimeRange>("expected"); | |
|
84 | auto now = QDateTime::currentDateTime(); | |
|
85 | auto yestd = QDateTime::currentDateTime().addDays(-1); | |
|
86 | auto range = DateTimeRange::fromDateTime(yestd, now); | |
|
87 | QTest::newRow("No zoom") << range << 1. << range; | |
|
88 | ||
|
89 | QTest::newRow("Zoom IN 0.001") << range << 1.001 << | |
|
90 | computeZoom(yestd, now, 1.001); | |
|
91 | QTest::newRow("Zoom OUT 0.001") << range << 0.999 << | |
|
92 | computeZoom(yestd, now, 0.999); | |
|
93 | } | |
|
94 | void testRangeZoom() | |
|
95 | { | |
|
96 | QFETCH(DateTimeRange,initial); | |
|
97 | QFETCH(double,zoom); | |
|
98 | QFETCH(DateTimeRange,expected); | |
|
99 | QCOMPARE(initial*zoom, expected); | |
|
100 | } | |
|
101 | ||
|
102 | }; | |
|
103 | QTEST_MAIN(TestDateTimeRange) | |
|
104 | ||
|
105 | ||
|
106 | #include "TestDateTimeRange.moc" |
@@ -1,8 +1,12 | |||
|
1 | #ifndef NUMERIC_H | |
|
2 | #define NUMERIC_H | |
|
1 | 3 | #include <cmath> |
|
2 | 4 | #include <limits> |
|
3 | 5 | #include <type_traits> |
|
4 | 6 | #include <algorithm> |
|
5 | 7 | |
|
8 | namespace SciQLop::numeric { | |
|
9 | ||
|
6 | 10 | /* |
|
7 | 11 | taken from here https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon |
|
8 | 12 | */ |
@@ -16,3 +20,7 typename std::enable_if<!std::numeric_limits<T>::is_integer, bool>::type | |||
|
16 | 20 | // unless the result is subnormal |
|
17 | 21 | || std::abs(x-y) < std::numeric_limits<T>::min(); |
|
18 | 22 | } |
|
23 | ||
|
24 | } | |
|
25 | ||
|
26 | #endif |
@@ -1,15 +1,15 | |||
|
1 | 1 | #ifndef SCIQLOP_SQPRANGE_H |
|
2 | 2 | #define SCIQLOP_SQPRANGE_H |
|
3 | 3 | |
|
4 | #include <cmath> | |
|
4 | 5 | #include <QObject> |
|
5 | 6 | |
|
6 | 7 | #include <QDebug> |
|
7 | 8 | |
|
9 | #include <opaque/numeric_typedef.hpp> | |
|
8 | 10 | #include <Common/DateUtils.h> |
|
9 | 11 | #include <Common/MetaTypes.h> |
|
10 |
#include < |
|
|
11 | ||
|
12 | #include <cmath> | |
|
12 | #include <Common/Numeric.h> | |
|
13 | 13 | |
|
14 | 14 | |
|
15 | 15 | template <typename T> |
@@ -22,6 +22,7 struct Seconds : opaque::numeric_typedef<T, Seconds<T>> , | |||
|
22 | 22 | { |
|
23 | 23 | using base = opaque::numeric_typedef<T, Seconds<T>>; |
|
24 | 24 | using base::base; |
|
25 | operator T () const {return this->value;} | |
|
25 | 26 | }; |
|
26 | 27 | |
|
27 | 28 | /** |
@@ -36,6 +37,12 struct DateTimeRange { | |||
|
36 | 37 | DateUtils::secondsSinceEpoch(QDateTime{endDate, endTime, Qt::UTC})}; |
|
37 | 38 | } |
|
38 | 39 | |
|
40 | static DateTimeRange fromDateTime(const QDateTime &start, const QDateTime &end) | |
|
41 | { | |
|
42 | return {DateUtils::secondsSinceEpoch(start), | |
|
43 | DateUtils::secondsSinceEpoch(end)}; | |
|
44 | } | |
|
45 | ||
|
39 | 46 | /// Start time (UTC) |
|
40 | 47 | double m_TStart; |
|
41 | 48 | /// End time (UTC) |
@@ -55,12 +62,10 struct DateTimeRange { | |||
|
55 | 62 | |
|
56 | 63 | bool operator==(const DateTimeRange &other) const |
|
57 | 64 | { |
|
58 | auto equals = [](const auto &v1, const auto &v2) { | |
|
59 | return (std::isnan(v1) && std::isnan(v2)) || v1 == v2; | |
|
60 | }; | |
|
61 | ||
|
62 | return equals(m_TStart, other.m_TStart) && equals(m_TEnd, other.m_TEnd); | |
|
65 | return SciQLop::numeric::almost_equal(m_TStart, other.m_TStart, 1.) && | |
|
66 | SciQLop::numeric::almost_equal(m_TEnd, other.m_TEnd, 1.); | |
|
63 | 67 | } |
|
68 | ||
|
64 | 69 | bool operator!=(const DateTimeRange &other) const { return !(*this == other); } |
|
65 | 70 | |
|
66 | 71 | void grow(double factor) |
@@ -659,7 +659,7 bool VariableController::hasPendingDownloads() | |||
|
659 | 659 | |
|
660 | 660 | AcquisitionZoomType VariableController::getZoomType(const DateTimeRange &range, const DateTimeRange &oldRange) |
|
661 | 661 | { |
|
662 |
if (almost_equal |
|
|
662 | if (SciQLop::numeric::almost_equal<double>(range.delta(), oldRange.delta(), 1)) // same delta -> must be a pan or nothing | |
|
663 | 663 | { |
|
664 | 664 | if(range.m_TStart > oldRange.m_TStart) |
|
665 | 665 | return AcquisitionZoomType::PanRight; |
@@ -1,4 +1,5 | |||
|
1 | 1 | #include "Variable/VariableController2.h" |
|
2 | #include "Variable/VariableSynchronizationGroup2.h" | |
|
2 | 3 | #include <Common/containers.h> |
|
3 | 4 | #include <Common/debug.h> |
|
4 | 5 | #include <Data/DataProviderParameters.h> |
@@ -7,6 +8,7 class VariableController2::VariableController2Private | |||
|
7 | 8 | { |
|
8 | 9 | std::set<std::shared_ptr<Variable>> _variables; |
|
9 | 10 | QMap<QUuid,std::shared_ptr<IDataProvider>> _providers; |
|
11 | QMap<QUuid,std::shared_ptr<VariableSynchronizationGroup2>> _synchronizationGroups; | |
|
10 | 12 | public: |
|
11 | 13 | VariableController2Private(QObject* parent=Q_NULLPTR) |
|
12 | 14 | { |
@@ -20,6 +22,7 public: | |||
|
20 | 22 | auto newVar = std::make_shared<Variable>(name,metadata); |
|
21 | 23 | this->_variables.insert(newVar); |
|
22 | 24 | this->_providers[newVar->ID()] = provider; |
|
25 | this->_synchronizationGroups[newVar->ID()] = std::make_shared<VariableSynchronizationGroup2>(newVar->ID()); | |
|
23 | 26 | return newVar; |
|
24 | 27 | } |
|
25 | 28 |
@@ -107,7 +107,7 PYBIND11_MODULE(pysciqlopcore,m){ | |||
|
107 | 107 | |
|
108 | 108 | |
|
109 | 109 | py::class_<DateTimeRange>(m,"SqpRange") |
|
110 | .def("fromDateTime", &DateTimeRange::fromDateTime, py::return_value_policy::move) | |
|
110 | //.def("fromDateTime", &DateTimeRange::fromDateTime, py::return_value_policy::move) | |
|
111 | 111 | .def(py::init([](double start, double stop){return DateTimeRange{start, stop};})) |
|
112 | 112 | .def(py::init([](system_clock::time_point start, system_clock::time_point stop) |
|
113 | 113 | { |
@@ -13,6 +13,8 declare_test(TestStringUtils TestStringUtils Common/TestStringUtils.cpp "sciqlop | |||
|
13 | 13 | declare_test(TestContainers TestContainers Common/TestContainers.cpp "sciqlopcore;Qt5::Test") |
|
14 | 14 | declare_test(TestSyncGroup TestSyncGroup Variable/TestSyncGroup.cpp "sciqlopcore;Qt5::Test") |
|
15 | 15 | |
|
16 | declare_test(TestDateTimeRange TestDateTimeRange Data/TestDateTimeRange.cpp "sciqlopcore;Qt5::Test") | |
|
17 | ||
|
16 | 18 | |
|
17 | 19 | declare_test(TestDataSeriesUtils TestDataSeriesUtils Data/TestDataSeriesUtils.cpp "sciqlopcore;Qt5::Test") |
|
18 | 20 | declare_test(TestOptionalAxis TestOptionalAxis Data/TestOptionalAxis.cpp "sciqlopcore;Qt5::Test") |
General Comments 0
You need to be logged in to leave comments.
Login now