##// END OF EJS Templates
Added new TS classes and tiny cleanup...
jeandet -
r60:1d5bfa8fd429
parent child
Show More
@@ -0,0 +1,17
1 #ifndef SCIQLOP_SCALARTIMESERIE_H
2 #define SCIQLOP_SCALARTIMESERIE_H
3
4 #include "CoreGlobal.h"
5
6 #include <TimeSeries.h>
7
8 class SCIQLOP_CORE_EXPORT ScalarTimeSerie
9 : public TimeSeries::TimeSerie<double, ScalarTimeSerie>
10 {
11 public:
12 ScalarTimeSerie() {}
13 ~ScalarTimeSerie() = default;
14 using TimeSerie::TimeSerie;
15 };
16
17 #endif // SCIQLOP_SCALARSERIES_H
@@ -0,0 +1,22
1 #ifndef SCIQLOP_VECTORTIMESERIE_H
2 #define SCIQLOP_VECTORTIMESERIE_H
3
4 #include "CoreGlobal.h"
5
6 #include <TimeSeries.h>
7
8 struct Vector
9 {
10 double x, y, z;
11 };
12
13 class SCIQLOP_CORE_EXPORT VectorTimeSerie
14 : public TimeSeries::TimeSerie<Vector, VectorTimeSerie>
15 {
16 public:
17 VectorTimeSerie() {}
18 ~VectorTimeSerie() = default;
19 using TimeSerie::TimeSerie;
20 };
21
22 #endif // SCIQLOP_VECTORTIMESERIE_H
@@ -0,0 +1,1
1 #include <Data/ScalarTimeSerie.h>
@@ -0,0 +1,1
1 #include <Data/VectorTimeSerie.h>
@@ -81,9 +81,11 FILE (GLOB_RECURSE core_SRCS
81 ./include/Plugin/IPlugin.h
81 ./include/Plugin/IPlugin.h
82 ./include/Data/ArrayDataIterator.h
82 ./include/Data/ArrayDataIterator.h
83 ./include/Data/VectorSeries.h
83 ./include/Data/VectorSeries.h
84 ./include/Data/VectorTimeSerie.h
84 ./include/Data/DateTimeRange.h
85 ./include/Data/DateTimeRange.h
85 ./include/Data/DateTimeRangeHelper.h
86 ./include/Data/DateTimeRangeHelper.h
86 ./include/Data/ScalarSeries.h
87 ./include/Data/ScalarSeries.h
88 ./include/Data/ScalarTimeSerie.h
87 ./include/Data/DataSeriesMergeHelper.h
89 ./include/Data/DataSeriesMergeHelper.h
88 ./include/Data/DataSeries.h
90 ./include/Data/DataSeries.h
89 ./include/Data/DataSeriesType.h
91 ./include/Data/DataSeriesType.h
@@ -125,12 +127,14 FILE (GLOB_RECURSE core_SRCS
125 ./src/Common/StringUtils.cpp
127 ./src/Common/StringUtils.cpp
126 ./src/Common/SignalWaiter.cpp
128 ./src/Common/SignalWaiter.cpp
127 ./src/Data/ScalarSeries.cpp
129 ./src/Data/ScalarSeries.cpp
130 ./src/Data/ScalarTimeSerie.cpp
128 ./src/Data/DataSeriesIterator.cpp
131 ./src/Data/DataSeriesIterator.cpp
129 ./src/Data/OptionalAxis.cpp
132 ./src/Data/OptionalAxis.cpp
130 ./src/Data/ArrayDataIterator.cpp
133 ./src/Data/ArrayDataIterator.cpp
131 ./src/Data/SpectrogramSeries.cpp
134 ./src/Data/SpectrogramSeries.cpp
132 ./src/Data/DataSeriesUtils.cpp
135 ./src/Data/DataSeriesUtils.cpp
133 ./src/Data/VectorSeries.cpp
136 ./src/Data/VectorSeries.cpp
137 ./src/Data/VectorTimeSerie.cpp
134 ./src/Network/NetworkController.cpp
138 ./src/Network/NetworkController.cpp
135 ./src/Network/Downloader.cpp
139 ./src/Network/Downloader.cpp
136 ./src/Visualization/VisualizationController.cpp
140 ./src/Visualization/VisualizationController.cpp
@@ -172,6 +176,7 target_include_directories(sciqlopcore PUBLIC
172 target_link_libraries(sciqlopcore PUBLIC
176 target_link_libraries(sciqlopcore PUBLIC
173 Qt5::Core
177 Qt5::Core
174 Qt5::Network
178 Qt5::Network
179 TimeSeries
175 )
180 )
176
181
177 if(Catalog)
182 if(Catalog)
@@ -3,24 +3,33
3
3
4 #include <QString>
4 #include <QString>
5
5
6 enum class DataSeriesType { SCALAR, SPECTROGRAM, VECTOR, UNKNOWN };
6 enum class DataSeriesType
7 {
8 SCALAR,
9 SPECTROGRAM,
10 VECTOR,
11 UNKNOWN
12 };
7
13
8 struct DataSeriesTypeUtils {
14 struct DataSeriesTypeUtils
9 static DataSeriesType fromString(const QString &type)
15 {
16 static DataSeriesType fromString(const QString& type)
17 {
18 if(type.toLower() == QStringLiteral("scalar"))
19 { return DataSeriesType::SCALAR; }
20 else if(type.toLower() == QStringLiteral("spectrogram"))
21 {
22 return DataSeriesType::SPECTROGRAM;
23 }
24 else if(type.toLower() == QStringLiteral("vector"))
25 {
26 return DataSeriesType::VECTOR;
27 }
28 else
10 {
29 {
11 if (type == QStringLiteral("scalar")) {
30 return DataSeriesType::UNKNOWN;
12 return DataSeriesType::SCALAR;
13 }
14 else if (type == QStringLiteral("spectrogram")) {
15 return DataSeriesType::SPECTROGRAM;
16 }
17 else if (type == QStringLiteral("vector")) {
18 return DataSeriesType::VECTOR;
19 }
20 else {
21 return DataSeriesType::UNKNOWN;
22 }
23 }
31 }
32 }
24 };
33 };
25
34
26 #endif // SCIQLOP_DATASERIESTYPE_H
35 #endif // SCIQLOP_DATASERIESTYPE_H
@@ -2,54 +2,48
2 #define SCIQLOP_IDATAPROVIDER_H
2 #define SCIQLOP_IDATAPROVIDER_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5 #include <Common/deprecate.h>
6
7 #include <memory>
8
9 #include <QObject>
10 #include <QUuid>
11
5
12 #include <Common/MetaTypes.h>
6 #include <Common/MetaTypes.h>
13
7 #include <Common/deprecate.h>
14 #include <Data/DateTimeRange.h>
8 #include <Data/DateTimeRange.h>
15
9 #include <QObject>
10 #include <QUuid>
16 #include <functional>
11 #include <functional>
12 #include <memory>
17
13
18 class DataProviderParameters;
14 class DataProviderParameters;
19 class IDataSeries;
15 class IDataSeries;
20 DEPRECATE(
16 DEPRECATE(class QNetworkReply; class QNetworkRequest;)
21 class QNetworkReply;
22 class QNetworkRequest;
23 )
24
17
25 /**
18 /**
26 * @brief The IDataProvider interface aims to declare a data provider.
19 * @brief The IDataProvider interface aims to declare a data provider.
27 *
20 *
28 * A data provider is an entity that generates data and returns it according to various parameters
21 * A data provider is an entity that generates data and returns it according to
29 * (time interval, product to retrieve the data, etc.)
22 * various parameters (time interval, product to retrieve the data, etc.) Since
30 * Since its client mihgt use it from different threads it has to be either stateless and/or thread safe
23 * its client mihgt use it from different threads it has to be either stateless
24 * and/or thread safe
31 *
25 *
32 * @sa IDataSeries
26 * @sa IDataSeries
33 */
27 */
34 class SCIQLOP_CORE_EXPORT IDataProvider : public QObject {
28 class SCIQLOP_CORE_EXPORT IDataProvider : public QObject
35
29 {
36 Q_OBJECT
30 Q_OBJECT
37 public:
31 public:
38 virtual ~IDataProvider() noexcept = default;
32 virtual ~IDataProvider() noexcept = default;
39 virtual std::shared_ptr<IDataProvider> clone() const = 0;
33 virtual std::shared_ptr<IDataProvider> clone() const = 0;
40
34
41 // Synchronous call -> asyncGetData may be written for asynchronous get
35 // Synchronous call -> asyncGetData may be written for asynchronous get
42 virtual IDataSeries* getData(const DataProviderParameters &parameters) = 0;
36 virtual IDataSeries* getData(const DataProviderParameters& parameters) = 0;
43
37
44 signals:
38 signals:
45
39
46 void progress(QUuid requestID, double progress);
40 void progress(QUuid requestID, double progress);
47
48 };
41 };
49
42
50 // Required for using shared_ptr in signals/slots
43 // Required for using shared_ptr in signals/slots
51 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_PTR_REGISTRY, std::shared_ptr<IDataProvider>)
44 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_PTR_REGISTRY,
45 std::shared_ptr<IDataProvider>)
52 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_FUNCTION_REGISTRY,
46 SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_FUNCTION_REGISTRY,
53 std::function<void(QNetworkReply *, QUuid)>)
47 std::function<void(QNetworkReply*, QUuid)>)
54
48
55 #endif // SCIQLOP_IDATAPROVIDER_H
49 #endif // SCIQLOP_IDATAPROVIDER_H
@@ -3,30 +3,15
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <QLoggingCategory>
7 #include <QObject>
8
9 #include <Data/DateTimeRange.h>
6 #include <Data/DateTimeRange.h>
10
7
11 #include <QLoggingCategory>
12
13 #include <Common/spimpl.h>
14 #include <utility>
15
16
17 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableCacheStrategy)
18
19 class Variable;
20
21 /// This class aims to hande the cache strategy.
8 /// This class aims to hande the cache strategy.
22 class SCIQLOP_CORE_EXPORT VariableCacheStrategy {
9 class SCIQLOP_CORE_EXPORT VariableCacheStrategy
23
10 {
24 public:
11 public:
25 virtual ~VariableCacheStrategy() noexcept = default;
12 virtual ~VariableCacheStrategy() noexcept = default;
26 virtual DateTimeRange computeRange(const DateTimeRange &currentCacheRange,
13 virtual DateTimeRange computeRange(const DateTimeRange& currentCacheRange,
27 const DateTimeRange &rangeRequested)
14 const DateTimeRange& rangeRequested) = 0;
28 = 0;
29 };
15 };
30
16
31
32 #endif // SCIQLOP_VARIABLECACHESTRATEGY_H
17 #endif // SCIQLOP_VARIABLECACHESTRATEGY_H
This diff has been collapsed as it changes many lines, (696 lines changed) Show them Hide them
@@ -1,432 +1,452
1 #include <QQueue>
2 #include <QThreadPool>
3 #include <QRunnable>
4 #include <QObject>
5 #include <QDataStream>
6
7 #include "Variable/VariableController2.h"
1 #include "Variable/VariableController2.h"
2
8 #include "Variable/VariableSynchronizationGroup2.h"
3 #include "Variable/VariableSynchronizationGroup2.h"
4
9 #include <Common/containers.h>
5 #include <Common/containers.h>
10 #include <Common/debug.h>
6 #include <Common/debug.h>
11 #include <Data/DataProviderParameters.h>
7 #include <Data/DataProviderParameters.h>
12 #include <Data/DateTimeRangeHelper.h>
13 #include <Data/DateTimeRange.h>
8 #include <Data/DateTimeRange.h>
9 #include <Data/DateTimeRangeHelper.h>
10 #include <QCoreApplication>
11 #include <QDataStream>
12 #include <QObject>
13 #include <QQueue>
14 #include <QRunnable>
15 #include <QThreadPool>
14 #include <Variable/VariableCacheStrategyFactory.h>
16 #include <Variable/VariableCacheStrategyFactory.h>
15 #include <Variable/private/VCTransaction.h>
17 #include <Variable/private/VCTransaction.h>
16 #include <QCoreApplication>
17
18
18
19 class VariableController2::VariableController2Private
19 class VariableController2::VariableController2Private
20 {
20 {
21 struct threadSafeVaraiblesMaps
21 struct threadSafeVaraiblesMaps
22 {
23 inline void
24 addVariable(const std::shared_ptr<Variable>& variable,
25 const std::shared_ptr<IDataProvider>& provider,
26 const std::shared_ptr<VariableSynchronizationGroup2>&
27 synchronizationGroup)
22 {
28 {
23 inline void addVariable(const std::shared_ptr<Variable>& variable, const std::shared_ptr<IDataProvider>& provider, const std::shared_ptr<VariableSynchronizationGroup2>& synchronizationGroup)
29 QWriteLocker lock{&_lock};
24 {
30 _variables[*variable] = variable;
25 QWriteLocker lock{&_lock};
31 _providers[*variable] = provider;
26 _variables[*variable] = variable;
32 _synchronizationGroups[*variable] = synchronizationGroup;
27 _providers[*variable] = provider;
28 _synchronizationGroups[*variable] = synchronizationGroup;
29 }
30
31 inline void removeVariable(const std::shared_ptr<Variable>& variable)
32 {
33 QWriteLocker lock{&_lock};
34 _variables.erase(*variable);
35 _providers.remove(*variable);
36 _synchronizationGroups.remove(*variable);
37 }
38
39 inline void synchronize(const std::shared_ptr<Variable>& variable, const std::optional<std::shared_ptr<Variable>>& with)
40 {
41 QWriteLocker lock{&_lock};
42 if(with.has_value())
43 {
44 auto newGroup = _synchronizationGroups[*with.value()];
45 newGroup->addVariable(*variable);
46 _synchronizationGroups[*variable] = newGroup;
47 }
48 else
49 {
50 _synchronizationGroups[*variable] = std::make_shared<VariableSynchronizationGroup2>(*variable);
51 }
52 }
53
54 inline std::shared_ptr<Variable> variable(QUuid variable)
55 {
56 QReadLocker lock{&_lock};
57 auto it = _variables.find(variable);
58 [[unlikely]]
59 if(it==_variables.end())
60 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
61 return (*it).second;
62 }
63
64 inline std::shared_ptr<Variable> variable(int index)
65 {
66 QReadLocker lock{&_lock};
67 [[unlikely]]
68 if(!_variables.size() > index)
69 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Index is out of bounds");
70 auto it = _variables.cbegin();
71 while (index!=0) {
72 index-=1;
73 it++;
74 }
75 return (*it).second;
76 }
77
78 inline const std::vector<std::shared_ptr<Variable>> variables()
79 {
80 std::vector<std::shared_ptr<Variable>> vars;
81 QReadLocker lock{&_lock};
82 for(const auto&[id, var]:_variables)
83 {
84 vars.push_back(var);
85 }
86 return vars;
87 }
88
89 inline std::shared_ptr<IDataProvider> provider(QUuid variable)
90 {
91 QReadLocker lock{&_lock};
92 [[unlikely]]
93 if(!_providers.contains(variable))
94 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
95 return _providers[variable];
96 }
97
98 inline std::shared_ptr<VariableSynchronizationGroup2> group(QUuid variable)
99 {
100 QReadLocker lock{&_lock};
101 [[unlikely]]
102 if(!_synchronizationGroups.contains(variable))
103 SCIQLOP_ERROR(threadSafeVaraiblesMaps,"Unknown Variable");
104 return _synchronizationGroups[variable];
105 }
106
107 inline bool has(const std::shared_ptr<Variable>& variable)
108 {
109 QReadLocker lock{&_lock};
110 return _variables.find(*variable)==_variables.end();
111 }
112
113 private:
114 std::map<QUuid,std::shared_ptr<Variable>> _variables;
115 QMap<QUuid,std::shared_ptr<IDataProvider>> _providers;
116 QMap<QUuid,std::shared_ptr<VariableSynchronizationGroup2>> _synchronizationGroups;
117 QReadWriteLock _lock{QReadWriteLock::Recursive};
118 }_maps;
119 std::vector<QUuid> _variablesToRemove;
120 QThreadPool* _ThreadPool;
121 VCTransactionsQueues _transactions;
122 std::unique_ptr<VariableCacheStrategy> _cacheStrategy;
123
124 void _transactionComplete(QUuid group, std::shared_ptr<VCTransaction> transaction)
125 {
126 if(transaction->done())
127 {
128 _transactions.complete(group);
129 }
130 this->_processTransactions();
131 }
33 }
132
34
133 void _cleanupVariables()
35 inline void removeVariable(const std::shared_ptr<Variable>& variable)
134 {
36 {
135 for(auto id:_variablesToRemove)
37 QWriteLocker lock{&_lock};
136 {
38 _variables.erase(*variable);
137 auto v = this->variable(id);
39 _providers.remove(*variable);
138 if(!hasPendingTransactions(v))
40 _synchronizationGroups.remove(*variable);
139 {
140 _variablesToRemove.erase(std::remove(_variablesToRemove.begin(), _variablesToRemove.end(), id), _variablesToRemove.end());
141 this->deleteVariable(v);
142 }
143 }
144 }
41 }
145
42
146 void _processTransactions(bool fragmented=false)
43 inline void
44 synchronize(const std::shared_ptr<Variable>& variable,
45 const std::optional<std::shared_ptr<Variable>>& with)
147 {
46 {
148 auto nextTransactions = _transactions.nextTransactions();
47 QWriteLocker lock{&_lock};
149 auto pendingTransactions = _transactions.pendingTransactions();
48 if(with.has_value())
150 for( auto [groupID, newTransaction] : nextTransactions)
49 {
151 {
50 auto newGroup = _synchronizationGroups[*with.value()];
152 if(newTransaction.has_value() && !pendingTransactions[groupID].has_value())
51 newGroup->addVariable(*variable);
153 {
52 _synchronizationGroups[*variable] = newGroup;
154 _transactions.start(groupID);
53 }
155 auto refVar = _maps.variable(newTransaction.value()->refVar);
54 else
156 auto ranges = _computeAllRangesInGroup(refVar,newTransaction.value()->range);
55 {
157 for( auto const& [ID, range] : ranges)
56 _synchronizationGroups[*variable] =
158 {
57 std::make_shared<VariableSynchronizationGroup2>(*variable);
159 auto provider = _maps.provider(ID);
58 }
160 auto variable = _maps.variable(ID);
161 if(fragmented)
162 {
163 auto [missingRanges, newCacheRange] = _computeMissingRanges(variable,range);
164
165 auto exe = new TransactionExe(variable, provider, missingRanges, range, newCacheRange);
166 QObject::connect(exe,
167 &TransactionExe::transactionComplete,
168 [groupID=groupID,transaction=newTransaction.value(),this]()
169 {
170 this->_transactionComplete(groupID, transaction);
171 }
172 );
173 _ThreadPool->start(exe);
174 }
175 else
176 {
177 auto exe = new TransactionExe(variable, provider, {range}, range, range);
178 QObject::connect(exe,
179 &TransactionExe::transactionComplete,
180 [groupID=groupID,transaction=newTransaction.value(),this]()
181 {
182 this->_transactionComplete(groupID, transaction);
183 }
184 );
185 _ThreadPool->start(exe);
186 }
187 }
188 }
189 }
190 //after each transaction update we get a new distribution of idle and working variables
191 //so we can delete variables which are waiting to be deleted if they are now idle
192 _cleanupVariables();
193 }
59 }
194
60
195 std::map<QUuid,DateTimeRange> _computeAllRangesInGroup(const std::shared_ptr<Variable>& refVar, DateTimeRange r)
61 inline std::shared_ptr<Variable> variable(QUuid variable)
196 {
62 {
197 std::map<QUuid,DateTimeRange> ranges;
63 QReadLocker lock{&_lock};
198 if(!DateTimeRangeHelper::hasnan(r))
64 auto it = _variables.find(variable);
199 {
65 [[unlikely]] if(it == _variables.end())
200 auto group = _maps.group(*refVar);
66 SCIQLOP_ERROR(threadSafeVaraiblesMaps, "Unknown Variable");
201 if(auto transformation = DateTimeRangeHelper::computeTransformation(refVar->range(),r);
67 return (*it).second;
202 transformation.has_value())
203 {
204 for(auto varId:group->variables())
205 {
206 auto var = _maps.variable(varId);
207 auto newRange = var->range().transform(transformation.value());
208 ranges[varId] = newRange;
209 }
210 }
211 else // force new range to all variables -> may be weird if more than one var in the group
212 // @TODO ensure that there is no side effects
213 {
214 for(auto varId:group->variables())
215 {
216 auto var = _maps.variable(varId);
217 ranges[varId] = r;
218 }
219 }
220 }
221 else
222 {
223 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
224 }
225 return ranges;
226 }
68 }
227
69
228 std::pair<std::vector<DateTimeRange>,DateTimeRange> _computeMissingRanges(const std::shared_ptr<Variable>& var, DateTimeRange r)
70 inline std::shared_ptr<Variable> variable(int index)
229 {
71 {
230 DateTimeRange newCacheRange;
72 QReadLocker lock{&_lock};
231 std::vector<DateTimeRange> missingRanges;
73 [[unlikely]] if(!_variables.size() > index)
232 if(DateTimeRangeHelper::hasnan(var->cacheRange()))
74 SCIQLOP_ERROR(threadSafeVaraiblesMaps, "Index is out of bounds");
233 {
75 auto it = _variables.cbegin();
234 newCacheRange = _cacheStrategy->computeRange(r,r);
76 while(index != 0)
235 missingRanges = {newCacheRange};
77 {
236 }
78 index -= 1;
237 else
79 it++;
238 {
80 }
239 newCacheRange = _cacheStrategy->computeRange(var->cacheRange(),r);
81 return (*(it)).second;
240 missingRanges = newCacheRange - var->cacheRange();
241 }
242 return {missingRanges,newCacheRange};
243 }
82 }
244
83
245 void _changeRange(QUuid id, DateTimeRange r)
84 inline const std::vector<std::shared_ptr<Variable>> variables()
246 {
85 {
247 _changeRange(_maps.variable(id) ,r);
86 std::vector<std::shared_ptr<Variable>> vars;
87 QReadLocker lock{&_lock};
88 for(const auto& [id, var] : _variables)
89 {
90 vars.push_back(var);
91 }
92 return vars;
248 }
93 }
249 void _changeRange(const std::shared_ptr<Variable>& var, DateTimeRange r)
94
95 inline std::shared_ptr<IDataProvider> provider(QUuid variable)
250 {
96 {
251 auto provider = _maps.provider(*var);
97 QReadLocker lock{&_lock};
252 auto [missingRanges, newCacheRange] = _computeMissingRanges(var,r);
98 [[unlikely]] if(!_providers.contains(variable))
253 std::vector<IDataSeries*> data;
99 SCIQLOP_ERROR(threadSafeVaraiblesMaps, "Unknown Variable");
254 for(auto range:missingRanges)
100 return _providers[variable];
255 {
256 data.push_back(provider->getData(DataProviderParameters{{range}, var->metadata()}));
257 }
258 var->updateData(data, r, newCacheRange, true);
259 }
101 }
260 public:
102
261 VariableController2Private(QObject* parent=Q_NULLPTR)
103 inline std::shared_ptr<VariableSynchronizationGroup2> group(QUuid variable)
262 :_cacheStrategy(VariableCacheStrategyFactory::createCacheStrategy(CacheStrategy::SingleThreshold))
263 {
104 {
264 Q_UNUSED(parent);
105 QReadLocker lock{&_lock};
265 this->_ThreadPool = new QThreadPool();
106 [[unlikely]] if(!_synchronizationGroups.contains(variable))
266 this->_ThreadPool->setMaxThreadCount(32);
107 SCIQLOP_ERROR(threadSafeVaraiblesMaps, "Unknown Variable");
108 return _synchronizationGroups[variable];
267 }
109 }
268
110
269 /*
111 inline bool has(const std::shared_ptr<Variable>& variable)
270 * This dtor has to like this even if this is ugly, because default dtor would rely on
271 * declaration order to destruct members and that would always lead to regressions when
272 * modifying class members
273 */
274 ~VariableController2Private()
275 {
112 {
276 delete this->_ThreadPool;
113 QReadLocker lock{&_lock};
114 return _variables.find(*variable) == _variables.end();
277 }
115 }
278
116
279 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata, std::shared_ptr<IDataProvider> provider)
117 private:
118 std::map<QUuid, std::shared_ptr<Variable>> _variables;
119 QMap<QUuid, std::shared_ptr<IDataProvider>> _providers;
120 QMap<QUuid, std::shared_ptr<VariableSynchronizationGroup2>>
121 _synchronizationGroups;
122 QReadWriteLock _lock{QReadWriteLock::Recursive};
123 } _maps;
124 std::vector<QUuid> _variablesToRemove;
125 QThreadPool* _ThreadPool;
126 VCTransactionsQueues _transactions;
127 std::unique_ptr<VariableCacheStrategy> _cacheStrategy;
128
129 void _transactionComplete(QUuid group,
130 std::shared_ptr<VCTransaction> transaction)
131 {
132 if(transaction->done()) { _transactions.complete(group); }
133 this->_processTransactions();
134 }
135
136 void _cleanupVariables()
137 {
138 for(auto id : _variablesToRemove)
280 {
139 {
281 auto newVar = std::make_shared<Variable>(name,metadata);
140 auto v = this->variable(id);
282 auto group = std::make_shared<VariableSynchronizationGroup2>(newVar->ID());
141 if(!hasPendingTransactions(v))
283 _maps.addVariable(newVar,std::move(provider),group);
142 {
284 this->_transactions.addEntry(*group);
143 _variablesToRemove.erase(std::remove(_variablesToRemove.begin(),
285 return newVar;
144 _variablesToRemove.end(), id),
145 _variablesToRemove.end());
146 this->deleteVariable(v);
147 }
286 }
148 }
149 }
287
150
288 std::shared_ptr<Variable> variable(QUuid ID)
151 void _processTransactions(bool fragmented = false)
152 {
153 auto nextTransactions = _transactions.nextTransactions();
154 auto pendingTransactions = _transactions.pendingTransactions();
155 for(auto [groupID, newTransaction] : nextTransactions)
289 {
156 {
290 return _maps.variable(ID);
157 if(newTransaction.has_value() &&
158 !pendingTransactions[groupID].has_value())
159 {
160 _transactions.start(groupID);
161 auto refVar = _maps.variable(newTransaction.value()->refVar);
162 auto ranges =
163 _computeAllRangesInGroup(refVar, newTransaction.value()->range);
164 for(auto const& [ID, range] : ranges)
165 {
166 auto provider = _maps.provider(ID);
167 auto variable = _maps.variable(ID);
168 if(fragmented)
169 {
170 auto [missingRanges, newCacheRange] =
171 _computeMissingRanges(variable, range);
172
173 auto exe = new TransactionExe(variable, provider, missingRanges,
174 range, newCacheRange);
175 QObject::connect(
176 exe, &TransactionExe::transactionComplete,
177 [groupID = groupID, transaction = newTransaction.value(),
178 this]() { this->_transactionComplete(groupID, transaction); });
179 _ThreadPool->start(exe);
180 }
181 else
182 {
183 auto exe =
184 new TransactionExe(variable, provider, {range}, range, range);
185 QObject::connect(
186 exe, &TransactionExe::transactionComplete,
187 [groupID = groupID, transaction = newTransaction.value(),
188 this]() { this->_transactionComplete(groupID, transaction); });
189 _ThreadPool->start(exe);
190 }
191 }
192 }
291 }
193 }
292
194 // after each transaction update we get a new distribution of idle and
293 std::shared_ptr<Variable> variable(int index)
195 // working variables so we can delete variables which are waiting to be
196 // deleted if they are now idle
197 _cleanupVariables();
198 }
199
200 std::map<QUuid, DateTimeRange>
201 _computeAllRangesInGroup(const std::shared_ptr<Variable>& refVar,
202 DateTimeRange r)
203 {
204 std::map<QUuid, DateTimeRange> ranges;
205 if(!DateTimeRangeHelper::hasnan(r))
294 {
206 {
295 return _maps.variable(index);
207 auto group = _maps.group(*refVar);
208 if(auto transformation =
209 DateTimeRangeHelper::computeTransformation(refVar->range(), r);
210 transformation.has_value())
211 {
212 for(auto varId : group->variables())
213 {
214 auto var = _maps.variable(varId);
215 auto newRange = var->range().transform(transformation.value());
216 ranges[varId] = newRange;
217 }
218 }
219 else // force new range to all variables -> may be weird if more than one
220 // var in the group
221 // @TODO ensure that there is no side effects
222 {
223 for(auto varId : group->variables())
224 {
225 auto var = _maps.variable(varId);
226 ranges[varId] = r;
227 }
228 }
296 }
229 }
297
230 else
298 std::shared_ptr<Variable> cloneVariable(const std::shared_ptr<Variable>& variable)
299 {
231 {
300 auto newVar = variable->clone();
232 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
301 _maps.synchronize(newVar,std::nullopt);
302 _maps.addVariable(newVar,_maps.provider(*variable),_maps.group(*newVar));
303 this->_transactions.addEntry(*_maps.group(*newVar));
304 return newVar;
305 }
233 }
306
234 return ranges;
307 bool hasPendingTransactions(const std::shared_ptr<Variable>& variable)
235 }
236
237 std::pair<std::vector<DateTimeRange>, DateTimeRange>
238 _computeMissingRanges(const std::shared_ptr<Variable>& var, DateTimeRange r)
239 {
240 DateTimeRange newCacheRange;
241 std::vector<DateTimeRange> missingRanges;
242 if(DateTimeRangeHelper::hasnan(var->cacheRange()))
308 {
243 {
309 return _transactions.active(*_maps.group(*variable));
244 newCacheRange = _cacheStrategy->computeRange(r, r);
245 missingRanges = {newCacheRange};
310 }
246 }
311
247 else
312 bool hasPendingTransactions()
313 {
248 {
314 bool has = false;
249 newCacheRange = _cacheStrategy->computeRange(var->cacheRange(), r);
315 for(const auto& var:_maps.variables())
250 missingRanges = newCacheRange - var->cacheRange();
316 {
317 has |= _transactions.active(*_maps.group(*var));
318 }
319 return has;
320 }
251 }
321
252 return {missingRanges, newCacheRange};
322 void deleteVariable(const std::shared_ptr<Variable>& variable)
253 }
254
255 void _changeRange(QUuid id, DateTimeRange r)
256 {
257 _changeRange(_maps.variable(id), r);
258 }
259 void _changeRange(const std::shared_ptr<Variable>& var, DateTimeRange r)
260 {
261 auto provider = _maps.provider(*var);
262 auto [missingRanges, newCacheRange] = _computeMissingRanges(var, r);
263 std::vector<IDataSeries*> data;
264 for(auto range : missingRanges)
323 {
265 {
324 if(!hasPendingTransactions(variable))
266 data.push_back(
325 _maps.removeVariable(variable);
267 provider->getData(DataProviderParameters{{range}, var->metadata()}));
326 else
327 _variablesToRemove.push_back(variable->ID());
328 }
268 }
269 var->updateData(data, r, newCacheRange, true);
270 }
329
271
330 void asyncChangeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r)
272 public:
273 VariableController2Private(QObject* parent = Q_NULLPTR)
274 : _cacheStrategy(VariableCacheStrategyFactory::createCacheStrategy(
275 CacheStrategy::SingleThreshold))
276 {
277 Q_UNUSED(parent);
278 this->_ThreadPool = new QThreadPool();
279 this->_ThreadPool->setMaxThreadCount(32);
280 }
281
282 /*
283 * This dtor has to like this even if this is ugly, because default dtor would
284 * rely on declaration order to destruct members and that would always lead to
285 * regressions when modifying class members
286 */
287 ~VariableController2Private() { delete this->_ThreadPool; }
288
289 std::shared_ptr<Variable>
290 createVariable(const QString& name, const QVariantHash& metadata,
291 std::shared_ptr<IDataProvider> provider)
292 {
293 auto newVar = std::make_shared<Variable>(name, metadata);
294 auto group = std::make_shared<VariableSynchronizationGroup2>(newVar->ID());
295 _maps.addVariable(newVar, std::move(provider), group);
296 this->_transactions.addEntry(*group);
297 return newVar;
298 }
299
300 std::shared_ptr<Variable> variable(QUuid ID) { return _maps.variable(ID); }
301
302 std::shared_ptr<Variable> variable(int index)
303 {
304 return _maps.variable(index);
305 }
306
307 std::shared_ptr<Variable>
308 cloneVariable(const std::shared_ptr<Variable>& variable)
309 {
310 auto newVar = variable->clone();
311 _maps.synchronize(newVar, std::nullopt);
312 _maps.addVariable(newVar, _maps.provider(*variable), _maps.group(*newVar));
313 this->_transactions.addEntry(*_maps.group(*newVar));
314 return newVar;
315 }
316
317 bool hasPendingTransactions(const std::shared_ptr<Variable>& variable)
318 {
319 return _transactions.active(*_maps.group(*variable));
320 }
321
322 bool hasPendingTransactions()
323 {
324 bool has = false;
325 for(const auto& var : _maps.variables())
331 {
326 {
332 if(!DateTimeRangeHelper::hasnan(r))
327 has |= _transactions.active(*_maps.group(*var));
333 {
334 auto group = _maps.group(*variable);
335 // Just overwrite next transaction
336 {
337 _transactions.enqueue(*group,std::make_shared<VCTransaction>(variable->ID(), r, static_cast<int>(group->variables().size())));
338 }
339 _processTransactions();
340 }
341 else
342 {
343 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
344 }
345 }
328 }
329 return has;
330 }
346
331
347 void changeRange(const std::shared_ptr<Variable>& variable, DateTimeRange r)
332 void deleteVariable(const std::shared_ptr<Variable>& variable)
333 {
334 if(!hasPendingTransactions(variable))
335 _maps.removeVariable(variable);
336 else
337 _variablesToRemove.push_back(variable->ID());
338 }
339
340 void asyncChangeRange(const std::shared_ptr<Variable>& variable,
341 const DateTimeRange& r)
342 {
343 if(!DateTimeRangeHelper::hasnan(r))
348 {
344 {
349 asyncChangeRange(variable,r);
345 auto group = _maps.group(*variable);
350 while (hasPendingTransactions(variable))
346 // Just overwrite next transaction
351 {
347 {
352 QCoreApplication::processEvents();
348 _transactions.enqueue(*group,
353 }
349 std::make_shared<VCTransaction>(
350 variable->ID(), r,
351 static_cast<int>(group->variables().size())));
352 }
353 _processTransactions();
354 }
354 }
355
355 else
356 inline void synchronize(const std::shared_ptr<Variable>& var, const std::shared_ptr<Variable>& with)
357 {
356 {
358 _maps.synchronize(var, with);
357 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
359 }
358 }
359 }
360
360
361 inline const std::vector<std::shared_ptr<Variable>> variables()
361 void changeRange(const std::shared_ptr<Variable>& variable, DateTimeRange r)
362 {
363 asyncChangeRange(variable, r);
364 while(hasPendingTransactions(variable))
362 {
365 {
363 return _maps.variables();
366 QCoreApplication::processEvents();
364 }
367 }
365
368 }
369
370 inline void synchronize(const std::shared_ptr<Variable>& var,
371 const std::shared_ptr<Variable>& with)
372 {
373 _maps.synchronize(var, with);
374 }
375
376 inline const std::vector<std::shared_ptr<Variable>> variables()
377 {
378 return _maps.variables();
379 }
366 };
380 };
367
381
368 VariableController2::VariableController2()
382 VariableController2::VariableController2()
369 :impl{spimpl::make_unique_impl<VariableController2Private>()}
383 : impl{spimpl::make_unique_impl<VariableController2Private>()}
370 {}
384 {}
371
385
372 std::shared_ptr<Variable> VariableController2::createVariable(const QString &name, const QVariantHash &metadata, const std::shared_ptr<IDataProvider>& provider, const DateTimeRange &range)
386 std::shared_ptr<Variable> VariableController2::createVariable(
387 const QString& name, const QVariantHash& metadata,
388 const std::shared_ptr<IDataProvider>& provider, const DateTimeRange& range)
373 {
389 {
374 auto var = impl->createVariable(name, metadata, provider);
390 auto var = impl->createVariable(name, metadata, provider);
375 var->setRange(range); // even with no data this is it's range
391 var->setRange(range); // even with no data this is it's range
376 if(!DateTimeRangeHelper::hasnan(range))
392 if(!DateTimeRangeHelper::hasnan(range))
377 impl->asyncChangeRange(var,range);
393 impl->asyncChangeRange(var, range);
378 else
394 else
379 SCIQLOP_ERROR(VariableController2, "Creating a variable with default constructed DateTimeRange is an error");
395 SCIQLOP_ERROR(VariableController2, "Creating a variable with default "
380 emit variableAdded(var);
396 "constructed DateTimeRange is an error");
381 return var;
397 emit variableAdded(var);
398 return var;
382 }
399 }
383
400
384 std::shared_ptr<Variable> VariableController2::cloneVariable(const std::shared_ptr<Variable> &variable)
401 std::shared_ptr<Variable>
402 VariableController2::cloneVariable(const std::shared_ptr<Variable>& variable)
385 {
403 {
386 return impl->cloneVariable(variable);
404 return impl->cloneVariable(variable);
387 }
405 }
388
406
389 void VariableController2::deleteVariable(const std::shared_ptr<Variable>& variable)
407 void VariableController2::deleteVariable(
408 const std::shared_ptr<Variable>& variable)
390 {
409 {
391 impl->deleteVariable(variable);
410 impl->deleteVariable(variable);
392 emit variableDeleted(variable);
411 emit variableDeleted(variable);
393 }
412 }
394
413
395 void VariableController2::changeRange(const std::shared_ptr<Variable>& variable, const DateTimeRange& r)
414 void VariableController2::changeRange(const std::shared_ptr<Variable>& variable,
415 const DateTimeRange& r)
396 {
416 {
397 impl->changeRange(variable, r);
417 impl->changeRange(variable, r);
398 }
418 }
399
419
400 void VariableController2::asyncChangeRange(const std::shared_ptr<Variable> &variable, const DateTimeRange &r)
420 void VariableController2::asyncChangeRange(
421 const std::shared_ptr<Variable>& variable, const DateTimeRange& r)
401 {
422 {
402 impl->asyncChangeRange(variable, r);
423 impl->asyncChangeRange(variable, r);
403 }
424 }
404
425
405 const std::vector<std::shared_ptr<Variable> > VariableController2::variables()
426 const std::vector<std::shared_ptr<Variable>> VariableController2::variables()
406 {
427 {
407 return impl->variables();
428 return impl->variables();
408 }
429 }
409
430
410 bool VariableController2::isReady(const std::shared_ptr<Variable> &variable)
431 bool VariableController2::isReady(const std::shared_ptr<Variable>& variable)
411 {
432 {
412 return !impl->hasPendingTransactions(variable);
433 return !impl->hasPendingTransactions(variable);
413 }
434 }
414
435
415 bool VariableController2::isReady()
436 bool VariableController2::isReady() { return !impl->hasPendingTransactions(); }
416 {
417 return !impl->hasPendingTransactions();
418 }
419
437
420 void VariableController2::synchronize(const std::shared_ptr<Variable> &var, const std::shared_ptr<Variable> &with)
438 void VariableController2::synchronize(const std::shared_ptr<Variable>& var,
439 const std::shared_ptr<Variable>& with)
421 {
440 {
422 impl->synchronize(var, with);
441 impl->synchronize(var, with);
423 }
442 }
424
443
425 const std::vector<std::shared_ptr<Variable>> VariableController2::variables(const std::vector<QUuid> &ids)
444 const std::vector<std::shared_ptr<Variable>>
445 VariableController2::variables(const std::vector<QUuid>& ids)
426 {
446 {
427 std::vector<std::shared_ptr<Variable>> variables;
447 std::vector<std::shared_ptr<Variable>> variables;
428 for (const auto& id : ids) {
448 std::transform(std::cbegin(ids), std::cend(ids),
429 variables.push_back(impl->variable(id));
449 std::back_inserter(variables),
430 }
450 [this](const auto& id) { return impl->variable(id); });
431 return variables;
451 return variables;
432 }
452 }
@@ -1,157 +1,177
1 #include <pybind11/pybind11.h>
1 #include "CoreWrappers.h"
2 #include <pybind11/operators.h>
3 #include <pybind11/embed.h>
4 #include <pybind11/numpy.h>
5 #include <pybind11/chrono.h>
6 #include <pybind11/functional.h>
7 #include <pybind11/stl.h>
8
9
10 #include <string>
11 #include <sstream>
12
2
13 #include "pywrappers_common.h"
3 #include "pywrappers_common.h"
14 #include "CoreWrappers.h"
15
4
16 #include <Data/DataSeriesType.h>
5 #include <Data/DataSeriesType.h>
6 #include <Data/IDataProvider.h>
7 #include <Data/OptionalAxis.h>
17 #include <Data/ScalarSeries.h>
8 #include <Data/ScalarSeries.h>
18 #include <Data/VectorSeries.h>
19 #include <Data/SpectrogramSeries.h>
9 #include <Data/SpectrogramSeries.h>
20 #include <Data/Unit.h>
10 #include <Data/Unit.h>
21 #include <Data/OptionalAxis.h>
11 #include <Data/VectorSeries.h>
22 #include <Data/IDataProvider.h>
23
24 #include <Variable/VariableController2.h>
25
26 #include <Time/TimeController.h>
27
28 #include <Network/Downloader.h>
12 #include <Network/Downloader.h>
29
13 #include <Time/TimeController.h>
30
14 #include <Variable/VariableController2.h>
15 #include <pybind11/chrono.h>
16 #include <pybind11/embed.h>
17 #include <pybind11/functional.h>
18 #include <pybind11/numpy.h>
19 #include <pybind11/operators.h>
20 #include <pybind11/pybind11.h>
21 #include <pybind11/stl.h>
22 #include <sstream>
23 #include <string>
31
24
32 namespace py = pybind11;
25 namespace py = pybind11;
33 using namespace std::chrono;
26 using namespace std::chrono;
34
27
35 PYBIND11_MODULE(pysciqlopcore,m){
28 PYBIND11_MODULE(pysciqlopcore, m)
36
29 {
37 py::enum_<DataSeriesType>(m, "DataSeriesType")
30 py::enum_<DataSeriesType>(m, "DataSeriesType")
38 .value("SCALAR", DataSeriesType::SCALAR)
31 .value("SCALAR", DataSeriesType::SCALAR)
39 .value("SPECTROGRAM", DataSeriesType::SPECTROGRAM)
32 .value("SPECTROGRAM", DataSeriesType::SPECTROGRAM)
40 .value("VECTOR", DataSeriesType::VECTOR)
33 .value("VECTOR", DataSeriesType::VECTOR)
41 .value("UNKNOWN", DataSeriesType::UNKNOWN)
34 .value("UNKNOWN", DataSeriesType::UNKNOWN)
42 .export_values();
35 .export_values();
43
36
44 py::class_<Unit>(m, "Unit")
37 py::class_<Unit>(m, "Unit")
45 .def_readwrite("name", &Unit::m_Name)
38 .def_readwrite("name", &Unit::m_Name)
46 .def_readwrite("time_unit", &Unit::m_TimeUnit)
39 .def_readwrite("time_unit", &Unit::m_TimeUnit)
47 .def(py::self == py::self)
40 .def(py::self == py::self)
48 .def(py::self != py::self)
41 .def(py::self != py::self)
49 .def("__repr__",__repr__<Unit>);
42 .def("__repr__", __repr__<Unit>);
50
43
51 py::class_<Response>(m,"Response")
44 py::class_<Response>(m, "Response")
52 .def("status_code", &Response::status_code);
45 .def("status_code", &Response::status_code);
53
46
54 py::class_<Downloader>(m,"Downloader")
47 py::class_<Downloader>(m, "Downloader")
55 .def_static("get", Downloader::get)
48 .def_static("get", Downloader::get)
56 .def_static("getAsync", Downloader::getAsync)
49 .def_static("getAsync", Downloader::getAsync)
57 .def_static("downloadFinished", Downloader::downloadFinished);
50 .def_static("downloadFinished", Downloader::downloadFinished);
58
51
59 py::class_<ArrayDataIteratorValue>(m, "ArrayDataIteratorValue")
52 py::class_<ArrayDataIteratorValue>(m, "ArrayDataIteratorValue")
60 .def_property_readonly("value", &ArrayDataIteratorValue::first);
53 .def_property_readonly("value", &ArrayDataIteratorValue::first);
61
54
62 py::class_<OptionalAxis>(m, "OptionalAxis")
55 py::class_<OptionalAxis>(m, "OptionalAxis")
63 .def("__len__", &OptionalAxis::size)
56 .def("__len__", &OptionalAxis::size)
64 .def_property_readonly("size", &OptionalAxis::size)
57 .def_property_readonly("size", &OptionalAxis::size)
65 .def("__getitem__", [](OptionalAxis& ax, int key) {
58 .def("__getitem__",
66 return (*(ax.begin()+key)).first();
59 [](OptionalAxis& ax, int key) {
67 }, py::is_operator())
60 return (*(ax.begin() + key)).first();
68 .def("__iter__", [](OptionalAxis& ax) {
61 },
69 return py::make_iterator(ax.begin(), ax.end());
62 py::is_operator())
70 }, py::keep_alive<0, 1>());
63 .def("__iter__",
71
64 [](OptionalAxis& ax) {
72 py::class_<DataSeriesIteratorValue>(m,"DataSeriesIteratorValue")
65 return py::make_iterator(ax.begin(), ax.end());
73 .def_property_readonly("x", &DataSeriesIteratorValue::x)
66 },
74 .def_property_readonly("y", &DataSeriesIteratorValue::y)
67 py::keep_alive<0, 1>());
75 .def("value", py::overload_cast<>(&DataSeriesIteratorValue::value, py::const_))
68
76 .def("value", py::overload_cast<int>(&DataSeriesIteratorValue::value, py::const_))
69 py::class_<DataSeriesIteratorValue>(m, "DataSeriesIteratorValue")
77 .def("values", &DataSeriesIteratorValue::values);
70 .def_property_readonly("x", &DataSeriesIteratorValue::x)
78
71 .def_property_readonly("y", &DataSeriesIteratorValue::y)
79 py::class_<IDataSeries, std::shared_ptr<IDataSeries>>(m, "IDataSeries")
72 .def("value",
80 .def("nbPoints", &IDataSeries::nbPoints)
73 py::overload_cast<>(&DataSeriesIteratorValue::value, py::const_))
81 .def_property_readonly("xAxisUnit", &IDataSeries::xAxisUnit)
74 .def("value",
82 .def_property_readonly("yAxisUnit", &IDataSeries::yAxisUnit)
75 py::overload_cast<int>(&DataSeriesIteratorValue::value, py::const_))
83 .def_property_readonly("valuesUnit", &IDataSeries::valuesUnit)
76 .def("values", &DataSeriesIteratorValue::values);
84 .def("__getitem__", [](IDataSeries& serie, int key) {
77
85 return *(serie.begin()+key);
78 py::class_<IDataSeries, std::shared_ptr<IDataSeries>>(m, "IDataSeries")
86 }, py::is_operator())
79 .def("nbPoints", &IDataSeries::nbPoints)
87 .def("__len__", &IDataSeries::nbPoints)
80 .def_property_readonly("xAxisUnit", &IDataSeries::xAxisUnit)
88 .def("__iter__", [](IDataSeries& serie) {
81 .def_property_readonly("yAxisUnit", &IDataSeries::yAxisUnit)
89 return py::make_iterator(serie.begin(), serie.end());
82 .def_property_readonly("valuesUnit", &IDataSeries::valuesUnit)
90 }, py::keep_alive<0, 1>())
83 .def("__getitem__",
91 .def("__repr__",__repr__<IDataSeries>);
84 [](IDataSeries& serie, int key) { return *(serie.begin() + key); },
92
85 py::is_operator())
93 py::class_<ArrayData<1>, std::shared_ptr<ArrayData<1>> >(m,"ArrayData1d")
86 .def("__len__", &IDataSeries::nbPoints)
94 .def("cdata", [](ArrayData<1>& array) {return array.cdata();});
87 .def("__iter__",
95
88 [](IDataSeries& serie) {
96 py::class_<ScalarSeries, std::shared_ptr<ScalarSeries>, IDataSeries>(m, "ScalarSeries")
89 return py::make_iterator(serie.begin(), serie.end());
97 .def("nbPoints", &ScalarSeries::nbPoints);
90 },
98
91 py::keep_alive<0, 1>())
99 py::class_<VectorSeries, std::shared_ptr<VectorSeries>, IDataSeries>(m, "VectorSeries")
92 .def("__repr__", __repr__<IDataSeries>);
100 .def("nbPoints", &VectorSeries::nbPoints);
93
101
94 py::class_<ArrayData<1>, std::shared_ptr<ArrayData<1>>>(m, "ArrayData1d")
102 py::class_<DataSeries<2>, std::shared_ptr<DataSeries<2>>, IDataSeries>(m,"DataSeries2d")
95 .def("cdata", [](ArrayData<1>& array) { return array.cdata(); });
103 .def_property_readonly("xAxis", py::overload_cast<>(&DataSeries<2>::xAxisData, py::const_))
96
104 .def_property_readonly("yAxis", py::overload_cast<>(&DataSeries<2>::yAxis, py::const_));
97 py::class_<ScalarSeries, std::shared_ptr<ScalarSeries>, IDataSeries>(
105
98 m, "ScalarSeries")
106 py::class_<SpectrogramSeries, std::shared_ptr<SpectrogramSeries>, DataSeries<2>>(m, "SpectrogramSeries")
99 .def("nbPoints", &ScalarSeries::nbPoints);
107 .def("nbPoints", &SpectrogramSeries::nbPoints)
100
108 .def("xRes", &SpectrogramSeries::xResolution);
101 py::class_<VectorSeries, std::shared_ptr<VectorSeries>, IDataSeries>(
109
102 m, "VectorSeries")
110
103 .def("nbPoints", &VectorSeries::nbPoints);
111 py::class_<IDataProvider, std::shared_ptr<IDataProvider>>(m, "IDataProvider");
104
112
105 py::class_<DataSeries<2>, std::shared_ptr<DataSeries<2>>, IDataSeries>(
113
106 m, "DataSeries2d")
114 py::class_<Variable,std::shared_ptr<Variable>>(m, "Variable")
107 .def_property_readonly(
115 .def(py::init<const QString&>())
108 "xAxis", py::overload_cast<>(&DataSeries<2>::xAxisData, py::const_))
116 .def_property("name", &Variable::name, &Variable::setName)
109 .def_property_readonly(
117 .def_property("range", &Variable::range, &Variable::setRange)
110 "yAxis", py::overload_cast<>(&DataSeries<2>::yAxis, py::const_));
118 .def_property("cacheRange", &Variable::cacheRange, &Variable::setCacheRange)
111
119 .def_property_readonly("nbPoints", &Variable::nbPoints)
112 py::class_<SpectrogramSeries, std::shared_ptr<SpectrogramSeries>,
120 .def_property_readonly("dataSeries", &Variable::dataSeries)
113 DataSeries<2>>(m, "SpectrogramSeries")
121 .def("__len__", [](Variable& variable) {
114 .def("nbPoints", &SpectrogramSeries::nbPoints)
122 auto rng = variable.dataSeries()->xAxisRange(variable.range().m_TStart,variable.range().m_TEnd);
115 .def("xRes", &SpectrogramSeries::xResolution);
123 return std::distance(rng.first,rng.second);
116
124 })
117 py::class_<IDataProvider, std::shared_ptr<IDataProvider>>(m, "IDataProvider");
125 .def("__iter__", [](Variable& variable) {
118
126 auto rng = variable.dataSeries()->xAxisRange(variable.range().m_TStart,variable.range().m_TEnd);
119 py::class_<Variable, std::shared_ptr<Variable>>(m, "Variable")
127 return py::make_iterator(rng.first, rng.second);
120 .def(py::init<const QString&>())
128 }, py::keep_alive<0, 1>())
121 .def_property("name", &Variable::name, &Variable::setName)
129 .def("__getitem__", [](Variable& variable, int key) {
122 .def_property("range", &Variable::range, &Variable::setRange)
130 //insane and slow!
123 .def_property("cacheRange", &Variable::cacheRange,
131 auto rng = variable.dataSeries()->xAxisRange(variable.range().m_TStart,variable.range().m_TEnd);
124 &Variable::setCacheRange)
132 if(key<0)
125 .def_property_readonly("nbPoints", &Variable::nbPoints)
133 return *(rng.second+key);
126 .def_property_readonly("dataSeries", &Variable::dataSeries)
134 else
127 .def("__len__",
135 return *(rng.first+key);
128 [](Variable& variable) {
136 })
129 auto rng = variable.dataSeries()->xAxisRange(
137 .def("__repr__",__repr__<Variable>);
130 variable.range().m_TStart, variable.range().m_TEnd);
138
131 return std::distance(rng.first, rng.second);
139
132 })
140 py::class_<DateTimeRange>(m,"SqpRange")
133 .def("__iter__",
141 //.def("fromDateTime", &DateTimeRange::fromDateTime, py::return_value_policy::move)
134 [](Variable& variable) {
142 .def(py::init([](double start, double stop){return DateTimeRange{start, stop};}))
135 auto rng = variable.dataSeries()->xAxisRange(
143 .def(py::init([](system_clock::time_point start, system_clock::time_point stop)
136 variable.range().m_TStart, variable.range().m_TEnd);
144 {
137 return py::make_iterator(rng.first, rng.second);
145 double start_ = 0.001 * duration_cast<milliseconds>(start.time_since_epoch()).count();
138 },
146 double stop_ = 0.001 * duration_cast<milliseconds>(stop.time_since_epoch()).count();
139 py::keep_alive<0, 1>())
147 return DateTimeRange{start_, stop_};
140 .def("__getitem__",
148 }))
141 [](Variable& variable, int key) {
149 .def_property_readonly("start", [](const DateTimeRange& range){
142 // insane and slow!
150 return system_clock::from_time_t(range.m_TStart);
143 auto rng = variable.dataSeries()->xAxisRange(
151 })
144 variable.range().m_TStart, variable.range().m_TEnd);
152 .def_property_readonly("stop", [](const DateTimeRange& range){
145 if(key < 0)
153 return system_clock::from_time_t(range.m_TEnd);
146 return *(rng.second + key);
154 })
147 else
155 .def("__repr__", __repr__<DateTimeRange>);
148 return *(rng.first + key);
156
149 })
150 .def("__repr__", __repr__<Variable>);
151
152 py::class_<DateTimeRange>(m, "SqpRange")
153 //.def("fromDateTime", &DateTimeRange::fromDateTime,
154 //py::return_value_policy::move)
155 .def(py::init([](double start, double stop) {
156 return DateTimeRange{start, stop};
157 }))
158 .def(py::init(
159 [](system_clock::time_point start, system_clock::time_point stop) {
160 double start_ =
161 0.001 *
162 duration_cast<milliseconds>(start.time_since_epoch()).count();
163 double stop_ =
164 0.001 *
165 duration_cast<milliseconds>(stop.time_since_epoch()).count();
166 return DateTimeRange{start_, stop_};
167 }))
168 .def_property_readonly("start",
169 [](const DateTimeRange& range) {
170 return system_clock::from_time_t(range.m_TStart);
171 })
172 .def_property_readonly("stop",
173 [](const DateTimeRange& range) {
174 return system_clock::from_time_t(range.m_TEnd);
175 })
176 .def("__repr__", __repr__<DateTimeRange>);
157 }
177 }
General Comments 0
You need to be logged in to leave comments. Login now