##// END OF EJS Templates
Updated to fixed TS lib, added spectrogram min/max sampling hints when available...
jeandet -
r85:1e3f92d40b0e
parent child
Show More
@@ -1,1 +1,1
1 Subproject commit 22e3e4553178230053aac40131b4fdb36c163075
1 Subproject commit 1c245f84d0728d99b6f5deab7793fb238105a54d
@@ -1,35 +1,41
1 #ifndef SCIQLOP_SPECTROGRAMTIMESERIE_H
1 #ifndef SCIQLOP_SPECTROGRAMTIMESERIE_H
2 #define SCIQLOP_SPECTROGRAMTIMESERIE_H
2 #define SCIQLOP_SPECTROGRAMTIMESERIE_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <TimeSeries.h>
6 #include <TimeSeries.h>
7 #include <cmath>
7
8
8 class SCIQLOP_CORE_EXPORT SpectrogramTimeSerie
9 class SCIQLOP_CORE_EXPORT SpectrogramTimeSerie
9 : public TimeSeries::TimeSerie<double, SpectrogramTimeSerie, 2>
10 : public TimeSeries::TimeSerie<double, SpectrogramTimeSerie, 2>
10 {
11 {
11 public:
12 public:
13 double min_sampling = std::nan("");
14 double max_sampling = std::nan("");
12 using item_t =
15 using item_t =
13 decltype(std::declval<
16 decltype(std::declval<
14 TimeSeries::TimeSerie<double, SpectrogramTimeSerie, 2>>()[0]);
17 TimeSeries::TimeSerie<double, SpectrogramTimeSerie, 2>>()[0]);
15
18
16 using iterator_t = decltype(
19 using iterator_t = decltype(
17 std::declval<TimeSeries::TimeSerie<double, SpectrogramTimeSerie, 2>>()
20 std::declval<TimeSeries::TimeSerie<double, SpectrogramTimeSerie, 2>>()
18 .begin());
21 .begin());
19
22
20 SpectrogramTimeSerie() {}
23 SpectrogramTimeSerie() {}
21 SpectrogramTimeSerie(SpectrogramTimeSerie::axis_t&& t,
24 SpectrogramTimeSerie(SpectrogramTimeSerie::axis_t&& t,
22 SpectrogramTimeSerie::axis_t&& y,
25 SpectrogramTimeSerie::axis_t&& y,
23 SpectrogramTimeSerie::container_type<
26 SpectrogramTimeSerie::container_type<
24 SpectrogramTimeSerie::raw_value_type>&& values,
27 SpectrogramTimeSerie::raw_value_type>&& values,
25 std::vector<std::size_t>& shape)
28 std::vector<std::size_t>& shape, double min_sampling,
26 : TimeSeries::TimeSerie<double, SpectrogramTimeSerie, 2>(t, values, shape)
29 double max_sampling)
30 : TimeSeries::TimeSerie<double, SpectrogramTimeSerie, 2>(t, values,
31 shape),
32 min_sampling{min_sampling}, max_sampling{max_sampling}
27 {
33 {
28 _axes[1] = y;
34 _axes[1] = y;
29 }
35 }
30
36
31 ~SpectrogramTimeSerie() = default;
37 ~SpectrogramTimeSerie() = default;
32 using TimeSerie::TimeSerie;
38 using TimeSerie::TimeSerie;
33 };
39 };
34
40
35 #endif // SCIQLOP_SPECTROGRAMTIMESERIE_H
41 #endif // SCIQLOP_SPECTROGRAMTIMESERIE_H
@@ -1,83 +1,93
1 #ifndef TIMESERIESUTILS_H
1 #ifndef TIMESERIESUTILS_H
2 #define TIMESERIESUTILS_H
2 #define TIMESERIESUTILS_H
3 #include "MultiComponentTimeSerie.h"
3 #include "MultiComponentTimeSerie.h"
4 #include "ScalarTimeSerie.h"
4 #include "ScalarTimeSerie.h"
5 #include "SpectrogramTimeSerie.h"
5 #include "SpectrogramTimeSerie.h"
6 #include "VectorTimeSerie.h"
6 #include "VectorTimeSerie.h"
7
7
8 #include <TimeSeries.h>
8 #include <TimeSeries.h>
9 #include <cmath>
9 #include <cmath>
10 #include <memory>
10 #include <memory>
11
11
12 namespace TimeSeriesUtils
12 namespace TimeSeriesUtils
13 {
13 {
14 template<typename T> TimeSeries::ITimeSerie* copy(T input_ts)
14 template<typename T> TimeSeries::ITimeSerie* copy(T input_ts)
15 {
15 {
16 if constexpr(std::is_base_of_v<TimeSeries::ITimeSerie, T>)
16 if constexpr(std::is_base_of_v<TimeSeries::ITimeSerie, T>)
17 {
17 {
18 if(auto ts = dynamic_cast<VectorTimeSerie*>(input_ts))
18 if(auto ts = dynamic_cast<VectorTimeSerie*>(input_ts))
19 { return new VectorTimeSerie(*ts); }
19 { return new VectorTimeSerie(*ts); }
20 if(auto ts = dynamic_cast<ScalarTimeSerie*>(input_ts))
20 if(auto ts = dynamic_cast<ScalarTimeSerie*>(input_ts))
21 { return new ScalarTimeSerie(*ts); }
21 { return new ScalarTimeSerie(*ts); }
22 if(auto ts = dynamic_cast<MultiComponentTimeSerie*>(input_ts))
22 if(auto ts = dynamic_cast<MultiComponentTimeSerie*>(input_ts))
23 { return new MultiComponentTimeSerie(*ts); }
23 { return new MultiComponentTimeSerie(*ts); }
24 if(auto ts = dynamic_cast<SpectrogramTimeSerie*>(input_ts))
24 if(auto ts = dynamic_cast<SpectrogramTimeSerie*>(input_ts))
25 { return new SpectrogramTimeSerie(*ts); }
25 { return new SpectrogramTimeSerie(*ts); }
26 }
26 }
27 else
27 else
28 {
28 {
29 if(auto ts = std::dynamic_pointer_cast<VectorTimeSerie>(input_ts))
29 if(auto ts = std::dynamic_pointer_cast<VectorTimeSerie>(input_ts))
30 { return new VectorTimeSerie(*ts); }
30 { return new VectorTimeSerie(*ts); }
31 if(auto ts = std::dynamic_pointer_cast<ScalarTimeSerie>(input_ts))
31 if(auto ts = std::dynamic_pointer_cast<ScalarTimeSerie>(input_ts))
32 { return new ScalarTimeSerie(*ts); }
32 { return new ScalarTimeSerie(*ts); }
33 if(auto ts = std::dynamic_pointer_cast<SpectrogramTimeSerie>(input_ts))
33 if(auto ts = std::dynamic_pointer_cast<SpectrogramTimeSerie>(input_ts))
34 { return new SpectrogramTimeSerie(*ts); }
34 { return new SpectrogramTimeSerie(*ts); }
35 if(auto ts = std::dynamic_pointer_cast<MultiComponentTimeSerie>(input_ts))
35 if(auto ts = std::dynamic_pointer_cast<MultiComponentTimeSerie>(input_ts))
36 { return new MultiComponentTimeSerie(*ts); }
36 { return new MultiComponentTimeSerie(*ts); }
37 }
37 }
38 return nullptr;
38 return nullptr;
39 }
39 }
40
40
41 struct axis_properties
41 struct axis_properties
42 {
42 {
43 double range;
43 double range;
44 double max_resolution;
44 double max_resolution;
45 bool is_log;
45 bool is_log;
46 double min;
47 double max;
46 };
48 };
47
49
48 constexpr auto IsLog = true;
50 constexpr auto IsLog = true;
49 constexpr auto IsLinear = false;
51 constexpr auto IsLinear = false;
50
52
51 constexpr auto CheckMedian = true;
53 constexpr auto CheckMedian = true;
52 constexpr auto DontCheckMedian = false;
54 constexpr auto DontCheckMedian = false;
53
55
54 template<bool is_log, bool check_median>
56 template<bool is_log, bool check_median>
55 axis_properties axis_analysis(
57 axis_properties axis_analysis(
56 typename std::conditional<is_log, std::vector<double>&,
58 typename std::conditional<is_log, std::vector<double>&,
57 const std::vector<double>&>::type axis)
59 const std::vector<double>&>::type axis,
60 double given_max_resolution = std::nan(""))
58 {
61 {
59 std::vector<double> axis_diff(axis.size());
62 std::vector<double> axis_diff(axis.size());
60 if constexpr(is_log)
63 if constexpr(is_log)
61 {
64 {
62 std::transform(std::cbegin(axis), std::cend(axis), std::begin(axis),
65 std::transform(std::cbegin(axis), std::cend(axis), std::begin(axis),
63 [](const auto v) { return std::log10(v); });
66 [](const auto v) { return std::log10(v); });
64 }
67 }
65 auto range = *(std::cend(axis) - 1) - *(std::begin(axis));
68 auto min = *std::begin(axis);
66 std::adjacent_difference(std::cbegin(axis), std::cend(axis),
69 auto max = *(std::cend(axis) - 1);
67 std::begin(axis_diff));
70 auto range = max - min;
68 auto min_diff =
71 auto min_diff = given_max_resolution;
69 (*std::min_element(std::cbegin(axis_diff) + 1, std::cend(axis_diff)));
72 if(std::isnan(min_diff))
70 if constexpr(check_median)
71 {
73 {
72 std::nth_element(std::begin(axis_diff) + 1,
74 std::adjacent_difference(std::cbegin(axis), std::cend(axis),
73 std::begin(axis_diff) + axis_diff.size() / 2,
75 std::begin(axis_diff));
74 std::end(axis_diff));
76 min_diff =
75 auto median_diff = *(std::begin(axis_diff) + axis_diff.size() / 2);
77 (*std::min_element(std::cbegin(axis_diff) + 1, std::cend(axis_diff)));
76 if(median_diff > (4 * min_diff)) min_diff = median_diff;
78 if constexpr(check_median)
79 {
80 std::nth_element(std::begin(axis_diff) + 1,
81 std::begin(axis_diff) + axis_diff.size() / 2,
82 std::end(axis_diff));
83 auto median_diff = *(std::begin(axis_diff) + axis_diff.size() / 2);
84 if(median_diff > (4 * min_diff)) min_diff = median_diff;
85 }
77 }
86 }
78 return {range, min_diff, is_log};
87
88 return {range, min_diff, is_log, min, max};
79 }
89 }
80
90
81 } // namespace TimeSeriesUtils
91 } // namespace TimeSeriesUtils
82
92
83 #endif
93 #endif
@@ -1,148 +1,148
1 #include "Variable/VariableSynchronizationGroup2.h"
1 #include "Variable/VariableSynchronizationGroup2.h"
2
2
3 #include <Common/containers.h>
3 #include <Common/containers.h>
4 #include <Common/debug.h>
4 #include <Common/debug.h>
5 #include <Data/DataProviderParameters.h>
5 #include <Data/DataProviderParameters.h>
6 #include <Data/DateTimeRange.h>
6 #include <Data/DateTimeRange.h>
7 #include <Data/DateTimeRangeHelper.h>
7 #include <Data/DateTimeRangeHelper.h>
8 #include <Data/IDataProvider.h>
8 #include <Data/IDataProvider.h>
9 #include <QObject>
9 #include <QObject>
10 #include <QReadWriteLock>
10 #include <QReadWriteLock>
11 #include <QRunnable>
11 #include <QRunnable>
12 #include <QThreadPool>
12 #include <QThreadPool>
13 #include <TimeSeries.h>
13 #include <TimeSeries.h>
14 #include <Variable/Variable2.h>
14 #include <Variable/Variable2.h>
15
15
16 struct VCTransaction
16 struct VCTransaction
17 {
17 {
18 VCTransaction(QUuid refVar, DateTimeRange range, int varCount)
18 VCTransaction(QUuid refVar, DateTimeRange range, int varCount)
19 : refVar{refVar}, range{range}, _remainingVars{varCount}
19 : refVar{refVar}, range{range}, _remainingVars{varCount}
20 {}
20 {}
21
21
22 QUuid refVar;
22 QUuid refVar;
23 DateTimeRange range;
23 DateTimeRange range;
24 bool ready()
24 bool ready()
25 {
25 {
26 QReadLocker lock{&_lock};
26 QReadLocker lock{&_lock};
27 return _remainingVars == 0;
27 return _remainingVars == 0;
28 }
28 }
29
29
30 bool done()
30 bool done()
31 {
31 {
32 QWriteLocker lock{&_lock};
32 QWriteLocker lock{&_lock};
33 _remainingVars -= 1;
33 _remainingVars -= 1;
34 return _remainingVars == 0;
34 return _remainingVars == 0;
35 }
35 }
36
36
37 private:
37 private:
38 QReadWriteLock _lock;
38 QReadWriteLock _lock;
39 int _remainingVars;
39 int _remainingVars;
40 };
40 };
41
41
42 class TransactionExe : public QObject, public QRunnable
42 class TransactionExe : public QObject, public QRunnable
43 {
43 {
44 Q_OBJECT
44 Q_OBJECT
45 std::shared_ptr<Variable2> _variable;
45 std::shared_ptr<Variable2> _variable;
46 std::shared_ptr<IDataProvider> _provider;
46 std::shared_ptr<IDataProvider> _provider;
47 std::vector<DateTimeRange> _ranges;
47 std::vector<DateTimeRange> _ranges;
48 DateTimeRange _range;
48 DateTimeRange _range;
49 bool _overwrite;
49 bool _overwrite;
50
50
51 public:
51 public:
52 TransactionExe(const std::shared_ptr<Variable2>& variable,
52 TransactionExe(const std::shared_ptr<Variable2>& variable,
53 const std::shared_ptr<IDataProvider>& provider,
53 const std::shared_ptr<IDataProvider>& provider,
54 const std::vector<DateTimeRange>& ranges, DateTimeRange range,
54 const std::vector<DateTimeRange>& ranges, DateTimeRange range,
55 bool overwrite = true)
55 bool overwrite = true)
56 : _variable{variable}, _provider{provider}, _ranges{ranges},
56 : _variable{variable}, _provider{provider}, _ranges{ranges},
57 _range{range}, _overwrite{overwrite}
57 _range{range}, _overwrite{overwrite}
58 {
58 {
59 setAutoDelete(true);
59 setAutoDelete(true);
60 }
60 }
61 void run() override
61 void run() override
62 {
62 {
63 std::vector<TimeSeries::ITimeSerie*> data;
63 std::vector<TimeSeries::ITimeSerie*> data;
64 for(auto range : _ranges)
64 for(auto range : _ranges)
65 {
65 {
66 auto ds = _provider->getData(
66 auto ds = _provider->getData(
67 DataProviderParameters{{range}, _variable->metadata()});
67 DataProviderParameters{{range}, _variable->metadata()});
68 if(ds) data.push_back(ds);
68 if(ds and ds->size()) data.push_back(ds); // skip empty dataSeries
69 }
69 }
70 if(_overwrite)
70 if(_overwrite)
71 _variable->setData(data, _range, true);
71 _variable->setData(data, _range, true);
72 else
72 else
73 {
73 {
74 data.push_back(_variable->data().get());
74 data.push_back(_variable->data().get());
75 _variable->setData(data, _range, true);
75 _variable->setData(data, _range, true);
76 }
76 }
77 std::for_each(std::begin(data), std::end(data),
77 std::for_each(std::begin(data), std::end(data),
78 [](TimeSeries::ITimeSerie* ts) { delete ts; });
78 [](TimeSeries::ITimeSerie* ts) { delete ts; });
79 emit transactionComplete();
79 emit transactionComplete();
80 }
80 }
81 signals:
81 signals:
82 void transactionComplete();
82 void transactionComplete();
83 };
83 };
84
84
85 class VCTransactionsQueues
85 class VCTransactionsQueues
86 {
86 {
87 QReadWriteLock _mutex{QReadWriteLock::Recursive};
87 QReadWriteLock _mutex{QReadWriteLock::Recursive};
88 std::map<QUuid, std::optional<std::shared_ptr<VCTransaction>>>
88 std::map<QUuid, std::optional<std::shared_ptr<VCTransaction>>>
89 _nextTransactions;
89 _nextTransactions;
90 std::map<QUuid, std::optional<std::shared_ptr<VCTransaction>>>
90 std::map<QUuid, std::optional<std::shared_ptr<VCTransaction>>>
91 _pendingTransactions;
91 _pendingTransactions;
92
92
93 public:
93 public:
94 void addEntry(QUuid id)
94 void addEntry(QUuid id)
95 {
95 {
96 QWriteLocker lock{&_mutex};
96 QWriteLocker lock{&_mutex};
97 _nextTransactions[id] = std::nullopt;
97 _nextTransactions[id] = std::nullopt;
98 _pendingTransactions[id] = std::nullopt;
98 _pendingTransactions[id] = std::nullopt;
99 }
99 }
100
100
101 void removeEntry(QUuid id)
101 void removeEntry(QUuid id)
102 {
102 {
103 QWriteLocker lock{&_mutex};
103 QWriteLocker lock{&_mutex};
104 _nextTransactions.erase(id);
104 _nextTransactions.erase(id);
105 _pendingTransactions.erase(id);
105 _pendingTransactions.erase(id);
106 }
106 }
107
107
108 std::map<QUuid, std::optional<std::shared_ptr<VCTransaction>>>
108 std::map<QUuid, std::optional<std::shared_ptr<VCTransaction>>>
109 pendingTransactions()
109 pendingTransactions()
110 {
110 {
111 QReadLocker lock{&_mutex};
111 QReadLocker lock{&_mutex};
112 return _pendingTransactions;
112 return _pendingTransactions;
113 }
113 }
114
114
115 std::map<QUuid, std::optional<std::shared_ptr<VCTransaction>>>
115 std::map<QUuid, std::optional<std::shared_ptr<VCTransaction>>>
116 nextTransactions()
116 nextTransactions()
117 {
117 {
118 QReadLocker lock{&_mutex};
118 QReadLocker lock{&_mutex};
119 return _nextTransactions;
119 return _nextTransactions;
120 }
120 }
121
121
122 std::optional<std::shared_ptr<VCTransaction>> start(QUuid id)
122 std::optional<std::shared_ptr<VCTransaction>> start(QUuid id)
123 {
123 {
124 QWriteLocker lock{&_mutex};
124 QWriteLocker lock{&_mutex};
125 _pendingTransactions[id] = _nextTransactions[id];
125 _pendingTransactions[id] = _nextTransactions[id];
126 _nextTransactions[id] = std::nullopt;
126 _nextTransactions[id] = std::nullopt;
127 return _pendingTransactions[id];
127 return _pendingTransactions[id];
128 }
128 }
129
129
130 void enqueue(QUuid id, std::shared_ptr<VCTransaction> transaction)
130 void enqueue(QUuid id, std::shared_ptr<VCTransaction> transaction)
131 {
131 {
132 QWriteLocker lock{&_mutex};
132 QWriteLocker lock{&_mutex};
133 _nextTransactions[id] = transaction;
133 _nextTransactions[id] = transaction;
134 }
134 }
135
135
136 void complete(QUuid id)
136 void complete(QUuid id)
137 {
137 {
138 QWriteLocker lock{&_mutex};
138 QWriteLocker lock{&_mutex};
139 _pendingTransactions[id] = std::nullopt;
139 _pendingTransactions[id] = std::nullopt;
140 }
140 }
141
141
142 bool active(QUuid id)
142 bool active(QUuid id)
143 {
143 {
144 QReadLocker lock{&_mutex};
144 QReadLocker lock{&_mutex};
145 return _nextTransactions[id].has_value() ||
145 return _nextTransactions[id].has_value() ||
146 _pendingTransactions[id].has_value();
146 _pendingTransactions[id].has_value();
147 }
147 }
148 };
148 };
@@ -1,236 +1,248
1 #include "Variable/Variable2.h"
1 #include "Variable/Variable2.h"
2
2
3 #define PROPERTY_(property, getter, setter, type) \
3 #define PROPERTY_(property, getter, setter, type) \
4 type getter() noexcept \
4 type getter() noexcept \
5 { \
5 { \
6 QReadLocker lock{&m_Lock}; \
6 QReadLocker lock{&m_Lock}; \
7 return property; \
7 return property; \
8 } \
8 } \
9 void setter(const type& getter) noexcept \
9 void setter(const type& getter) noexcept \
10 { \
10 { \
11 QWriteLocker lock{&m_Lock}; \
11 QWriteLocker lock{&m_Lock}; \
12 property = getter; \
12 property = getter; \
13 } \
13 } \
14 type property;
14 type property;
15
15
16 #define V_FW_GETTER_SETTER(getter, setter, type) \
16 #define V_FW_GETTER_SETTER(getter, setter, type) \
17 type Variable2::getter() \
17 type Variable2::getter() \
18 { \
18 { \
19 QReadLocker lock{&this->m_lock}; \
19 QReadLocker lock{&this->m_lock}; \
20 return impl->getter(); \
20 return impl->getter(); \
21 } \
21 } \
22 void Variable2::setter(const type& value) \
22 void Variable2::setter(const type& value) \
23 { \
23 { \
24 { \
24 { \
25 QWriteLocker lock{&this->m_lock}; \
25 QWriteLocker lock{&this->m_lock}; \
26 impl->setter(value); \
26 impl->setter(value); \
27 } \
27 } \
28 emit updated(this->ID()); \
28 emit updated(this->ID()); \
29 }
29 }
30
30
31 static DataSeriesType findDataSeriesType(const QVariantHash& metadata)
31 static DataSeriesType findDataSeriesType(const QVariantHash& metadata)
32 {
32 {
33 auto dataSeriesType = DataSeriesType::NONE;
33 auto dataSeriesType = DataSeriesType::NONE;
34
34
35 // Go through the metadata and stop at the first value that could be converted
35 // Go through the metadata and stop at the first value that could be converted
36 // to DataSeriesType
36 // to DataSeriesType
37 for(auto it = metadata.cbegin(), end = metadata.cend();
37 for(auto it = metadata.cbegin(), end = metadata.cend();
38 it != end && dataSeriesType == DataSeriesType::NONE; ++it)
38 it != end && dataSeriesType == DataSeriesType::NONE; ++it)
39 {
39 {
40 dataSeriesType = DataSeriesTypeUtils::fromString(it.value().toString());
40 dataSeriesType = DataSeriesTypeUtils::fromString(it.value().toString());
41 }
41 }
42
42
43 return dataSeriesType;
43 return dataSeriesType;
44 }
44 }
45
45
46 std::shared_ptr<TimeSeries::ITimeSerie>
46 std::shared_ptr<TimeSeries::ITimeSerie>
47 clone_ts(const std::shared_ptr<TimeSeries::ITimeSerie>& ts)
47 clone_ts(const std::shared_ptr<TimeSeries::ITimeSerie>& ts)
48 {
48 {
49 if(auto scal_ts = std::dynamic_pointer_cast<ScalarTimeSerie>(ts))
49 if(auto scal_ts = std::dynamic_pointer_cast<ScalarTimeSerie>(ts))
50 return std::make_shared<ScalarTimeSerie>(*scal_ts);
50 return std::make_shared<ScalarTimeSerie>(*scal_ts);
51 if(auto scal_ts = std::dynamic_pointer_cast<VectorTimeSerie>(ts))
51 if(auto scal_ts = std::dynamic_pointer_cast<VectorTimeSerie>(ts))
52 return std::make_shared<VectorTimeSerie>(*scal_ts);
52 return std::make_shared<VectorTimeSerie>(*scal_ts);
53 if(auto scal_ts = std::dynamic_pointer_cast<SpectrogramTimeSerie>(ts))
53 if(auto scal_ts = std::dynamic_pointer_cast<SpectrogramTimeSerie>(ts))
54 return std::make_shared<SpectrogramTimeSerie>(*scal_ts);
54 return std::make_shared<SpectrogramTimeSerie>(*scal_ts);
55 return nullptr;
55 return nullptr;
56 }
56 }
57
57
58 struct Variable2::VariablePrivate
58 struct Variable2::VariablePrivate
59 {
59 {
60 VariablePrivate(const QString& name, const QVariantHash& metadata)
60 VariablePrivate(const QString& name, const QVariantHash& metadata)
61 : m_Name{name}, m_Range{INVALID_RANGE}, m_Metadata{metadata}, m_TimeSerie{
61 : m_Name{name}, m_Range{INVALID_RANGE}, m_Metadata{metadata}, m_TimeSerie{
62 nullptr}
62 nullptr}
63 {
63 {
64 switch(findDataSeriesType(metadata))
64 switch(findDataSeriesType(metadata))
65 {
65 {
66 case DataSeriesType::SCALAR:
66 case DataSeriesType::SCALAR:
67 m_TimeSerie = std::make_shared<ScalarTimeSerie>(ScalarTimeSerie{});
67 m_TimeSerie = std::make_shared<ScalarTimeSerie>(ScalarTimeSerie{});
68 break;
68 break;
69 case DataSeriesType::VECTOR:
69 case DataSeriesType::VECTOR:
70 m_TimeSerie = std::make_shared<VectorTimeSerie>(VectorTimeSerie{});
70 m_TimeSerie = std::make_shared<VectorTimeSerie>(VectorTimeSerie{});
71 break;
71 break;
72 case DataSeriesType::SPECTROGRAM:
72 case DataSeriesType::SPECTROGRAM:
73 m_TimeSerie =
73 m_TimeSerie =
74 std::make_shared<SpectrogramTimeSerie>(SpectrogramTimeSerie{});
74 std::make_shared<SpectrogramTimeSerie>(SpectrogramTimeSerie{});
75 break;
75 break;
76 case DataSeriesType::MULTICOMPONENT:
76 case DataSeriesType::MULTICOMPONENT:
77 {
77 {
78 std::size_t count = metadata.value(QString("size"), 0).toInt();
78 std::size_t count = metadata.value(QString("size"), 0).toInt();
79 m_TimeSerie = std::make_shared<MultiComponentTimeSerie>(
79 m_TimeSerie = std::make_shared<MultiComponentTimeSerie>(
80 MultiComponentTimeSerie{{0, count}});
80 MultiComponentTimeSerie{{0, count}});
81 }
81 }
82 break;
82 break;
83 default: break;
83 default: break;
84 }
84 }
85 }
85 }
86
86
87 VariablePrivate(const VariablePrivate& other)
87 VariablePrivate(const VariablePrivate& other)
88 : m_Name{other.m_Name}, m_Range{other.m_Range},
88 : m_Name{other.m_Name}, m_Range{other.m_Range},
89 m_Metadata{other.m_Metadata}, m_RealRange{other.m_RealRange}
89 m_Metadata{other.m_Metadata}, m_RealRange{other.m_RealRange}
90 {
90 {
91 m_TimeSerie = clone_ts(other.m_TimeSerie);
91 m_TimeSerie = clone_ts(other.m_TimeSerie);
92 }
92 }
93
93
94 std::size_t nbPoints()
94 std::size_t nbPoints()
95 {
95 {
96 if(m_TimeSerie) return m_TimeSerie->size();
96 if(m_TimeSerie) return m_TimeSerie->size();
97 return 0;
97 return 0;
98 }
98 }
99 DataSeriesType type() const
99 DataSeriesType type() const
100 {
100 {
101 return DataSeriesTypeUtils::type(m_TimeSerie.get());
101 return DataSeriesTypeUtils::type(m_TimeSerie.get());
102 }
102 }
103
103
104 PROPERTY_(m_Name, name, setName, QString)
104 PROPERTY_(m_Name, name, setName, QString)
105 PROPERTY_(m_Range, range, setRange, DateTimeRange)
105 PROPERTY_(m_Range, range, setRange, DateTimeRange)
106 PROPERTY_(m_Metadata, metadata, setMetadata, QVariantHash)
106 PROPERTY_(m_Metadata, metadata, setMetadata, QVariantHash)
107 PROPERTY_(m_RealRange, realRange, setRealRange, std::optional<DateTimeRange>)
107 PROPERTY_(m_RealRange, realRange, setRealRange, std::optional<DateTimeRange>)
108 std::shared_ptr<TimeSeries::ITimeSerie> dataSeries() { return m_TimeSerie; }
108 std::shared_ptr<TimeSeries::ITimeSerie> dataSeries() { return m_TimeSerie; }
109 void setDataSeries(std::shared_ptr<TimeSeries::ITimeSerie>&& timeSerie)
109 void setDataSeries(std::shared_ptr<TimeSeries::ITimeSerie>&& timeSerie)
110 {
110 {
111 QWriteLocker lock{&m_Lock};
111 QWriteLocker lock{&m_Lock};
112 m_TimeSerie = timeSerie;
112 m_TimeSerie = timeSerie;
113 if(m_TimeSerie) { setRealRange(DateTimeRange(m_TimeSerie->axis_range(0))); }
113 if(m_TimeSerie) { setRealRange(DateTimeRange(m_TimeSerie->axis_range(0))); }
114 else
114 else
115 {
115 {
116 setRealRange(std::nullopt);
116 setRealRange(std::nullopt);
117 }
117 }
118 }
118 }
119 std::shared_ptr<TimeSeries::ITimeSerie> m_TimeSerie;
119 std::shared_ptr<TimeSeries::ITimeSerie> m_TimeSerie;
120 QReadWriteLock m_Lock{QReadWriteLock::Recursive};
120 QReadWriteLock m_Lock{QReadWriteLock::Recursive};
121 };
121 };
122
122
123 Variable2::Variable2(const QString& name, const QVariantHash& metadata)
123 Variable2::Variable2(const QString& name, const QVariantHash& metadata)
124 : impl{spimpl::make_unique_impl<VariablePrivate>(name, metadata)},
124 : impl{spimpl::make_unique_impl<VariablePrivate>(name, metadata)},
125 _uuid{QUuid::createUuid()}
125 _uuid{QUuid::createUuid()}
126 {}
126 {}
127
127
128 Variable2::Variable2(const Variable2& other)
128 Variable2::Variable2(const Variable2& other)
129 : impl{spimpl::make_unique_impl<VariablePrivate>(*other.impl)},
129 : impl{spimpl::make_unique_impl<VariablePrivate>(*other.impl)},
130 _uuid{QUuid::createUuid()} // is a clone but must have a != uuid
130 _uuid{QUuid::createUuid()} // is a clone but must have a != uuid
131 {}
131 {}
132
132
133 std::shared_ptr<Variable2> Variable2::clone() const
133 std::shared_ptr<Variable2> Variable2::clone() const
134 {
134 {
135 return std::make_shared<Variable2>(*this);
135 return std::make_shared<Variable2>(*this);
136 }
136 }
137
137
138 V_FW_GETTER_SETTER(name, setName, QString)
138 V_FW_GETTER_SETTER(name, setName, QString)
139
139
140 DateTimeRange Variable2::range() { return impl->range(); }
140 DateTimeRange Variable2::range() { return impl->range(); }
141
141
142 void Variable2::setRange(const DateTimeRange& range)
142 void Variable2::setRange(const DateTimeRange& range)
143 {
143 {
144 QWriteLocker lock{&m_lock};
144 QWriteLocker lock{&m_lock};
145 impl->setRange(range);
145 impl->setRange(range);
146 }
146 }
147
147
148 std::optional<DateTimeRange> Variable2::realRange()
148 std::optional<DateTimeRange> Variable2::realRange()
149 {
149 {
150 QReadLocker lock{&m_lock};
150 QReadLocker lock{&m_lock};
151 return impl->realRange();
151 return impl->realRange();
152 }
152 }
153
153
154 std::size_t Variable2::nbPoints() { return impl->nbPoints(); }
154 std::size_t Variable2::nbPoints() { return impl->nbPoints(); }
155
155
156 std::shared_ptr<TimeSeries::ITimeSerie> Variable2::data()
156 std::shared_ptr<TimeSeries::ITimeSerie> Variable2::data()
157 {
157 {
158 return impl->dataSeries();
158 return impl->dataSeries();
159 }
159 }
160
160
161 DataSeriesType Variable2::type()
161 DataSeriesType Variable2::type()
162 {
162 {
163 QReadLocker lock{&m_lock};
163 QReadLocker lock{&m_lock};
164 return impl->type();
164 return impl->type();
165 }
165 }
166
166
167 QVariantHash Variable2::metadata() const noexcept { return impl->metadata(); }
167 QVariantHash Variable2::metadata() const noexcept { return impl->metadata(); }
168
168
169 template<typename T>
169 template<typename T>
170 std::shared_ptr<TimeSeries::ITimeSerie>
170 std::shared_ptr<TimeSeries::ITimeSerie>
171 _merge(std::vector<TimeSeries::ITimeSerie*> source, const DateTimeRange& range)
171 _merge(std::vector<TimeSeries::ITimeSerie*> source, const DateTimeRange& range)
172 {
172 {
173 std::sort(std::begin(source), std::end(source),
173 std::sort(std::begin(source), std::end(source),
174 [](TimeSeries::ITimeSerie* a, TimeSeries::ITimeSerie* b) {
174 [](TimeSeries::ITimeSerie* a, TimeSeries::ITimeSerie* b) {
175 if(a->size() && b->size()) return a->t(0) < b->t(0);
175 if(a->size() && b->size()) return a->t(0) < b->t(0);
176 return false;
176 return false;
177 });
177 });
178 std::shared_ptr<TimeSeries::ITimeSerie> dest = std::make_shared<T>();
178 std::shared_ptr<TimeSeries::ITimeSerie> dest = std::make_shared<T>();
179 std::for_each(
179 std::for_each(
180 std::begin(source), std::end(source),
180 std::begin(source), std::end(source),
181 [&dest, &range](TimeSeries::ITimeSerie* serie) {
181 [&dest, &range](TimeSeries::ITimeSerie* serie) {
182 auto& ts = *static_cast<T*>(serie);
182 auto& ts = *static_cast<T*>(serie);
183 auto last_t = range.m_TStart;
183 auto last_t = range.m_TStart;
184 if(dest->size()) last_t = dest->axis(0).back();
184 if(dest->size()) last_t = dest->axis(0).back();
185 if(ts.size())
185 if(ts.size())
186 {
186 {
187 std::copy(std::upper_bound(
187 std::copy(std::upper_bound(
188 std::begin(ts), std::end(ts), last_t,
188 std::begin(ts), std::end(ts), last_t,
189 [](const auto& a, const auto& b) { return a < b.t(); }),
189 [](const auto& a, const auto& b) { return a < b.t(); }),
190 std::lower_bound(
190 std::lower_bound(
191 std::begin(ts), std::end(ts), range.m_TEnd,
191 std::begin(ts), std::end(ts), range.m_TEnd,
192 [](const auto& a, const auto& b) { return a.t() < b; }),
192 [](const auto& a, const auto& b) { return a.t() < b; }),
193 std::back_inserter(*std::dynamic_pointer_cast<T>(dest)));
193 std::back_inserter(*std::dynamic_pointer_cast<T>(dest)));
194 }
194 }
195 });
195 });
196 if(source.size())
196 if(source.size())
197 {
197 {
198 const auto& first = *source.begin();
198 const auto& first = *source.begin();
199 for(std::size_t ax_index = 1; ax_index < first->shape().size(); ax_index++)
199 for(std::size_t ax_index = 1; ax_index < first->shape().size(); ax_index++)
200 {
200 {
201 const auto& ax = first->axis(ax_index);
201 const auto& ax = first->axis(ax_index);
202 std::copy(std::cbegin(ax), std::cend(ax),
202 std::copy(std::cbegin(ax), std::cend(ax),
203 std::back_inserter(dest->axis(ax_index)));
203 std::back_inserter(dest->axis(ax_index)));
204 }
204 }
205 }
205 }
206 if constexpr(std::is_same_v<T, SpectrogramTimeSerie>)
207 {
208 auto d = std::dynamic_pointer_cast<SpectrogramTimeSerie>(dest);
209 if(std::isnan(d->max_sampling))
210 {
211 std::for_each(std::begin(source), std::end(source), [&d](auto src) {
212 auto s = dynamic_cast<SpectrogramTimeSerie*>(src);
213 if(!std::isnan(s->max_sampling)) { d->max_sampling = s->max_sampling; }
214 if(!std::isnan(s->min_sampling)) { d->min_sampling = s->min_sampling; }
215 });
216 }
217 }
206 return dest;
218 return dest;
207 }
219 }
208
220
209 std::shared_ptr<TimeSeries::ITimeSerie>
221 std::shared_ptr<TimeSeries::ITimeSerie>
210 merge(const std::vector<TimeSeries::ITimeSerie*>& dataSeries,
222 merge(const std::vector<TimeSeries::ITimeSerie*>& dataSeries,
211 const DateTimeRange& range)
223 const DateTimeRange& range)
212 {
224 {
213 if(dynamic_cast<ScalarTimeSerie*>(dataSeries.front()))
225 if(dynamic_cast<ScalarTimeSerie*>(dataSeries.front()))
214 return _merge<ScalarTimeSerie>(dataSeries, range);
226 return _merge<ScalarTimeSerie>(dataSeries, range);
215 if(dynamic_cast<VectorTimeSerie*>(dataSeries.front()))
227 if(dynamic_cast<VectorTimeSerie*>(dataSeries.front()))
216 return _merge<VectorTimeSerie>(dataSeries, range);
228 return _merge<VectorTimeSerie>(dataSeries, range);
217 if(dynamic_cast<MultiComponentTimeSerie*>(dataSeries.front()))
229 if(dynamic_cast<MultiComponentTimeSerie*>(dataSeries.front()))
218 return _merge<MultiComponentTimeSerie>(dataSeries, range);
230 return _merge<MultiComponentTimeSerie>(dataSeries, range);
219 if(dynamic_cast<SpectrogramTimeSerie*>(dataSeries.front()))
231 if(dynamic_cast<SpectrogramTimeSerie*>(dataSeries.front()))
220 return _merge<SpectrogramTimeSerie>(dataSeries, range);
232 return _merge<SpectrogramTimeSerie>(dataSeries, range);
221 return std::shared_ptr<TimeSeries::ITimeSerie>{};
233 return std::shared_ptr<TimeSeries::ITimeSerie>{};
222 }
234 }
223
235
224 void Variable2::setData(const std::vector<TimeSeries::ITimeSerie*>& dataSeries,
236 void Variable2::setData(const std::vector<TimeSeries::ITimeSerie*>& dataSeries,
225 const DateTimeRange& range, bool notify)
237 const DateTimeRange& range, bool notify)
226 {
238 {
227 if(dataSeries.size())
239 if(dataSeries.size())
228 {
240 {
229 {
241 {
230 QWriteLocker lock{&m_lock};
242 QWriteLocker lock{&m_lock};
231 impl->setDataSeries(merge(dataSeries, range));
243 impl->setDataSeries(merge(dataSeries, range));
232 impl->setRange(range);
244 impl->setRange(range);
233 }
245 }
234 if(notify) emit this->updated(this->ID());
246 if(notify) emit this->updated(this->ID());
235 }
247 }
236 }
248 }
@@ -1,447 +1,448
1 #include "Variable/VariableController2.h"
1 #include "Variable/VariableController2.h"
2
2
3 #include "Variable/VariableSynchronizationGroup2.h"
3 #include "Variable/VariableSynchronizationGroup2.h"
4
4
5 #include <Common/containers.h>
5 #include <Common/containers.h>
6 #include <Common/debug.h>
6 #include <Common/debug.h>
7 #include <Data/DataProviderParameters.h>
7 #include <Data/DataProviderParameters.h>
8 #include <Data/DateTimeRange.h>
8 #include <Data/DateTimeRange.h>
9 #include <Data/DateTimeRangeHelper.h>
9 #include <Data/DateTimeRangeHelper.h>
10 #include <QCoreApplication>
10 #include <QCoreApplication>
11 #include <QDataStream>
11 #include <QDataStream>
12 #include <QObject>
12 #include <QObject>
13 #include <QQueue>
13 #include <QQueue>
14 #include <QRunnable>
14 #include <QRunnable>
15 #include <QThreadPool>
15 #include <QThreadPool>
16 #include <Variable/private/VCTransaction.h>
16 #include <Variable/private/VCTransaction.h>
17
17
18 class VariableController2::VariableController2Private
18 class VariableController2::VariableController2Private
19 {
19 {
20 struct threadSafeVaraiblesMaps
20 struct threadSafeVaraiblesMaps
21 {
21 {
22 inline void
22 inline void
23 addVariable(const std::shared_ptr<Variable2>& variable,
23 addVariable(const std::shared_ptr<Variable2>& variable,
24 const std::shared_ptr<IDataProvider>& provider,
24 const std::shared_ptr<IDataProvider>& provider,
25 const std::shared_ptr<VariableSynchronizationGroup2>&
25 const std::shared_ptr<VariableSynchronizationGroup2>&
26 synchronizationGroup)
26 synchronizationGroup)
27 {
27 {
28 QWriteLocker lock{&_lock};
28 QWriteLocker lock{&_lock};
29 _variables[*variable] = variable;
29 _variables[*variable] = variable;
30 _providers[*variable] = provider;
30 _providers[*variable] = provider;
31 _synchronizationGroups[*variable] = synchronizationGroup;
31 _synchronizationGroups[*variable] = synchronizationGroup;
32 }
32 }
33
33
34 inline void removeVariable(const std::shared_ptr<Variable2>& variable)
34 inline void removeVariable(const std::shared_ptr<Variable2>& variable)
35 {
35 {
36 QWriteLocker lock{&_lock};
36 QWriteLocker lock{&_lock};
37 _variables.erase(*variable);
37 _variables.erase(*variable);
38 _providers.remove(*variable);
38 _providers.remove(*variable);
39 _synchronizationGroups.remove(*variable);
39 _synchronizationGroups.remove(*variable);
40 }
40 }
41
41
42 inline void
42 inline void
43 synchronize(const std::shared_ptr<Variable2>& variable,
43 synchronize(const std::shared_ptr<Variable2>& variable,
44 const std::optional<std::shared_ptr<Variable2>>& with)
44 const std::optional<std::shared_ptr<Variable2>>& with)
45 {
45 {
46 QWriteLocker lock{&_lock};
46 QWriteLocker lock{&_lock};
47 if(with.has_value())
47 if(with.has_value())
48 {
48 {
49 auto newGroup = _synchronizationGroups[*with.value()];
49 auto newGroup = _synchronizationGroups[*with.value()];
50 newGroup->addVariable(*variable);
50 newGroup->addVariable(*variable);
51 _synchronizationGroups[*variable] = newGroup;
51 _synchronizationGroups[*variable] = newGroup;
52 }
52 }
53 else
53 else
54 {
54 {
55 _synchronizationGroups[*variable] =
55 _synchronizationGroups[*variable] =
56 std::make_shared<VariableSynchronizationGroup2>(*variable);
56 std::make_shared<VariableSynchronizationGroup2>(*variable);
57 }
57 }
58 }
58 }
59
59
60 inline std::shared_ptr<Variable2> variable(QUuid variable)
60 inline std::shared_ptr<Variable2> variable(QUuid variable)
61 {
61 {
62 QReadLocker lock{&_lock};
62 QReadLocker lock{&_lock};
63 auto it = _variables.find(variable);
63 auto it = _variables.find(variable);
64 #if __cplusplus > 201703L
64 #if __cplusplus > 201703L
65 [[unlikely]]
65 [[unlikely]]
66 #endif
66 #endif
67 if(it == _variables.end())
67 if(it == _variables.end())
68 SCIQLOP_ERROR(threadSafeVaraiblesMaps, "Unknown Variable");
68 SCIQLOP_ERROR(threadSafeVaraiblesMaps, "Unknown Variable");
69 return (*it).second;
69 return (*it).second;
70 }
70 }
71
71
72 inline std::shared_ptr<Variable2> variable(int index)
72 inline std::shared_ptr<Variable2> variable(int index)
73 {
73 {
74 QReadLocker lock{&_lock};
74 QReadLocker lock{&_lock};
75 #if __cplusplus > 201703L
75 #if __cplusplus > 201703L
76 [[unlikely]]
76 [[unlikely]]
77 #endif
77 #endif
78 if(!_variables.size() > index)
78 if(!_variables.size() > index)
79 SCIQLOP_ERROR(threadSafeVaraiblesMaps, "Index is out of bounds");
79 SCIQLOP_ERROR(threadSafeVaraiblesMaps, "Index is out of bounds");
80 auto it = _variables.cbegin();
80 auto it = _variables.cbegin();
81 while(index != 0)
81 while(index != 0)
82 {
82 {
83 index -= 1;
83 index -= 1;
84 it++;
84 it++;
85 }
85 }
86 return (*(it)).second;
86 return (*(it)).second;
87 }
87 }
88
88
89 inline const std::vector<std::shared_ptr<Variable2>> variables()
89 inline const std::vector<std::shared_ptr<Variable2>> variables()
90 {
90 {
91 std::vector<std::shared_ptr<Variable2>> vars;
91 std::vector<std::shared_ptr<Variable2>> vars;
92 QReadLocker lock{&_lock};
92 QReadLocker lock{&_lock};
93 for(const auto& [id, var] : _variables)
93 for(const auto& [id, var] : _variables)
94 {
94 {
95 vars.push_back(var);
95 vars.push_back(var);
96 }
96 }
97 return vars;
97 return vars;
98 }
98 }
99
99
100 inline std::shared_ptr<IDataProvider> provider(QUuid variable)
100 inline std::shared_ptr<IDataProvider> provider(QUuid variable)
101 {
101 {
102 QReadLocker lock{&_lock};
102 QReadLocker lock{&_lock};
103 #if __cplusplus > 201703L
103 #if __cplusplus > 201703L
104 [[unlikely]]
104 [[unlikely]]
105 #endif
105 #endif
106 if(!_providers.contains(variable))
106 if(!_providers.contains(variable))
107 SCIQLOP_ERROR(threadSafeVaraiblesMaps, "Unknown Variable");
107 SCIQLOP_ERROR(threadSafeVaraiblesMaps, "Unknown Variable");
108 return _providers[variable];
108 return _providers[variable];
109 }
109 }
110
110
111 inline std::shared_ptr<VariableSynchronizationGroup2> group(QUuid variable)
111 inline std::shared_ptr<VariableSynchronizationGroup2> group(QUuid variable)
112 {
112 {
113 QReadLocker lock{&_lock};
113 QReadLocker lock{&_lock};
114 #if __cplusplus > 201703L
114 #if __cplusplus > 201703L
115 [[unlikely]]
115 [[unlikely]]
116 #endif
116 #endif
117 if(!_synchronizationGroups.contains(variable))
117 if(!_synchronizationGroups.contains(variable))
118 SCIQLOP_ERROR(threadSafeVaraiblesMaps, "Unknown Variable");
118 SCIQLOP_ERROR(threadSafeVaraiblesMaps, "Unknown Variable");
119 return _synchronizationGroups[variable];
119 return _synchronizationGroups[variable];
120 }
120 }
121
121
122 inline bool has(const std::shared_ptr<Variable2>& variable)
122 inline bool has(const std::shared_ptr<Variable2>& variable)
123 {
123 {
124 QReadLocker lock{&_lock};
124 QReadLocker lock{&_lock};
125 return _variables.find(*variable) == _variables.end();
125 return _variables.find(*variable) == _variables.end();
126 }
126 }
127
127
128 private:
128 private:
129 std::map<QUuid, std::shared_ptr<Variable2>> _variables;
129 std::map<QUuid, std::shared_ptr<Variable2>> _variables;
130 QMap<QUuid, std::shared_ptr<IDataProvider>> _providers;
130 QMap<QUuid, std::shared_ptr<IDataProvider>> _providers;
131 QMap<QUuid, std::shared_ptr<VariableSynchronizationGroup2>>
131 QMap<QUuid, std::shared_ptr<VariableSynchronizationGroup2>>
132 _synchronizationGroups;
132 _synchronizationGroups;
133 QReadWriteLock _lock{QReadWriteLock::Recursive};
133 QReadWriteLock _lock{QReadWriteLock::Recursive};
134 } _maps;
134 } _maps;
135 std::vector<QUuid> _variablesToRemove;
135 std::vector<QUuid> _variablesToRemove;
136 QThreadPool* _ThreadPool;
136 QThreadPool* _ThreadPool;
137 VCTransactionsQueues _transactions;
137 VCTransactionsQueues _transactions;
138
138
139 void _transactionComplete(QUuid group,
139 void _transactionComplete(QUuid group,
140 std::shared_ptr<VCTransaction> transaction)
140 std::shared_ptr<VCTransaction> transaction)
141 {
141 {
142 if(transaction->done()) { _transactions.complete(group); }
142 if(transaction->done()) { _transactions.complete(group); }
143 this->_processTransactions();
143 this->_processTransactions();
144 }
144 }
145
145
146 void _cleanupVariables()
146 void _cleanupVariables()
147 {
147 {
148 for(auto id : _variablesToRemove)
148 for(auto id : _variablesToRemove)
149 {
149 {
150 auto v = this->variable(id);
150 auto v = this->variable(id);
151 if(!hasPendingTransactions(v))
151 if(!hasPendingTransactions(v))
152 {
152 {
153 _variablesToRemove.erase(std::remove(_variablesToRemove.begin(),
153 _variablesToRemove.erase(std::remove(_variablesToRemove.begin(),
154 _variablesToRemove.end(), id),
154 _variablesToRemove.end(), id),
155 _variablesToRemove.end());
155 _variablesToRemove.end());
156 this->deleteVariable(v);
156 this->deleteVariable(v);
157 }
157 }
158 }
158 }
159 }
159 }
160
160
161 void _processTransactions(bool fragmented = false)
161 void _processTransactions(bool fragmented = false)
162 {
162 {
163 auto nextTransactions = _transactions.nextTransactions();
163 auto nextTransactions = _transactions.nextTransactions();
164 auto pendingTransactions = _transactions.pendingTransactions();
164 auto pendingTransactions = _transactions.pendingTransactions();
165 for(auto [groupID, newTransaction] : nextTransactions)
165 for(auto [groupID, newTransaction] : nextTransactions)
166 {
166 {
167 if(newTransaction.has_value() &&
167 if(newTransaction.has_value() &&
168 !pendingTransactions[groupID].has_value())
168 !pendingTransactions[groupID].has_value())
169 {
169 {
170 _transactions.start(groupID);
170 _transactions.start(groupID);
171 auto refVar = _maps.variable(newTransaction.value()->refVar);
171 auto refVar = _maps.variable(newTransaction.value()->refVar);
172 auto ranges =
172 auto ranges =
173 _computeAllRangesInGroup(refVar, newTransaction.value()->range);
173 _computeAllRangesInGroup(refVar, newTransaction.value()->range);
174 for(auto const& [ID, range] : ranges)
174 for(auto const& [ID, range] : ranges)
175 {
175 {
176 auto provider = _maps.provider(ID);
176 auto provider = _maps.provider(ID);
177 auto variable = _maps.variable(ID);
177 auto variable = _maps.variable(ID);
178 if(fragmented)
178 if(fragmented)
179 {
179 {
180 auto missingRanges = _computeMissingRanges(variable, range);
180 auto missingRanges = _computeMissingRanges(variable, range);
181
181
182 auto exe =
182 auto exe =
183 new TransactionExe(variable, provider, missingRanges, range);
183 new TransactionExe(variable, provider, missingRanges, range);
184 QObject::connect(
184 QObject::connect(
185 exe, &TransactionExe::transactionComplete,
185 exe, &TransactionExe::transactionComplete,
186 [groupID = groupID, transaction = newTransaction.value(),
186 [groupID = groupID, transaction = newTransaction.value(),
187 this]() { this->_transactionComplete(groupID, transaction); });
187 this]() { this->_transactionComplete(groupID, transaction); });
188 _ThreadPool->start(exe);
188 _ThreadPool->start(exe);
189 }
189 }
190 else
190 else
191 {
191 {
192 auto exe = new TransactionExe(variable, provider, {range}, range);
192 auto exe = new TransactionExe(variable, provider, {range}, range);
193 QObject::connect(
193 QObject::connect(
194 exe, &TransactionExe::transactionComplete,
194 exe, &TransactionExe::transactionComplete,
195 [groupID = groupID, transaction = newTransaction.value(),
195 [groupID = groupID, transaction = newTransaction.value(),
196 this]() { this->_transactionComplete(groupID, transaction); });
196 this]() { this->_transactionComplete(groupID, transaction); });
197 _ThreadPool->start(exe);
197 _ThreadPool->start(exe);
198 }
198 }
199 }
199 }
200 }
200 }
201 }
201 }
202 // after each transaction update we get a new distribution of idle and
202 // after each transaction update we get a new distribution of idle and
203 // working variables so we can delete variables which are waiting to be
203 // working variables so we can delete variables which are waiting to be
204 // deleted if they are now idle
204 // deleted if they are now idle
205 _cleanupVariables();
205 _cleanupVariables();
206 }
206 }
207
207
208 std::map<QUuid, DateTimeRange>
208 std::map<QUuid, DateTimeRange>
209 _computeAllRangesInGroup(const std::shared_ptr<Variable2>& refVar,
209 _computeAllRangesInGroup(const std::shared_ptr<Variable2>& refVar,
210 DateTimeRange r)
210 DateTimeRange r)
211 {
211 {
212 std::map<QUuid, DateTimeRange> ranges;
212 std::map<QUuid, DateTimeRange> ranges;
213 if(!DateTimeRangeHelper::hasnan(r))
213 if(!DateTimeRangeHelper::hasnan(r))
214 {
214 {
215 auto group = _maps.group(*refVar);
215 auto group = _maps.group(*refVar);
216 if(auto transformation =
216 if(auto transformation =
217 DateTimeRangeHelper::computeTransformation(refVar->range(), r);
217 DateTimeRangeHelper::computeTransformation(refVar->range(), r);
218 transformation.has_value())
218 transformation.has_value())
219 {
219 {
220 for(auto varId : group->variables())
220 for(auto varId : group->variables())
221 {
221 {
222 auto var = _maps.variable(varId);
222 auto var = _maps.variable(varId);
223 auto newRange = var->range().transform(transformation.value());
223 auto newRange = var->range().transform(transformation.value());
224 ranges[varId] = newRange;
224 ranges[varId] = newRange;
225 }
225 }
226 }
226 }
227 else // force new range to all variables -> may be weird if more than one
227 else // force new range to all variables -> may be weird if more than one
228 // var in the group
228 // var in the group
229 // @TODO ensure that there is no side effects
229 // @TODO ensure that there is no side effects
230 {
230 {
231 for(auto varId : group->variables())
231 for(auto varId : group->variables())
232 {
232 {
233 auto var = _maps.variable(varId);
233 auto var = _maps.variable(varId);
234 ranges[varId] = r;
234 ranges[varId] = r;
235 }
235 }
236 }
236 }
237 }
237 }
238 else
238 else
239 {
239 {
240 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
240 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
241 }
241 }
242 return ranges;
242 return ranges;
243 }
243 }
244
244
245 std::vector<DateTimeRange>
245 std::vector<DateTimeRange>
246 _computeMissingRanges(const std::shared_ptr<Variable2>& var, DateTimeRange r)
246 _computeMissingRanges(const std::shared_ptr<Variable2>& var, DateTimeRange r)
247 {
247 {
248 return r - var->range();
248 return r - var->range();
249 }
249 }
250
250
251 void _changeRange(QUuid id, DateTimeRange r)
251 void _changeRange(QUuid id, DateTimeRange r)
252 {
252 {
253 _changeRange(_maps.variable(id), r);
253 _changeRange(_maps.variable(id), r);
254 }
254 }
255 void _changeRange(const std::shared_ptr<Variable2>& var, DateTimeRange r)
255 void _changeRange(const std::shared_ptr<Variable2>& var, DateTimeRange r)
256 {
256 {
257 auto provider = _maps.provider(*var);
257 auto provider = _maps.provider(*var);
258 auto missingRanges = _computeMissingRanges(var, r);
258 auto missingRanges = _computeMissingRanges(var, r);
259 std::vector<TimeSeries::ITimeSerie*> data;
259 std::vector<TimeSeries::ITimeSerie*> data;
260 for(auto range : missingRanges)
260 for(auto range : missingRanges)
261 {
261 {
262 data.push_back(
262 data.push_back(
263 provider->getData(DataProviderParameters{{range}, var->metadata()}));
263 provider->getData(DataProviderParameters{{range}, var->metadata()}));
264 }
264 }
265 data.push_back(var->data().get()); // might be smarter
265 data.push_back(var->data().get()); // might be smarter
266 var->setData(data, r, true);
266 var->setData(data, r, true);
267 std::for_each(std::begin(data), std::end(data), [](auto ts) { delete ts; });
267 }
268 }
268
269
269 public:
270 public:
270 VariableController2Private(QObject* parent = Q_NULLPTR)
271 VariableController2Private(QObject* parent = Q_NULLPTR)
271 {
272 {
272 Q_UNUSED(parent);
273 Q_UNUSED(parent);
273 this->_ThreadPool = new QThreadPool();
274 this->_ThreadPool = new QThreadPool();
274 this->_ThreadPool->setMaxThreadCount(32);
275 this->_ThreadPool->setMaxThreadCount(32);
275 }
276 }
276
277
277 /*
278 /*
278 * This dtor has to like this even if this is ugly, because default dtor would
279 * This dtor has to like this even if this is ugly, because default dtor would
279 * rely on declaration order to destruct members and that would always lead to
280 * rely on declaration order to destruct members and that would always lead to
280 * regressions when modifying class members
281 * regressions when modifying class members
281 */
282 */
282 ~VariableController2Private() { delete this->_ThreadPool; }
283 ~VariableController2Private() { delete this->_ThreadPool; }
283
284
284 std::shared_ptr<Variable2>
285 std::shared_ptr<Variable2>
285 createVariable(const QString& name, const QVariantHash& metadata,
286 createVariable(const QString& name, const QVariantHash& metadata,
286 std::shared_ptr<IDataProvider> provider)
287 std::shared_ptr<IDataProvider> provider)
287 {
288 {
288 auto newVar = std::make_shared<Variable2>(name, metadata);
289 auto newVar = std::make_shared<Variable2>(name, metadata);
289 auto group = std::make_shared<VariableSynchronizationGroup2>(newVar->ID());
290 auto group = std::make_shared<VariableSynchronizationGroup2>(newVar->ID());
290 _maps.addVariable(newVar, std::move(provider), group);
291 _maps.addVariable(newVar, std::move(provider), group);
291 this->_transactions.addEntry(*group);
292 this->_transactions.addEntry(*group);
292 return newVar;
293 return newVar;
293 }
294 }
294
295
295 std::shared_ptr<Variable2> variable(QUuid ID) { return _maps.variable(ID); }
296 std::shared_ptr<Variable2> variable(QUuid ID) { return _maps.variable(ID); }
296
297
297 std::shared_ptr<Variable2> variable(int index)
298 std::shared_ptr<Variable2> variable(int index)
298 {
299 {
299 return _maps.variable(index);
300 return _maps.variable(index);
300 }
301 }
301
302
302 std::shared_ptr<Variable2>
303 std::shared_ptr<Variable2>
303 cloneVariable(const std::shared_ptr<Variable2>& variable)
304 cloneVariable(const std::shared_ptr<Variable2>& variable)
304 {
305 {
305 auto newVar = variable->clone();
306 auto newVar = variable->clone();
306 _maps.synchronize(newVar, std::nullopt);
307 _maps.synchronize(newVar, std::nullopt);
307 _maps.addVariable(newVar, _maps.provider(*variable), _maps.group(*newVar));
308 _maps.addVariable(newVar, _maps.provider(*variable), _maps.group(*newVar));
308 this->_transactions.addEntry(*_maps.group(*newVar));
309 this->_transactions.addEntry(*_maps.group(*newVar));
309 return newVar;
310 return newVar;
310 }
311 }
311
312
312 bool hasPendingTransactions(const std::shared_ptr<Variable2>& variable)
313 bool hasPendingTransactions(const std::shared_ptr<Variable2>& variable)
313 {
314 {
314 return _transactions.active(*_maps.group(*variable));
315 return _transactions.active(*_maps.group(*variable));
315 }
316 }
316
317
317 bool hasPendingTransactions()
318 bool hasPendingTransactions()
318 {
319 {
319 bool has = false;
320 bool has = false;
320 for(const auto& var : _maps.variables())
321 for(const auto& var : _maps.variables())
321 {
322 {
322 has |= _transactions.active(*_maps.group(*var));
323 has |= _transactions.active(*_maps.group(*var));
323 }
324 }
324 return has;
325 return has;
325 }
326 }
326
327
327 void deleteVariable(const std::shared_ptr<Variable2>& variable)
328 void deleteVariable(const std::shared_ptr<Variable2>& variable)
328 {
329 {
329 if(!hasPendingTransactions(variable))
330 if(!hasPendingTransactions(variable))
330 _maps.removeVariable(variable);
331 _maps.removeVariable(variable);
331 else
332 else
332 _variablesToRemove.push_back(variable->ID());
333 _variablesToRemove.push_back(variable->ID());
333 }
334 }
334
335
335 void asyncChangeRange(const std::shared_ptr<Variable2>& variable,
336 void asyncChangeRange(const std::shared_ptr<Variable2>& variable,
336 const DateTimeRange& r)
337 const DateTimeRange& r)
337 {
338 {
338 if(!DateTimeRangeHelper::hasnan(r))
339 if(!DateTimeRangeHelper::hasnan(r))
339 {
340 {
340 auto group = _maps.group(*variable);
341 auto group = _maps.group(*variable);
341 // Just overwrite next transaction
342 // Just overwrite next transaction
342 {
343 {
343 _transactions.enqueue(*group,
344 _transactions.enqueue(*group,
344 std::make_shared<VCTransaction>(
345 std::make_shared<VCTransaction>(
345 variable->ID(), r,
346 variable->ID(), r,
346 static_cast<int>(group->variables().size())));
347 static_cast<int>(group->variables().size())));
347 }
348 }
348 _processTransactions();
349 _processTransactions();
349 }
350 }
350 else
351 else
351 {
352 {
352 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
353 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
353 }
354 }
354 }
355 }
355
356
356 void changeRange(const std::shared_ptr<Variable2>& variable, DateTimeRange r)
357 void changeRange(const std::shared_ptr<Variable2>& variable, DateTimeRange r)
357 {
358 {
358 asyncChangeRange(variable, r);
359 asyncChangeRange(variable, r);
359 while(hasPendingTransactions(variable))
360 while(hasPendingTransactions(variable))
360 {
361 {
361 QCoreApplication::processEvents();
362 QCoreApplication::processEvents();
362 }
363 }
363 }
364 }
364
365
365 inline void synchronize(const std::shared_ptr<Variable2>& var,
366 inline void synchronize(const std::shared_ptr<Variable2>& var,
366 const std::shared_ptr<Variable2>& with)
367 const std::shared_ptr<Variable2>& with)
367 {
368 {
368 _maps.synchronize(var, with);
369 _maps.synchronize(var, with);
369 }
370 }
370
371
371 inline const std::vector<std::shared_ptr<Variable2>> variables()
372 inline const std::vector<std::shared_ptr<Variable2>> variables()
372 {
373 {
373 return _maps.variables();
374 return _maps.variables();
374 }
375 }
375 };
376 };
376
377
377 VariableController2::VariableController2()
378 VariableController2::VariableController2()
378 : impl{spimpl::make_unique_impl<VariableController2Private>()}
379 : impl{spimpl::make_unique_impl<VariableController2Private>()}
379 {}
380 {}
380
381
381 std::shared_ptr<Variable2> VariableController2::createVariable(
382 std::shared_ptr<Variable2> VariableController2::createVariable(
382 const QString& name, const QVariantHash& metadata,
383 const QString& name, const QVariantHash& metadata,
383 const std::shared_ptr<IDataProvider>& provider, const DateTimeRange& range)
384 const std::shared_ptr<IDataProvider>& provider, const DateTimeRange& range)
384 {
385 {
385 auto var = impl->createVariable(name, metadata, provider);
386 auto var = impl->createVariable(name, metadata, provider);
386 var->setRange(range); // even with no data this is it's range
387 var->setRange(range); // even with no data this is it's range
387 if(!DateTimeRangeHelper::hasnan(range))
388 if(!DateTimeRangeHelper::hasnan(range))
388 impl->asyncChangeRange(var, range);
389 impl->asyncChangeRange(var, range);
389 else
390 else
390 SCIQLOP_ERROR(VariableController2, "Creating a variable with default "
391 SCIQLOP_ERROR(VariableController2, "Creating a variable with default "
391 "constructed DateTimeRange is an error");
392 "constructed DateTimeRange is an error");
392 emit variableAdded(var);
393 emit variableAdded(var);
393 return var;
394 return var;
394 }
395 }
395
396
396 std::shared_ptr<Variable2>
397 std::shared_ptr<Variable2>
397 VariableController2::cloneVariable(const std::shared_ptr<Variable2>& variable)
398 VariableController2::cloneVariable(const std::shared_ptr<Variable2>& variable)
398 {
399 {
399 return impl->cloneVariable(variable);
400 return impl->cloneVariable(variable);
400 }
401 }
401
402
402 void VariableController2::deleteVariable(
403 void VariableController2::deleteVariable(
403 const std::shared_ptr<Variable2>& variable)
404 const std::shared_ptr<Variable2>& variable)
404 {
405 {
405 impl->deleteVariable(variable);
406 impl->deleteVariable(variable);
406 emit variableDeleted(variable);
407 emit variableDeleted(variable);
407 }
408 }
408
409
409 void VariableController2::changeRange(
410 void VariableController2::changeRange(
410 const std::shared_ptr<Variable2>& variable, const DateTimeRange& r)
411 const std::shared_ptr<Variable2>& variable, const DateTimeRange& r)
411 {
412 {
412 impl->changeRange(variable, r);
413 impl->changeRange(variable, r);
413 }
414 }
414
415
415 void VariableController2::asyncChangeRange(
416 void VariableController2::asyncChangeRange(
416 const std::shared_ptr<Variable2>& variable, const DateTimeRange& r)
417 const std::shared_ptr<Variable2>& variable, const DateTimeRange& r)
417 {
418 {
418 impl->asyncChangeRange(variable, r);
419 impl->asyncChangeRange(variable, r);
419 }
420 }
420
421
421 const std::vector<std::shared_ptr<Variable2>> VariableController2::variables()
422 const std::vector<std::shared_ptr<Variable2>> VariableController2::variables()
422 {
423 {
423 return impl->variables();
424 return impl->variables();
424 }
425 }
425
426
426 bool VariableController2::isReady(const std::shared_ptr<Variable2>& variable)
427 bool VariableController2::isReady(const std::shared_ptr<Variable2>& variable)
427 {
428 {
428 return !impl->hasPendingTransactions(variable);
429 return !impl->hasPendingTransactions(variable);
429 }
430 }
430
431
431 bool VariableController2::isReady() { return !impl->hasPendingTransactions(); }
432 bool VariableController2::isReady() { return !impl->hasPendingTransactions(); }
432
433
433 void VariableController2::synchronize(const std::shared_ptr<Variable2>& var,
434 void VariableController2::synchronize(const std::shared_ptr<Variable2>& var,
434 const std::shared_ptr<Variable2>& with)
435 const std::shared_ptr<Variable2>& with)
435 {
436 {
436 impl->synchronize(var, with);
437 impl->synchronize(var, with);
437 }
438 }
438
439
439 const std::vector<std::shared_ptr<Variable2>>
440 const std::vector<std::shared_ptr<Variable2>>
440 VariableController2::variables(const std::vector<QUuid>& ids)
441 VariableController2::variables(const std::vector<QUuid>& ids)
441 {
442 {
442 std::vector<std::shared_ptr<Variable2>> variables;
443 std::vector<std::shared_ptr<Variable2>> variables;
443 std::transform(std::cbegin(ids), std::cend(ids),
444 std::transform(std::cbegin(ids), std::cend(ids),
444 std::back_inserter(variables),
445 std::back_inserter(variables),
445 [this](const auto& id) { return impl->variable(id); });
446 [this](const auto& id) { return impl->variable(id); });
446 return variables;
447 return variables;
447 }
448 }
@@ -1,299 +1,302
1 #include "CoreWrappers.h"
1 #include "CoreWrappers.h"
2
2
3 #include "pywrappers_common.h"
3 #include "pywrappers_common.h"
4
4
5 #include <Common/debug.h>
5 #include <Data/DataSeriesType.h>
6 #include <Data/DataSeriesType.h>
6 #include <Data/IDataProvider.h>
7 #include <Data/IDataProvider.h>
7 #include <Network/Downloader.h>
8 #include <Network/Downloader.h>
8 #include <Time/TimeController.h>
9 #include <Time/TimeController.h>
9 #include <Variable/Variable2.h>
10 #include <Variable/Variable2.h>
10 #include <Variable/VariableController2.h>
11 #include <Variable/VariableController2.h>
11 #include <pybind11/chrono.h>
12 #include <pybind11/chrono.h>
12 #include <pybind11/embed.h>
13 #include <pybind11/embed.h>
13 #include <pybind11/functional.h>
14 #include <pybind11/functional.h>
14 #include <pybind11/numpy.h>
15 #include <pybind11/numpy.h>
15 #include <pybind11/operators.h>
16 #include <pybind11/operators.h>
16 #include <pybind11/pybind11.h>
17 #include <pybind11/pybind11.h>
17 #include <pybind11/stl.h>
18 #include <pybind11/stl.h>
18 #include <pybind11/stl_bind.h>
19 #include <pybind11/stl_bind.h>
19 #include <sstream>
20 #include <sstream>
20 #include <string>
21 #include <string>
21
22
22 namespace py = pybind11;
23 namespace py = pybind11;
23 using namespace std::chrono;
24 using namespace std::chrono;
24
25
25 template<typename T, typename U, bool row_major = true>
26 template<typename T, typename U, bool row_major = true>
26 void copy_vector(py::array_t<double>& t, py::array_t<double>& values, T& dest_t,
27 void copy_vector(py::array_t<double>& t, py::array_t<double>& values, T& dest_t,
27 U& dest_values)
28 U& dest_values)
28 {
29 {
29 auto t_view = t.unchecked<1>();
30 auto t_view = t.unchecked<1>();
30 auto values_view = values.unchecked<2>();
31 auto values_view = values.unchecked<2>();
31 for(std::size_t i = 0; i < t.size(); i++)
32 for(std::size_t i = 0; i < t.size(); i++)
32 {
33 {
33 dest_t[i] = t_view[i];
34 dest_t[i] = t_view[i];
34 dest_values[i] = {values_view(i, 0), values_view(i, 1), values_view(i, 2)};
35 dest_values[i] = {values_view(i, 0), values_view(i, 1), values_view(i, 2)};
35 }
36 }
36 }
37 }
37
38
38 template<typename T, typename U>
39 template<typename T, typename U>
39 void copy_scalar(py::array_t<double>& t, py::array_t<double>& values, T& dest_t,
40 void copy_scalar(py::array_t<double>& t, py::array_t<double>& values, T& dest_t,
40 U& dest_values)
41 U& dest_values)
41 {
42 {
42 auto t_view = t.unchecked<1>();
43 auto t_view = t.unchecked<1>();
43 if(values.ndim() == 1)
44 if(values.ndim() == 1)
44 {
45 {
45 auto values_view = values.unchecked<1>();
46 auto values_view = values.unchecked<1>();
46 for(std::size_t i = 0; i < t.size(); i++)
47 for(std::size_t i = 0; i < t.size(); i++)
47 {
48 {
48 dest_t[i] = t_view[i];
49 dest_t[i] = t_view[i];
49 dest_values[i] = values_view[i];
50 dest_values[i] = values_view[i];
50 }
51 }
51 }
52 }
52 else if(values.ndim() == 2 && values.shape(1) == 1)
53 else if(values.ndim() == 2 && values.shape(1) == 1)
53 {
54 {
54 auto values_view = values.unchecked<2>();
55 auto values_view = values.unchecked<2>();
55 for(std::size_t i = 0; i < t.size(); i++)
56 for(std::size_t i = 0; i < t.size(); i++)
56 {
57 {
57 dest_t[i] = t_view[i];
58 dest_t[i] = t_view[i];
58 dest_values[i] = values_view(i, 0);
59 dest_values[i] = values_view(i, 0);
59 }
60 }
60 }
61 }
61 }
62 }
62 template<typename T, typename U>
63 template<typename T, typename U>
63 void copy_multicomp(py::array_t<double>& t, py::array_t<double>& values,
64 void copy_multicomp(py::array_t<double>& t, py::array_t<double>& values,
64 T& dest_t, U& dest_values)
65 T& dest_t, U& dest_values)
65 {
66 {
66 auto t_view = t.unchecked<1>();
67 auto t_view = t.unchecked<1>();
67 auto values_view = values.unchecked<2>();
68 auto values_view = values.unchecked<2>();
68 const auto width = values.shape(1);
69 const auto width = values.shape(1);
69 for(std::size_t i = 0; i < t.size(); i++)
70 for(std::size_t i = 0; i < t.size(); i++)
70 {
71 {
71 dest_t[i] = t_view[i];
72 dest_t[i] = t_view[i];
72 for(int j = 0; j < width; j++)
73 for(int j = 0; j < width; j++)
73 {
74 {
74 dest_values[i * width + j] = values_view(i, j);
75 dest_values[i * width + j] = values_view(i, j);
75 }
76 }
76 }
77 }
77 }
78 }
78
79
79 template<typename T, typename U>
80 template<typename T, typename U>
80 void copy_spectro(py::array_t<double>& t, py::array_t<double>& y,
81 void copy_spectro(py::array_t<double>& t, py::array_t<double>& y,
81 py::array_t<double>& values, T& dest_t, T& dest_y,
82 py::array_t<double>& values, T& dest_t, T& dest_y,
82 U& dest_values)
83 U& dest_values)
83 {
84 {
84 auto t_view = t.unchecked<1>();
85 auto t_view = t.unchecked<1>();
85 auto y_view = y.unchecked<1>();
86 auto y_view = y.unchecked<1>();
86 auto values_view = values.unchecked<2>();
87 auto values_view = values.unchecked<2>();
87 const auto width = values.shape(1);
88 const auto width = values.shape(1);
88 for(std::size_t i = 0; i < y.size(); i++)
89 for(std::size_t i = 0; i < y.size(); i++)
89 {
90 {
90 dest_y[i] = y_view[i];
91 dest_y[i] = y_view[i];
91 }
92 }
92 for(std::size_t i = 0; i < t.size(); i++)
93 for(std::size_t i = 0; i < t.size(); i++)
93 {
94 {
94 dest_t[i] = t_view[i];
95 dest_t[i] = t_view[i];
95 for(int j = 0; j < width; j++)
96 for(int j = 0; j < width; j++)
96 {
97 {
97 dest_values[i * width + j] = values_view(i, j);
98 dest_values[i * width + j] = values_view(i, j);
98 }
99 }
99 }
100 }
100 }
101 }
101
102
102 PYBIND11_MODULE(pysciqlopcore, m)
103 PYBIND11_MODULE(pysciqlopcore, m)
103 {
104 {
104 pybind11::bind_vector<std::vector<double>>(m, "VectorDouble");
105 pybind11::bind_vector<std::vector<double>>(m, "VectorDouble");
105
106
106 py::enum_<DataSeriesType>(m, "DataSeriesType")
107 py::enum_<DataSeriesType>(m, "DataSeriesType")
107 .value("SCALAR", DataSeriesType::SCALAR)
108 .value("SCALAR", DataSeriesType::SCALAR)
108 .value("SPECTROGRAM", DataSeriesType::SPECTROGRAM)
109 .value("SPECTROGRAM", DataSeriesType::SPECTROGRAM)
109 .value("VECTOR", DataSeriesType::VECTOR)
110 .value("VECTOR", DataSeriesType::VECTOR)
110 .value("MULTICOMPONENT", DataSeriesType::MULTICOMPONENT)
111 .value("MULTICOMPONENT", DataSeriesType::MULTICOMPONENT)
111 .value("NONE", DataSeriesType::NONE)
112 .value("NONE", DataSeriesType::NONE)
112 .export_values();
113 .export_values();
113
114
114 py::class_<Response>(m, "Response")
115 py::class_<Response>(m, "Response")
115 .def("status_code", &Response::status_code);
116 .def("status_code", &Response::status_code);
116
117
117 py::class_<Downloader>(m, "Downloader")
118 py::class_<Downloader>(m, "Downloader")
118 .def_static("get", Downloader::get)
119 .def_static("get", Downloader::get)
119 .def_static("getAsync", Downloader::getAsync)
120 .def_static("getAsync", Downloader::getAsync)
120 .def_static("downloadFinished", Downloader::downloadFinished);
121 .def_static("downloadFinished", Downloader::downloadFinished);
121
122
122 py::class_<IDataProvider, std::shared_ptr<IDataProvider>>(m, "IDataProvider");
123 py::class_<IDataProvider, std::shared_ptr<IDataProvider>>(m, "IDataProvider");
123
124
124 py::class_<TimeSeries::ITimeSerie, std::shared_ptr<TimeSeries::ITimeSerie>>(
125 py::class_<TimeSeries::ITimeSerie, std::shared_ptr<TimeSeries::ITimeSerie>>(
125 m, "ITimeSerie")
126 m, "ITimeSerie")
126 .def_property_readonly(
127 .def_property_readonly(
127 "size", [](const TimeSeries::ITimeSerie& ts) { return ts.size(); })
128 "size", [](const TimeSeries::ITimeSerie& ts) { return ts.size(); })
128 .def("__len__",
129 .def("__len__",
129 [](const TimeSeries::ITimeSerie& ts) { return ts.size(); })
130 [](const TimeSeries::ITimeSerie& ts) { return ts.size(); })
130 .def_property_readonly(
131 .def_property_readonly(
131 "shape", [](const TimeSeries::ITimeSerie& ts) { return ts.shape(); })
132 "shape", [](const TimeSeries::ITimeSerie& ts) { return ts.shape(); })
132 .def_property_readonly(
133 .def_property_readonly(
133 "t",
134 "t",
134 [](TimeSeries::ITimeSerie& ts) -> decltype(ts.axis(0))& {
135 [](TimeSeries::ITimeSerie& ts) -> decltype(ts.axis(0))& {
135 return ts.axis(0);
136 return ts.axis(0);
136 },
137 },
137 py::return_value_policy::reference)
138 py::return_value_policy::reference)
138 .def(
139 .def(
139 "axis",
140 "axis",
140 [](TimeSeries::ITimeSerie& ts, unsigned int index)
141 [](TimeSeries::ITimeSerie& ts, unsigned int index)
141 -> decltype(ts.axis(0))& { return ts.axis(index); },
142 -> decltype(ts.axis(0))& { return ts.axis(index); },
142 py::return_value_policy::reference);
143 py::return_value_policy::reference);
143
144
144 py::class_<ScalarTimeSerie, TimeSeries::ITimeSerie,
145 py::class_<ScalarTimeSerie, TimeSeries::ITimeSerie,
145 std::shared_ptr<ScalarTimeSerie>>(m, "ScalarTimeSerie")
146 std::shared_ptr<ScalarTimeSerie>>(m, "ScalarTimeSerie")
146 .def(py::init<>())
147 .def(py::init<>())
147 .def(py::init<std::size_t>())
148 .def(py::init<std::size_t>())
148 .def(py::init([](py::array_t<double> t, py::array_t<double> values) {
149 .def(py::init([](py::array_t<double> t, py::array_t<double> values) {
149 assert(t.size() == values.size());
150 assert(t.size() == values.size());
150 ScalarTimeSerie::axis_t _t(t.size());
151 ScalarTimeSerie::axis_t _t(t.size());
151 ScalarTimeSerie::axis_t _values(t.size());
152 ScalarTimeSerie::axis_t _values(t.size());
152 copy_scalar(t, values, _t, _values);
153 copy_scalar(t, values, _t, _values);
153 return ScalarTimeSerie(_t, _values);
154 return ScalarTimeSerie(_t, _values);
154 }))
155 }))
155 .def("__getitem__",
156 .def("__getitem__",
156 [](ScalarTimeSerie& ts, std::size_t key) { return ts[key]; })
157 [](ScalarTimeSerie& ts, std::size_t key) { return ts[key]; })
157 .def("__setitem__", [](ScalarTimeSerie& ts, std::size_t key,
158 .def("__setitem__", [](ScalarTimeSerie& ts, std::size_t key,
158 double value) { *(ts.begin() + key) = value; });
159 double value) { *(ts.begin() + key) = value; });
159
160
160 py::class_<VectorTimeSerie::raw_value_type>(m, "vector")
161 py::class_<VectorTimeSerie::raw_value_type>(m, "vector")
161 .def(py::init<>())
162 .def(py::init<>())
162 .def(py::init<double, double, double>())
163 .def(py::init<double, double, double>())
163 .def("__repr__", __repr__<VectorTimeSerie::raw_value_type>)
164 .def("__repr__", __repr__<VectorTimeSerie::raw_value_type>)
164 .def_readwrite("x", &VectorTimeSerie::raw_value_type::x)
165 .def_readwrite("x", &VectorTimeSerie::raw_value_type::x)
165 .def_readwrite("y", &VectorTimeSerie::raw_value_type::y)
166 .def_readwrite("y", &VectorTimeSerie::raw_value_type::y)
166 .def_readwrite("z", &VectorTimeSerie::raw_value_type::z);
167 .def_readwrite("z", &VectorTimeSerie::raw_value_type::z);
167
168
168 py::class_<VectorTimeSerie, TimeSeries::ITimeSerie,
169 py::class_<VectorTimeSerie, TimeSeries::ITimeSerie,
169 std::shared_ptr<VectorTimeSerie>>(m, "VectorTimeSerie")
170 std::shared_ptr<VectorTimeSerie>>(m, "VectorTimeSerie")
170 .def(py::init<>())
171 .def(py::init<>())
171 .def(py::init<std::size_t>())
172 .def(py::init<std::size_t>())
172 .def(py::init([](py::array_t<double> t, py::array_t<double> values) {
173 .def(py::init([](py::array_t<double> t, py::array_t<double> values) {
173 assert(t.size() * 3 == values.size());
174 assert(t.size() * 3 == values.size());
174 VectorTimeSerie::axis_t _t(t.size());
175 VectorTimeSerie::axis_t _t(t.size());
175 VectorTimeSerie::container_type<VectorTimeSerie::raw_value_type>
176 VectorTimeSerie::container_type<VectorTimeSerie::raw_value_type>
176 _values(t.size());
177 _values(t.size());
177 copy_vector(t, values, _t, _values);
178 copy_vector(t, values, _t, _values);
178 return VectorTimeSerie(_t, _values);
179 return VectorTimeSerie(_t, _values);
179 }))
180 }))
180 .def(
181 .def(
181 "__getitem__",
182 "__getitem__",
182 [](VectorTimeSerie& ts, std::size_t key)
183 [](VectorTimeSerie& ts, std::size_t key)
183 -> VectorTimeSerie::raw_value_type& { return ts[key]; },
184 -> VectorTimeSerie::raw_value_type& { return ts[key]; },
184 py::return_value_policy::reference)
185 py::return_value_policy::reference)
185 .def("__setitem__", [](VectorTimeSerie& ts, std::size_t key,
186 .def("__setitem__", [](VectorTimeSerie& ts, std::size_t key,
186 VectorTimeSerie::raw_value_type value) {
187 VectorTimeSerie::raw_value_type value) {
187 *(ts.begin() + key) = value;
188 *(ts.begin() + key) = value;
188 });
189 });
189
190
190 py::class_<MultiComponentTimeSerie::iterator_t>(m,
191 py::class_<MultiComponentTimeSerie::iterator_t>(m,
191 "MultiComponentTimeSerieItem")
192 "MultiComponentTimeSerieItem")
192 .def("__getitem__", [](MultiComponentTimeSerie::iterator_t& self,
193 .def("__getitem__", [](MultiComponentTimeSerie::iterator_t& self,
193 std::size_t key) { return (*self)[key]; })
194 std::size_t key) { return (*self)[key]; })
194 .def("__setitem__",
195 .def("__setitem__",
195 [](MultiComponentTimeSerie::iterator_t& self, std::size_t key,
196 [](MultiComponentTimeSerie::iterator_t& self, std::size_t key,
196 double value) { (*self)[key] = value; });
197 double value) { (*self)[key] = value; });
197
198
198 py::class_<MultiComponentTimeSerie, TimeSeries::ITimeSerie,
199 py::class_<MultiComponentTimeSerie, TimeSeries::ITimeSerie,
199 std::shared_ptr<MultiComponentTimeSerie>>(
200 std::shared_ptr<MultiComponentTimeSerie>>(
200 m, "MultiComponentTimeSerie")
201 m, "MultiComponentTimeSerie")
201 .def(py::init<>())
202 .def(py::init<>())
202 .def(py::init<const std::vector<std::size_t>>())
203 .def(py::init<const std::vector<std::size_t>>())
203 .def(py::init([](py::array_t<double> t, py::array_t<double> values) {
204 .def(py::init([](py::array_t<double> t, py::array_t<double> values) {
204 assert((t.size() < values.size()) |
205 assert((t.size() < values.size()) |
205 (t.size() == 0)); // TODO check geometry
206 (t.size() == 0)); // TODO check geometry
206 MultiComponentTimeSerie::axis_t _t(t.size());
207 MultiComponentTimeSerie::axis_t _t(t.size());
207 MultiComponentTimeSerie::container_type<
208 MultiComponentTimeSerie::container_type<
208 MultiComponentTimeSerie::raw_value_type>
209 MultiComponentTimeSerie::raw_value_type>
209 _values(values.size());
210 _values(values.size());
210 copy_multicomp(t, values, _t, _values);
211 copy_multicomp(t, values, _t, _values);
211 std::vector<std::size_t> shape;
212 std::vector<std::size_t> shape;
212 shape.push_back(values.shape(0));
213 shape.push_back(values.shape(0));
213 shape.push_back(values.shape(1));
214 shape.push_back(values.shape(1));
214 return MultiComponentTimeSerie(_t, _values, shape);
215 return MultiComponentTimeSerie(_t, _values, shape);
215 }))
216 }))
216 .def("__getitem__",
217 .def("__getitem__",
217 [](MultiComponentTimeSerie& ts,
218 [](MultiComponentTimeSerie& ts,
218 std::size_t key) -> MultiComponentTimeSerie::iterator_t {
219 std::size_t key) -> MultiComponentTimeSerie::iterator_t {
219 return ts.begin() + key;
220 return ts.begin() + key;
220 });
221 });
221
222
222 py::class_<SpectrogramTimeSerie::iterator_t>(m, "SpectrogramTimeSerieItem")
223 py::class_<SpectrogramTimeSerie::iterator_t>(m, "SpectrogramTimeSerieItem")
223 .def("__getitem__", [](SpectrogramTimeSerie::iterator_t& self,
224 .def("__getitem__", [](SpectrogramTimeSerie::iterator_t& self,
224 std::size_t key) { return (*self)[key]; })
225 std::size_t key) { return (*self)[key]; })
225 .def("__setitem__",
226 .def("__setitem__",
226 [](SpectrogramTimeSerie::iterator_t& self, std::size_t key,
227 [](SpectrogramTimeSerie::iterator_t& self, std::size_t key,
227 double value) { (*self)[key] = value; });
228 double value) { (*self)[key] = value; });
228
229
229 py::class_<SpectrogramTimeSerie, TimeSeries::ITimeSerie,
230 py::class_<SpectrogramTimeSerie, TimeSeries::ITimeSerie,
230 std::shared_ptr<SpectrogramTimeSerie>>(m, "SpectrogramTimeSerie")
231 std::shared_ptr<SpectrogramTimeSerie>>(m, "SpectrogramTimeSerie")
231 .def(py::init<>())
232 .def(py::init<>())
232 .def(py::init<const std::vector<std::size_t>>())
233 .def(py::init<const std::vector<std::size_t>>())
233 .def(py::init([](py::array_t<double> t, py::array_t<double> y,
234 .def(py::init([](py::array_t<double> t, py::array_t<double> y,
234 py::array_t<double> values) {
235 py::array_t<double> values, double min_sampling,
235 auto t_s = t.size();
236 double max_sampling) {
236 auto v_s = values.size();
237 if(t.size() >= values.size() and t.size() != 0)
237 assert(t.size() < values.size() or
238 SCIQLOP_ERROR(decltype(py::self), "Doesn't look like a Spectrogram");
238 t.size() == 0); // TODO check geometry
239 if(y.size() != values.shape(1))
239 assert(y.size() == values.shape(1));
240 SCIQLOP_ERROR(decltype(py::self),
241 "Y axis size and data shape are incompatible");
240 SpectrogramTimeSerie::axis_t _t(t.size());
242 SpectrogramTimeSerie::axis_t _t(t.size());
241 SpectrogramTimeSerie::axis_t _y(y.size());
243 SpectrogramTimeSerie::axis_t _y(y.size());
242 SpectrogramTimeSerie::container_type<
244 SpectrogramTimeSerie::container_type<
243 SpectrogramTimeSerie::raw_value_type>
245 SpectrogramTimeSerie::raw_value_type>
244 _values(values.size());
246 _values(values.size());
245 copy_spectro(t, y, values, _t, _y, _values);
247 copy_spectro(t, y, values, _t, _y, _values);
246 std::vector<std::size_t> shape;
248 std::vector<std::size_t> shape;
247 shape.push_back(values.shape(0));
249 shape.push_back(values.shape(0));
248 shape.push_back(values.shape(1));
250 shape.push_back(values.shape(1));
249 return SpectrogramTimeSerie(std::move(_t), std::move(_y),
251 return SpectrogramTimeSerie(std::move(_t), std::move(_y),
250 std::move(_values), shape);
252 std::move(_values), shape, min_sampling,
253 max_sampling);
251 }))
254 }))
252 .def("__getitem__",
255 .def("__getitem__",
253 [](SpectrogramTimeSerie& ts,
256 [](SpectrogramTimeSerie& ts,
254 std::size_t key) -> SpectrogramTimeSerie::iterator_t {
257 std::size_t key) -> SpectrogramTimeSerie::iterator_t {
255 return ts.begin() + key;
258 return ts.begin() + key;
256 });
259 });
257
260
258 py::class_<Variable2, std::shared_ptr<Variable2>>(m, "Variable2")
261 py::class_<Variable2, std::shared_ptr<Variable2>>(m, "Variable2")
259 .def(py::init<const QString&>())
262 .def(py::init<const QString&>())
260 .def_property("name", &Variable2::name, &Variable2::setName)
263 .def_property("name", &Variable2::name, &Variable2::setName)
261 .def_property_readonly("range", &Variable2::range)
264 .def_property_readonly("range", &Variable2::range)
262 .def_property_readonly("nbPoints", &Variable2::nbPoints)
265 .def_property_readonly("nbPoints", &Variable2::nbPoints)
263 .def_property_readonly(
266 .def_property_readonly(
264 "data",
267 "data",
265 [](Variable2& var) -> std::shared_ptr<TimeSeries::ITimeSerie> {
268 [](Variable2& var) -> std::shared_ptr<TimeSeries::ITimeSerie> {
266 return var.data();
269 return var.data();
267 })
270 })
268 .def("set_data",
271 .def("set_data",
269 [](Variable2& var, std::vector<TimeSeries::ITimeSerie*> ts_list,
272 [](Variable2& var, std::vector<TimeSeries::ITimeSerie*> ts_list,
270 const DateTimeRange& range) { var.setData(ts_list, range); })
273 const DateTimeRange& range) { var.setData(ts_list, range); })
271 .def("__len__", &Variable2::nbPoints)
274 .def("__len__", &Variable2::nbPoints)
272 .def("__repr__", __repr__<Variable2>);
275 .def("__repr__", __repr__<Variable2>);
273
276
274 py::class_<DateTimeRange>(m, "SqpRange")
277 py::class_<DateTimeRange>(m, "SqpRange")
275 //.def("fromDateTime", &DateTimeRange::fromDateTime,
278 //.def("fromDateTime", &DateTimeRange::fromDateTime,
276 // py::return_value_policy::move)
279 // py::return_value_policy::move)
277 .def(py::init([](double start, double stop) {
280 .def(py::init([](double start, double stop) {
278 return DateTimeRange{start, stop};
281 return DateTimeRange{start, stop};
279 }))
282 }))
280 .def(py::init(
283 .def(py::init(
281 [](system_clock::time_point start, system_clock::time_point stop) {
284 [](system_clock::time_point start, system_clock::time_point stop) {
282 double start_ =
285 double start_ =
283 0.001 *
286 0.001 *
284 duration_cast<milliseconds>(start.time_since_epoch()).count();
287 duration_cast<milliseconds>(start.time_since_epoch()).count();
285 double stop_ =
288 double stop_ =
286 0.001 *
289 0.001 *
287 duration_cast<milliseconds>(stop.time_since_epoch()).count();
290 duration_cast<milliseconds>(stop.time_since_epoch()).count();
288 return DateTimeRange{start_, stop_};
291 return DateTimeRange{start_, stop_};
289 }))
292 }))
290 .def_property_readonly("start",
293 .def_property_readonly("start",
291 [](const DateTimeRange& range) {
294 [](const DateTimeRange& range) {
292 return system_clock::from_time_t(range.m_TStart);
295 return system_clock::from_time_t(range.m_TStart);
293 })
296 })
294 .def_property_readonly("stop",
297 .def_property_readonly("stop",
295 [](const DateTimeRange& range) {
298 [](const DateTimeRange& range) {
296 return system_clock::from_time_t(range.m_TEnd);
299 return system_clock::from_time_t(range.m_TEnd);
297 })
300 })
298 .def("__repr__", __repr__<DateTimeRange>);
301 .def("__repr__", __repr__<DateTimeRange>);
299 }
302 }
General Comments 0
You need to be logged in to leave comments. Login now