##// END OF EJS Templates
Removed old Variable impl...
jeandet -
r69:cc26524fb5d1
parent child
Show More
@@ -1,226 +1,199
1 1 cmake_minimum_required(VERSION 3.6)
2 2 project(SciQLOPCore CXX)
3 3
4 4 OPTION (CPPCHECK "Analyzes the source code with cppcheck" OFF)
5 5 OPTION (CLANG_TIDY "Analyzes the source code with Clang Tidy" OFF)
6 6 OPTION (IWYU "Analyzes the source code with Include What You Use" OFF)
7 7 OPTION (PyWrappers "Enables Python 3 wrappers" ON)
8 8
9 9 OPTION (Catalog "builds catalog API" ON)
10 10
11 11 set(CMAKE_CXX_STANDARD 17)
12 12
13 13 set(CMAKE_AUTOMOC ON)
14 14 #https://gitlab.kitware.com/cmake/cmake/issues/15227
15 15 #set(CMAKE_AUTOUIC ON)
16 16 if(POLICY CMP0071)
17 17 cmake_policy(SET CMP0071 OLD)
18 18 endif()
19 19 set(CMAKE_AUTORCC ON)
20 20 set(CMAKE_INCLUDE_CURRENT_DIR ON)
21 21
22 22 find_package(Qt5 COMPONENTS Core Widgets Concurrent Network PrintSupport Svg Test REQUIRED)
23 23
24 24 if(PyWrappers)
25 25 find_package(pybind11 CONFIG QUIET)
26 26 if (NOT pybind11_FOUND)
27 27 if(NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/external/pybind11/CMakeLists.txt)
28 28 message("Init submodule pybind11")
29 29 execute_process(COMMAND git submodule init external/pybind11 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
30 30 execute_process(COMMAND git submodule update external/pybind11 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
31 31 endif()
32 32 add_subdirectory(external/pybind11)
33 33 endif()
34 34 endif()
35 35
36 36 find_package(catalogicpp CONFIG QUIET)
37 37 if (NOT catalogicpp_FOUND)
38 38 if(NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/external/catalogicpp/CMakeLists.txt)
39 39 message("Init submodule catalogicpp")
40 40 execute_process(COMMAND git submodule init external/catalogicpp WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
41 41 execute_process(COMMAND git submodule update external/catalogicpp WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
42 42 endif()
43 43 add_subdirectory(external/catalogicpp)
44 44 endif()
45 45
46 46 find_package(TimeSeries CONFIG QUIET)
47 47 if (NOT TimeSeries_FOUND)
48 48 if(NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/external/TimeSeries/CMakeLists.txt)
49 49 message("Init submodule TimeSeries")
50 50 execute_process(COMMAND git submodule init external/TimeSeries WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
51 51 execute_process(COMMAND git submodule update external/TimeSeries WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
52 52 endif()
53 53 add_subdirectory(external/TimeSeries)
54 54 endif()
55 55
56 56 macro(declare_test testname testexe sources libraries)
57 57 add_executable(${testexe} ${sources})
58 58 target_link_libraries(${testexe} ${libraries})
59 59 add_test(NAME ${testname} COMMAND ${testexe})
60 60 endmacro(declare_test)
61 61
62 62 enable_testing()
63 63
64 64 FILE (GLOB_RECURSE core_SRCS
65 65 ./include/DataSource/DataSourceItemMergeHelper.h
66 66 ./include/DataSource/DataSourceItemAction.h
67 67 ./include/DataSource/DataSourceItem.h
68 68 ./include/DataSource/DataSourceController.h
69 69 ./include/Common/SortUtils.h
70 70 ./include/Common/spimpl.h
71 71 ./include/Common/MimeTypesDef.h
72 72 ./include/Common/MetaTypes.h
73 73 ./include/Common/StringUtils.h
74 74 ./include/Common/SignalWaiter.h
75 75 ./include/Common/DateUtils.h
76 76 ./include/Common/Numeric.h
77 77 ./include/Common/deprecate.h
78 78 ./include/Common/containers.h
79 79 ./include/Common/debug.h
80 80 ./include/Common/cpp_utils.h
81 ./include/Common/variant_with_base.h
82 81 ./include/Plugin/IPlugin.h
83 ./include/Data/ArrayDataIterator.h
84 ./include/Data/VectorSeries.h
85 82 ./include/Data/VectorTimeSerie.h
86 83 ./include/Data/DateTimeRange.h
87 84 ./include/Data/DateTimeRangeHelper.h
88 ./include/Data/ScalarSeries.h
89 85 ./include/Data/ScalarTimeSerie.h
90 ./include/Data/DataSeriesMergeHelper.h
91 ./include/Data/DataSeries.h
92 86 ./include/Data/DataSeriesType.h
93 87 ./include/Data/SqpIterator.h
94 ./include/Data/ArrayData.h
95 ./include/Data/DataSeriesIterator.h
96 ./include/Data/DataSeriesUtils.h
97 ./include/Data/SpectrogramSeries.h
98 88 ./include/Data/SpectrogramTimeSerie.h
99 ./include/Data/Unit.h
100 89 ./include/Data/DataProviderParameters.h
101 ./include/Data/OptionalAxis.h
102 90 ./include/Data/IDataProvider.h
103 ./include/Data/IDataSeries.h
104 91 ./include/Network/NetworkController.h
105 92 ./include/Network/Downloader.h
106 93 ./include/Version.h
107 94 ./include/CoreGlobal.h
108 95 ./include/Visualization/VisualizationController.h
109 96 ./include/PluginManager/PluginManager.h
110 97 ./include/Variable/VariableModel2.h
111 ./include/Variable/VariableCacheStrategy.h
112 98 ./include/Variable/VariableSynchronizationGroup2.h
113 ./include/Variable/ProportionalCacheStrategy.h
114 ./include/Variable/SingleThresholdCacheStrategy.h
115 ./include/Variable/VariableCacheStrategyFactory.h
116 ./include/Variable/Variable.h
117 99 ./include/Variable/Variable2.h
118 100 ./include/Variable/VariableController2.h
119 101 ./include/Variable/private/VCTransaction.h
120 102 ./include/Time/TimeController.h
121 103 ./include/Settings/ISqpSettingsBindable.h
122 104 ./include/Settings/SqpSettingsDefs.h
123 105
124 106 ./src/DataSource/DataSourceItem.cpp
125 107 ./src/DataSource/DataSourceItemAction.cpp
126 108 ./src/DataSource/DataSourceItemMergeHelper.cpp
127 109 ./src/DataSource/DataSourceController.cpp
128 110 ./src/Common/DateUtils.cpp
129 111 ./src/Common/MimeTypesDef.cpp
130 112 ./src/Common/StringUtils.cpp
131 113 ./src/Common/SignalWaiter.cpp
132 ./src/Data/ScalarSeries.cpp
133 ./src/Data/ScalarTimeSerie.cpp
134 ./src/Data/DataSeriesIterator.cpp
135 ./src/Data/OptionalAxis.cpp
136 ./src/Data/ArrayDataIterator.cpp
137 ./src/Data/SpectrogramSeries.cpp
138 ./src/Data/DataSeriesUtils.cpp
139 ./src/Data/VectorSeries.cpp
140 ./src/Data/VectorTimeSerie.cpp
141 114 ./src/Network/NetworkController.cpp
142 115 ./src/Network/Downloader.cpp
143 116 ./src/Visualization/VisualizationController.cpp
144 117 ./src/PluginManager/PluginManager.cpp
145 118 ./src/Variable/VariableController2.cpp
146 119 ./src/Variable/VariableModel2.cpp
147 120 ./src/Variable/VariableSynchronizationGroup2.cpp
148 121 ./src/Variable/Variable.cpp
149 122 ./src/Variable/Variable2.cpp
150 123 ./src/Version.cpp
151 124 ./src/Time/TimeController.cpp
152 125 ./src/Settings/SqpSettingsDefs.cpp
153 126
154 127 )
155 128
156 129
157 130 IF(Catalog)
158 131 FILE (GLOB_RECURSE core_catalog_SRCS
159 132 ./src/Catalogue/CatalogueController.cpp
160 133 ./include/Catalogue/CatalogueController.h
161 134 )
162 135 ELSE()
163 136 FILE (GLOB_RECURSE core_catalog_SRCS
164 137 )
165 138 ENDIF(Catalog)
166 139
167 140 add_definitions(-DCORE_STATIC)
168 141 #add_definitions(-DHIDE_DEPRECATED)
169 142 add_definitions(-DSCIQLOP_CRASH_ON_ERROR)
170 143
171 144 add_library(sciqlopcore ${core_SRCS} ${core_catalog_SRCS})
172 145 SET_TARGET_PROPERTIES(sciqlopcore PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
173 146 add_definitions(-DCORE_LIB)
174 147
175 148 target_include_directories(sciqlopcore PUBLIC
176 149 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
177 150 $<INSTALL_INTERFACE:include/SciQLOP>
178 151 )
179 152
180 153 target_link_libraries(sciqlopcore PUBLIC
181 154 Qt5::Core
182 155 Qt5::Network
183 156 TimeSeries
184 157 )
185 158
186 159 if(Catalog)
187 160 target_link_libraries(sciqlopcore PUBLIC
188 161 CatalogiCpp
189 162 )
190 163 endif()
191 164
192 165
193 166 if(PyWrappers)
194 167 if(MINGW)
195 168 add_definitions(-D_hypot=hypot)
196 169 endif()
197 170 pybind11_add_module(sciqlopqt src/pybind11_wrappers/QtWrappers.cpp)
198 171 target_link_libraries(sciqlopqt PUBLIC Qt5::Core)
199 172
200 173 pybind11_add_module(pysciqlopcore src/pybind11_wrappers/CoreWrappers.cpp)
201 174 target_link_libraries(pysciqlopcore PUBLIC sciqlopcore)
202 175
203 176 pybind11_add_module(pysciqlopcatalogs src/pybind11_wrappers/CatalogWrappers.cpp)
204 177 target_link_libraries(pysciqlopcatalogs PUBLIC sciqlopcore)
205 178
206 179 add_library(pysciqlop src/pybind11_wrappers/pywrappers_common.h)
207 180 target_link_libraries(pysciqlop PUBLIC Qt5::Core)
208 181 target_include_directories(pysciqlop PUBLIC
209 182 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/pybind11_wrappers/>
210 183 $<INSTALL_INTERFACE:include/SciQLOP/py_wrappers>
211 184 )
212 185 endif()
213 186
214 187 SET_PROPERTY(GLOBAL PROPERTY CORE_PYTHON_PATH ${CMAKE_CURRENT_BINARY_DIR})
215 188
216 189
217 190 install(TARGETS sciqlopcore EXPORT SciQLOPCoreConfig
218 191 ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
219 192 LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
220 193 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
221 194
222 195 install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/SciQLOP)
223 196 install(EXPORT SciQLOPCoreConfig DESTINATION share/SciQLOPCore/cmake)
224 197 export(TARGETS sciqlopcore FILE SciQLOPCoreConfig.cmake)
225 198
226 199 add_subdirectory(tests)
@@ -1,98 +1,97
1 1 #ifndef SCIQLOP_VARIABLE2_H
2 2 #define SCIQLOP_VARIABLE2_H
3 3
4 4 #include "CoreGlobal.h"
5 5
6 6 #include <Common/MetaTypes.h>
7 7 #include <Common/deprecate.h>
8 8 #include <Common/spimpl.h>
9 #include <Common/variant_with_base.h>
10 9 #include <Data/DataSeriesType.h>
11 10 #include <Data/DateTimeRange.h>
12 11 #include <Data/ScalarTimeSerie.h>
13 12 #include <Data/SpectrogramTimeSerie.h>
14 13 #include <Data/VectorTimeSerie.h>
15 14 #include <QDataStream>
16 15 #include <QObject>
17 16 #include <QReadWriteLock>
18 17 #include <QUuid>
19 18 #include <TimeSeries.h>
20 19 #include <optional>
21 20
22 21 class SCIQLOP_CORE_EXPORT Variable2 : public QObject
23 22 {
24 23 Q_OBJECT
25 24
26 25 public:
27 26 explicit Variable2(const QString& name, const QVariantHash& metadata = {});
28 27
29 28 /// Copy ctor
30 29 explicit Variable2(const Variable2& other);
31 30
32 31 std::shared_ptr<Variable2> clone() const;
33 32
34 33 QString name();
35 34 void setName(const QString& name);
36 35 DateTimeRange range();
37 36 void setRange(const DateTimeRange& range);
38 37 std::optional<DateTimeRange> realRange();
39 38
40 39 std::size_t nbPoints();
41 40
42 41 /// @return the data of the variable, nullptr if there is no data
43 42 std::shared_ptr<TimeSeries::ITimeSerie> data();
44 43
45 44 /// @return the type of data that the variable holds
46 45 DataSeriesType type();
47 46
48 47 QVariantHash metadata() const noexcept;
49 48
50 49 // void setData(const std::vector<AnyTimeSerie*>& dataSeries,
51 50 // const DateTimeRange& range, bool notify = true);
52 51
53 52 void setData(const std::vector<TimeSeries::ITimeSerie*>& dataSeries,
54 53 const DateTimeRange& range, bool notify = true);
55 54
56 55 static QByteArray
57 56 mimeData(const std::vector<std::shared_ptr<Variable2>>& variables)
58 57 {
59 58 auto encodedData = QByteArray{};
60 59 QDataStream stream{&encodedData, QIODevice::WriteOnly};
61 60 for(auto& var : variables)
62 61 {
63 62 stream << var->ID().toByteArray();
64 63 }
65 64 return encodedData;
66 65 }
67 66
68 67 static std::vector<QUuid> IDs(QByteArray mimeData)
69 68 {
70 69 std::vector<QUuid> variables;
71 70 QDataStream stream{mimeData};
72 71
73 72 QVariantList ids;
74 73 stream >> ids;
75 74 std::transform(std::cbegin(ids), std::cend(ids),
76 75 std::back_inserter(variables),
77 76 [](const auto& id) { return id.toByteArray(); });
78 77 return variables;
79 78 }
80 79
81 80 operator QUuid() { return _uuid; }
82 81 QUuid ID() { return _uuid; }
83 82 signals:
84 83 void updated(QUuid ID);
85 84
86 85 private:
87 86 struct VariablePrivate;
88 87 spimpl::unique_impl_ptr<VariablePrivate> impl;
89 88 QUuid _uuid;
90 89 QReadWriteLock m_lock;
91 90 };
92 91
93 92 // Required for using shared_ptr in signals/slots
94 93 // SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable2>)
95 94 // SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_VECTOR_REGISTRY,
96 95 // QVector<std::shared_ptr<Variable2>>)
97 96
98 97 #endif // SCIQLOP_VARIABLE2_H
@@ -1,451 +1,447
1 1 #include "Variable/VariableController2.h"
2 2
3 3 #include "Variable/VariableSynchronizationGroup2.h"
4 4
5 5 #include <Common/containers.h>
6 6 #include <Common/debug.h>
7 7 #include <Data/DataProviderParameters.h>
8 8 #include <Data/DateTimeRange.h>
9 9 #include <Data/DateTimeRangeHelper.h>
10 10 #include <QCoreApplication>
11 11 #include <QDataStream>
12 12 #include <QObject>
13 13 #include <QQueue>
14 14 #include <QRunnable>
15 15 #include <QThreadPool>
16 #include <Variable/VariableCacheStrategyFactory.h>
17 16 #include <Variable/private/VCTransaction.h>
18 17
19 18 class VariableController2::VariableController2Private
20 19 {
21 20 struct threadSafeVaraiblesMaps
22 21 {
23 22 inline void
24 23 addVariable(const std::shared_ptr<Variable2>& variable,
25 24 const std::shared_ptr<IDataProvider>& provider,
26 25 const std::shared_ptr<VariableSynchronizationGroup2>&
27 26 synchronizationGroup)
28 27 {
29 28 QWriteLocker lock{&_lock};
30 29 _variables[*variable] = variable;
31 30 _providers[*variable] = provider;
32 31 _synchronizationGroups[*variable] = synchronizationGroup;
33 32 }
34 33
35 34 inline void removeVariable(const std::shared_ptr<Variable2>& variable)
36 35 {
37 36 QWriteLocker lock{&_lock};
38 37 _variables.erase(*variable);
39 38 _providers.remove(*variable);
40 39 _synchronizationGroups.remove(*variable);
41 40 }
42 41
43 42 inline void
44 43 synchronize(const std::shared_ptr<Variable2>& variable,
45 44 const std::optional<std::shared_ptr<Variable2>>& with)
46 45 {
47 46 QWriteLocker lock{&_lock};
48 47 if(with.has_value())
49 48 {
50 49 auto newGroup = _synchronizationGroups[*with.value()];
51 50 newGroup->addVariable(*variable);
52 51 _synchronizationGroups[*variable] = newGroup;
53 52 }
54 53 else
55 54 {
56 55 _synchronizationGroups[*variable] =
57 56 std::make_shared<VariableSynchronizationGroup2>(*variable);
58 57 }
59 58 }
60 59
61 60 inline std::shared_ptr<Variable2> variable(QUuid variable)
62 61 {
63 62 QReadLocker lock{&_lock};
64 63 auto it = _variables.find(variable);
65 64 #if __cplusplus > 201703L
66 65 [[unlikely]]
67 66 #endif
68 67 if(it == _variables.end())
69 68 SCIQLOP_ERROR(threadSafeVaraiblesMaps, "Unknown Variable");
70 69 return (*it).second;
71 70 }
72 71
73 72 inline std::shared_ptr<Variable2> variable(int index)
74 73 {
75 74 QReadLocker lock{&_lock};
76 75 #if __cplusplus > 201703L
77 76 [[unlikely]]
78 77 #endif
79 78 if(!_variables.size() > index)
80 79 SCIQLOP_ERROR(threadSafeVaraiblesMaps, "Index is out of bounds");
81 80 auto it = _variables.cbegin();
82 81 while(index != 0)
83 82 {
84 83 index -= 1;
85 84 it++;
86 85 }
87 86 return (*(it)).second;
88 87 }
89 88
90 89 inline const std::vector<std::shared_ptr<Variable2>> variables()
91 90 {
92 91 std::vector<std::shared_ptr<Variable2>> vars;
93 92 QReadLocker lock{&_lock};
94 93 for(const auto& [id, var] : _variables)
95 94 {
96 95 vars.push_back(var);
97 96 }
98 97 return vars;
99 98 }
100 99
101 100 inline std::shared_ptr<IDataProvider> provider(QUuid variable)
102 101 {
103 102 QReadLocker lock{&_lock};
104 103 #if __cplusplus > 201703L
105 104 [[unlikely]]
106 105 #endif
107 106 if(!_providers.contains(variable))
108 107 SCIQLOP_ERROR(threadSafeVaraiblesMaps, "Unknown Variable");
109 108 return _providers[variable];
110 109 }
111 110
112 111 inline std::shared_ptr<VariableSynchronizationGroup2> group(QUuid variable)
113 112 {
114 113 QReadLocker lock{&_lock};
115 114 #if __cplusplus > 201703L
116 115 [[unlikely]]
117 116 #endif
118 117 if(!_synchronizationGroups.contains(variable))
119 118 SCIQLOP_ERROR(threadSafeVaraiblesMaps, "Unknown Variable");
120 119 return _synchronizationGroups[variable];
121 120 }
122 121
123 122 inline bool has(const std::shared_ptr<Variable2>& variable)
124 123 {
125 124 QReadLocker lock{&_lock};
126 125 return _variables.find(*variable) == _variables.end();
127 126 }
128 127
129 128 private:
130 129 std::map<QUuid, std::shared_ptr<Variable2>> _variables;
131 130 QMap<QUuid, std::shared_ptr<IDataProvider>> _providers;
132 131 QMap<QUuid, std::shared_ptr<VariableSynchronizationGroup2>>
133 132 _synchronizationGroups;
134 133 QReadWriteLock _lock{QReadWriteLock::Recursive};
135 134 } _maps;
136 135 std::vector<QUuid> _variablesToRemove;
137 136 QThreadPool* _ThreadPool;
138 137 VCTransactionsQueues _transactions;
139 std::unique_ptr<VariableCacheStrategy> _cacheStrategy;
140 138
141 139 void _transactionComplete(QUuid group,
142 140 std::shared_ptr<VCTransaction> transaction)
143 141 {
144 142 if(transaction->done()) { _transactions.complete(group); }
145 143 this->_processTransactions();
146 144 }
147 145
148 146 void _cleanupVariables()
149 147 {
150 148 for(auto id : _variablesToRemove)
151 149 {
152 150 auto v = this->variable(id);
153 151 if(!hasPendingTransactions(v))
154 152 {
155 153 _variablesToRemove.erase(std::remove(_variablesToRemove.begin(),
156 154 _variablesToRemove.end(), id),
157 155 _variablesToRemove.end());
158 156 this->deleteVariable(v);
159 157 }
160 158 }
161 159 }
162 160
163 161 void _processTransactions(bool fragmented = false)
164 162 {
165 163 auto nextTransactions = _transactions.nextTransactions();
166 164 auto pendingTransactions = _transactions.pendingTransactions();
167 165 for(auto [groupID, newTransaction] : nextTransactions)
168 166 {
169 167 if(newTransaction.has_value() &&
170 168 !pendingTransactions[groupID].has_value())
171 169 {
172 170 _transactions.start(groupID);
173 171 auto refVar = _maps.variable(newTransaction.value()->refVar);
174 172 auto ranges =
175 173 _computeAllRangesInGroup(refVar, newTransaction.value()->range);
176 174 for(auto const& [ID, range] : ranges)
177 175 {
178 176 auto provider = _maps.provider(ID);
179 177 auto variable = _maps.variable(ID);
180 178 if(fragmented)
181 179 {
182 180 auto missingRanges = _computeMissingRanges(variable, range);
183 181
184 182 auto exe =
185 183 new TransactionExe(variable, provider, missingRanges, range);
186 184 QObject::connect(
187 185 exe, &TransactionExe::transactionComplete,
188 186 [groupID = groupID, transaction = newTransaction.value(),
189 187 this]() { this->_transactionComplete(groupID, transaction); });
190 188 _ThreadPool->start(exe);
191 189 }
192 190 else
193 191 {
194 192 auto exe = new TransactionExe(variable, provider, {range}, range);
195 193 QObject::connect(
196 194 exe, &TransactionExe::transactionComplete,
197 195 [groupID = groupID, transaction = newTransaction.value(),
198 196 this]() { this->_transactionComplete(groupID, transaction); });
199 197 _ThreadPool->start(exe);
200 198 }
201 199 }
202 200 }
203 201 }
204 202 // after each transaction update we get a new distribution of idle and
205 203 // working variables so we can delete variables which are waiting to be
206 204 // deleted if they are now idle
207 205 _cleanupVariables();
208 206 }
209 207
210 208 std::map<QUuid, DateTimeRange>
211 209 _computeAllRangesInGroup(const std::shared_ptr<Variable2>& refVar,
212 210 DateTimeRange r)
213 211 {
214 212 std::map<QUuid, DateTimeRange> ranges;
215 213 if(!DateTimeRangeHelper::hasnan(r))
216 214 {
217 215 auto group = _maps.group(*refVar);
218 216 if(auto transformation =
219 217 DateTimeRangeHelper::computeTransformation(refVar->range(), r);
220 218 transformation.has_value())
221 219 {
222 220 for(auto varId : group->variables())
223 221 {
224 222 auto var = _maps.variable(varId);
225 223 auto newRange = var->range().transform(transformation.value());
226 224 ranges[varId] = newRange;
227 225 }
228 226 }
229 227 else // force new range to all variables -> may be weird if more than one
230 228 // var in the group
231 229 // @TODO ensure that there is no side effects
232 230 {
233 231 for(auto varId : group->variables())
234 232 {
235 233 auto var = _maps.variable(varId);
236 234 ranges[varId] = r;
237 235 }
238 236 }
239 237 }
240 238 else
241 239 {
242 240 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
243 241 }
244 242 return ranges;
245 243 }
246 244
247 245 std::vector<DateTimeRange>
248 246 _computeMissingRanges(const std::shared_ptr<Variable2>& var, DateTimeRange r)
249 247 {
250 248 return r - var->range();
251 249 }
252 250
253 251 void _changeRange(QUuid id, DateTimeRange r)
254 252 {
255 253 _changeRange(_maps.variable(id), r);
256 254 }
257 255 void _changeRange(const std::shared_ptr<Variable2>& var, DateTimeRange r)
258 256 {
259 257 auto provider = _maps.provider(*var);
260 258 auto missingRanges = _computeMissingRanges(var, r);
261 259 std::vector<TimeSeries::ITimeSerie*> data;
262 260 for(auto range : missingRanges)
263 261 {
264 262 data.push_back(
265 263 provider->getData(DataProviderParameters{{range}, var->metadata()}));
266 264 }
267 265 data.push_back(var->data().get()); // might be smarter
268 266 var->setData(data, r, true);
269 267 }
270 268
271 269 public:
272 270 VariableController2Private(QObject* parent = Q_NULLPTR)
273 : _cacheStrategy(VariableCacheStrategyFactory::createCacheStrategy(
274 CacheStrategy::SingleThreshold))
275 271 {
276 272 Q_UNUSED(parent);
277 273 this->_ThreadPool = new QThreadPool();
278 274 this->_ThreadPool->setMaxThreadCount(32);
279 275 }
280 276
281 277 /*
282 278 * This dtor has to like this even if this is ugly, because default dtor would
283 279 * rely on declaration order to destruct members and that would always lead to
284 280 * regressions when modifying class members
285 281 */
286 282 ~VariableController2Private() { delete this->_ThreadPool; }
287 283
288 284 std::shared_ptr<Variable2>
289 285 createVariable(const QString& name, const QVariantHash& metadata,
290 286 std::shared_ptr<IDataProvider> provider)
291 287 {
292 288 auto newVar = std::make_shared<Variable2>(name, metadata);
293 289 auto group = std::make_shared<VariableSynchronizationGroup2>(newVar->ID());
294 290 _maps.addVariable(newVar, std::move(provider), group);
295 291 this->_transactions.addEntry(*group);
296 292 return newVar;
297 293 }
298 294
299 295 std::shared_ptr<Variable2> variable(QUuid ID) { return _maps.variable(ID); }
300 296
301 297 std::shared_ptr<Variable2> variable(int index)
302 298 {
303 299 return _maps.variable(index);
304 300 }
305 301
306 302 std::shared_ptr<Variable2>
307 303 cloneVariable(const std::shared_ptr<Variable2>& variable)
308 304 {
309 305 auto newVar = variable->clone();
310 306 _maps.synchronize(newVar, std::nullopt);
311 307 _maps.addVariable(newVar, _maps.provider(*variable), _maps.group(*newVar));
312 308 this->_transactions.addEntry(*_maps.group(*newVar));
313 309 return newVar;
314 310 }
315 311
316 312 bool hasPendingTransactions(const std::shared_ptr<Variable2>& variable)
317 313 {
318 314 return _transactions.active(*_maps.group(*variable));
319 315 }
320 316
321 317 bool hasPendingTransactions()
322 318 {
323 319 bool has = false;
324 320 for(const auto& var : _maps.variables())
325 321 {
326 322 has |= _transactions.active(*_maps.group(*var));
327 323 }
328 324 return has;
329 325 }
330 326
331 327 void deleteVariable(const std::shared_ptr<Variable2>& variable)
332 328 {
333 329 if(!hasPendingTransactions(variable))
334 330 _maps.removeVariable(variable);
335 331 else
336 332 _variablesToRemove.push_back(variable->ID());
337 333 }
338 334
339 335 void asyncChangeRange(const std::shared_ptr<Variable2>& variable,
340 336 const DateTimeRange& r)
341 337 {
342 338 if(!DateTimeRangeHelper::hasnan(r))
343 339 {
344 340 auto group = _maps.group(*variable);
345 341 // Just overwrite next transaction
346 342 {
347 343 _transactions.enqueue(*group,
348 344 std::make_shared<VCTransaction>(
349 345 variable->ID(), r,
350 346 static_cast<int>(group->variables().size())));
351 347 }
352 348 _processTransactions();
353 349 }
354 350 else
355 351 {
356 352 SCIQLOP_ERROR(VariableController2Private, "Invalid range containing NaN");
357 353 }
358 354 }
359 355
360 356 void changeRange(const std::shared_ptr<Variable2>& variable, DateTimeRange r)
361 357 {
362 358 asyncChangeRange(variable, r);
363 359 while(hasPendingTransactions(variable))
364 360 {
365 361 QCoreApplication::processEvents();
366 362 }
367 363 }
368 364
369 365 inline void synchronize(const std::shared_ptr<Variable2>& var,
370 366 const std::shared_ptr<Variable2>& with)
371 367 {
372 368 _maps.synchronize(var, with);
373 369 }
374 370
375 371 inline const std::vector<std::shared_ptr<Variable2>> variables()
376 372 {
377 373 return _maps.variables();
378 374 }
379 375 };
380 376
381 377 VariableController2::VariableController2()
382 378 : impl{spimpl::make_unique_impl<VariableController2Private>()}
383 379 {}
384 380
385 381 std::shared_ptr<Variable2> VariableController2::createVariable(
386 382 const QString& name, const QVariantHash& metadata,
387 383 const std::shared_ptr<IDataProvider>& provider, const DateTimeRange& range)
388 384 {
389 385 auto var = impl->createVariable(name, metadata, provider);
390 386 var->setRange(range); // even with no data this is it's range
391 387 if(!DateTimeRangeHelper::hasnan(range))
392 388 impl->asyncChangeRange(var, range);
393 389 else
394 390 SCIQLOP_ERROR(VariableController2, "Creating a variable with default "
395 391 "constructed DateTimeRange is an error");
396 392 emit variableAdded(var);
397 393 return var;
398 394 }
399 395
400 396 std::shared_ptr<Variable2>
401 397 VariableController2::cloneVariable(const std::shared_ptr<Variable2>& variable)
402 398 {
403 399 return impl->cloneVariable(variable);
404 400 }
405 401
406 402 void VariableController2::deleteVariable(
407 403 const std::shared_ptr<Variable2>& variable)
408 404 {
409 405 impl->deleteVariable(variable);
410 406 emit variableDeleted(variable);
411 407 }
412 408
413 409 void VariableController2::changeRange(
414 410 const std::shared_ptr<Variable2>& variable, const DateTimeRange& r)
415 411 {
416 412 impl->changeRange(variable, r);
417 413 }
418 414
419 415 void VariableController2::asyncChangeRange(
420 416 const std::shared_ptr<Variable2>& variable, const DateTimeRange& r)
421 417 {
422 418 impl->asyncChangeRange(variable, r);
423 419 }
424 420
425 421 const std::vector<std::shared_ptr<Variable2>> VariableController2::variables()
426 422 {
427 423 return impl->variables();
428 424 }
429 425
430 426 bool VariableController2::isReady(const std::shared_ptr<Variable2>& variable)
431 427 {
432 428 return !impl->hasPendingTransactions(variable);
433 429 }
434 430
435 431 bool VariableController2::isReady() { return !impl->hasPendingTransactions(); }
436 432
437 433 void VariableController2::synchronize(const std::shared_ptr<Variable2>& var,
438 434 const std::shared_ptr<Variable2>& with)
439 435 {
440 436 impl->synchronize(var, with);
441 437 }
442 438
443 439 const std::vector<std::shared_ptr<Variable2>>
444 440 VariableController2::variables(const std::vector<QUuid>& ids)
445 441 {
446 442 std::vector<std::shared_ptr<Variable2>> variables;
447 443 std::transform(std::cbegin(ids), std::cend(ids),
448 444 std::back_inserter(variables),
449 445 [this](const auto& id) { return impl->variable(id); });
450 446 return variables;
451 447 }
@@ -1,279 +1,278
1 1 #include <Common/DateUtils.h>
2 2 #include <Common/MimeTypesDef.h>
3 3 #include <Common/StringUtils.h>
4 4 #include <Common/containers.h>
5 #include <Data/IDataSeries.h>
6 5 #include <DataSource/DataSourceController.h>
7 6 #include <QMimeData>
8 7 #include <QSize>
9 8 #include <QTimer>
10 9 #include <Time/TimeController.h>
11 10 #include <Variable/Variable2.h>
12 11 #include <Variable/VariableController2.h>
13 12 #include <Variable/VariableModel2.h>
14 13 #include <unordered_map>
15 14
16 15 namespace
17 16 {
18 17 // Column indexes
19 18 const auto NAME_COLUMN = 0;
20 19 const auto TSTART_COLUMN = 1;
21 20 const auto TEND_COLUMN = 2;
22 21 const auto NBPOINTS_COLUMN = 3;
23 22 const auto UNIT_COLUMN = 4;
24 23 const auto MISSION_COLUMN = 5;
25 24 const auto PLUGIN_COLUMN = 6;
26 25 const auto NB_COLUMNS = 7;
27 26
28 27 // Column properties
29 28 const auto DEFAULT_HEIGHT = 25;
30 29 const auto DEFAULT_WIDTH = 100;
31 30
32 31 struct ColumnProperties
33 32 {
34 33 ColumnProperties(const QString& name = {}, int width = DEFAULT_WIDTH,
35 34 int height = DEFAULT_HEIGHT)
36 35 : m_Name{name}, m_Width{width}, m_Height{height}
37 36 {}
38 37
39 38 QString m_Name;
40 39 int m_Width;
41 40 int m_Height;
42 41 };
43 42
44 43 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
45 44 {NAME_COLUMN, {QObject::tr("Name")}},
46 45 {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
47 46 {TEND_COLUMN, {QObject::tr("tEnd"), 180}},
48 47 {NBPOINTS_COLUMN, {QObject::tr("Nb points")}},
49 48 {UNIT_COLUMN, {QObject::tr("Unit")}},
50 49 {MISSION_COLUMN, {QObject::tr("Mission")}},
51 50 {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
52 51
53 52 QString uniqueName(const QString& defaultName,
54 53 const std::vector<std::shared_ptr<Variable2>>& variables)
55 54 {
56 55 auto forbiddenNames = std::vector<QString>(variables.size());
57 56 std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(),
58 57 [](const auto& variable) { return variable->name(); });
59 58 auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames);
60 59 Q_ASSERT(!uniqueName.isEmpty());
61 60
62 61 return uniqueName;
63 62 }
64 63
65 64 } // namespace
66 65
67 66 VariableModel2::VariableModel2(QObject* parent) : QAbstractTableModel{parent} {}
68 67
69 68 int VariableModel2::columnCount(const QModelIndex& parent) const
70 69 {
71 70 Q_UNUSED(parent);
72 71
73 72 return NB_COLUMNS;
74 73 }
75 74
76 75 int VariableModel2::rowCount(const QModelIndex& parent) const
77 76 {
78 77 Q_UNUSED(parent);
79 78 return _variables.size();
80 79 }
81 80
82 81 QVariant VariableModel2::data(const QModelIndex& index, int role) const
83 82 {
84 83 if(!index.isValid()) { return QVariant{}; }
85 84
86 85 if(index.row() < 0 || index.row() >= rowCount()) { return QVariant{}; }
87 86
88 87 if(role == Qt::DisplayRole)
89 88 {
90 89 if(auto variable = _variables[index.row()])
91 90 {
92 91 switch(index.column())
93 92 {
94 93 case NAME_COLUMN: return variable->name();
95 94 case TSTART_COLUMN:
96 95 {
97 96 if(auto range = variable->realRange(); range.has_value())
98 97 return DateUtils::dateTime(range.value().m_TStart)
99 98 .toString(DATETIME_FORMAT);
100 99 return QVariant{};
101 100 }
102 101 case TEND_COLUMN:
103 102 {
104 103 if(auto range = variable->realRange(); range.has_value())
105 104 return DateUtils::dateTime(range.value().m_TEnd)
106 105 .toString(DATETIME_FORMAT);
107 106 return QVariant{};
108 107 }
109 108 case NBPOINTS_COLUMN: return int(variable->nbPoints());
110 109 case UNIT_COLUMN:
111 110 return variable->metadata().value(QStringLiteral("units"));
112 111 case MISSION_COLUMN:
113 112 return variable->metadata().value(QStringLiteral("mission"));
114 113 case PLUGIN_COLUMN:
115 114 return variable->metadata().value(QStringLiteral("plugin"));
116 115 default:
117 116 // No action
118 117 break;
119 118 }
120 119 }
121 120 }
122 121 else if(role == VariableRoles::ProgressRole)
123 122 {
124 123 return QVariant{};
125 124 }
126 125
127 126 return QVariant{};
128 127 }
129 128
130 129 QVariant VariableModel2::headerData(int section, Qt::Orientation orientation,
131 130 int role) const
132 131 {
133 132 if(role != Qt::DisplayRole && role != Qt::SizeHintRole) { return QVariant{}; }
134 133
135 134 if(orientation == Qt::Horizontal)
136 135 {
137 136 auto propertiesIt = COLUMN_PROPERTIES.find(section);
138 137 if(propertiesIt != COLUMN_PROPERTIES.cend())
139 138 {
140 139 // Role is either DisplayRole or SizeHintRole
141 140 return (role == Qt::DisplayRole)
142 141 ? QVariant{propertiesIt->m_Name}
143 142 : QVariant{
144 143 QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
145 144 }
146 145 }
147 146
148 147 return QVariant{};
149 148 }
150 149
151 150 Qt::ItemFlags VariableModel2::flags(const QModelIndex& index) const
152 151 {
153 152 return QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled |
154 153 Qt::ItemIsDropEnabled;
155 154 }
156 155
157 156 Qt::DropActions VariableModel2::supportedDropActions() const
158 157 {
159 158 return Qt::CopyAction | Qt::MoveAction;
160 159 }
161 160
162 161 Qt::DropActions VariableModel2::supportedDragActions() const
163 162 {
164 163 return Qt::CopyAction | Qt::MoveAction;
165 164 }
166 165
167 166 QStringList VariableModel2::mimeTypes() const
168 167 {
169 168 return {MIME_TYPE_VARIABLE_LIST, MIME_TYPE_TIME_RANGE};
170 169 }
171 170
172 171 QMimeData* VariableModel2::mimeData(const QModelIndexList& indexes) const
173 172 {
174 173 auto mimeData = new QMimeData;
175 174 std::vector<std::shared_ptr<Variable2>> variables;
176 175
177 176 DateTimeRange firstTimeRange;
178 177 for(const auto& index : indexes)
179 178 {
180 179 if(index.column() == 0)
181 180 { // only the first column
182 181 auto variable = _variables[index.row()];
183 182 if(variable.get() && index.isValid())
184 183 {
185 184 if(variables.size() == 0)
186 185 {
187 186 // Gets the range of the first variable
188 187 firstTimeRange = variable->range();
189 188 }
190 189 variables.push_back(variable);
191 190 }
192 191 }
193 192 }
194 193
195 194 auto variablesEncodedData = Variable2::mimeData(variables);
196 195 mimeData->setData(MIME_TYPE_VARIABLE_LIST, variablesEncodedData);
197 196
198 197 if(variables.size() == 1)
199 198 {
200 199 // No time range MIME data if multiple variables are dragged
201 200 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
202 201 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
203 202 }
204 203
205 204 return mimeData;
206 205 }
207 206
208 207 bool VariableModel2::canDropMimeData(const QMimeData* data,
209 208 Qt::DropAction action, int row, int column,
210 209 const QModelIndex& parent) const
211 210 {
212 211 Q_UNUSED(column);
213 212 // drop of a product
214 213 return data->hasFormat(MIME_TYPE_PRODUCT_LIST) ||
215 214 (data->hasFormat(MIME_TYPE_TIME_RANGE) && parent.isValid() &&
216 215 !data->hasFormat(MIME_TYPE_VARIABLE_LIST));
217 216 }
218 217
219 218 bool VariableModel2::dropMimeData(const QMimeData* data, Qt::DropAction action,
220 219 int row, int column,
221 220 const QModelIndex& parent)
222 221 {
223 222 auto dropDone = false;
224 223
225 224 if(data->hasFormat(MIME_TYPE_PRODUCT_LIST))
226 225 {
227 226 auto productList = DataSourceController::productsDataForMimeData(
228 227 data->data(MIME_TYPE_PRODUCT_LIST));
229 228
230 229 for(auto metaData : productList)
231 230 {
232 231 emit createVariable(metaData.toHash());
233 232 }
234 233
235 234 dropDone = true;
236 235 }
237 236 else if(data->hasFormat(MIME_TYPE_TIME_RANGE) && parent.isValid())
238 237 {
239 238 auto variable = _variables[parent.row()];
240 239 auto range =
241 240 TimeController::timeRangeForMimeData(data->data(MIME_TYPE_TIME_RANGE));
242 241
243 242 emit asyncChangeRange(variable, range);
244 243
245 244 dropDone = true;
246 245 }
247 246
248 247 return dropDone;
249 248 }
250 249
251 250 void VariableModel2::variableUpdated(QUuid id) noexcept
252 251 {
253 252 emit dataChanged(QModelIndex(), QModelIndex());
254 253 }
255 254
256 255 void VariableModel2::variableAdded(const std::shared_ptr<Variable2>& variable)
257 256 {
258 257 if(!SciQLop::containers::contains(_variables, variable))
259 258 {
260 259 beginInsertRows(QModelIndex(), this->_variables.size(),
261 260 this->_variables.size());
262 261 this->_variables.push_back(variable);
263 262 endInsertRows();
264 263 connect(variable.get(), &Variable2::updated, this,
265 264 &VariableModel2::variableUpdated);
266 265 }
267 266 }
268 267
269 268 void VariableModel2::variableDeleted(const std::shared_ptr<Variable2>& variable)
270 269 {
271 270 auto it = std::find(_variables.begin(), _variables.end(), variable);
272 271 if(it != _variables.end())
273 272 {
274 273 auto index = std::distance(_variables.begin(), it);
275 274 beginRemoveRows(QModelIndex(), index, index);
276 275 _variables.erase(it);
277 276 endRemoveRows();
278 277 }
279 278 }
@@ -1,48 +1,43
1 #include <Visualization/VisualizationController.h>
2
3 #include <Variable/Variable.h>
4
5 #include <QMutex>
6 #include <QThread>
7
8 1 #include <QDir>
2 #include <QMutex>
9 3 #include <QStandardPaths>
4 #include <QThread>
5 #include <Visualization/VisualizationController.h>
10 6
11 7 Q_LOGGING_CATEGORY(LOG_VisualizationController, "VisualizationController")
12 8
13 class VisualizationController::VisualizationControllerPrivate {
9 class VisualizationController::VisualizationControllerPrivate
10 {
14 11 public:
15 QMutex m_WorkingMutex;
12 QMutex m_WorkingMutex;
16 13 };
17 14
18 VisualizationController::VisualizationController(QObject *parent)
19 : impl{spimpl::make_unique_impl<VisualizationControllerPrivate>()}
15 VisualizationController::VisualizationController(QObject* parent)
16 : impl{spimpl::make_unique_impl<VisualizationControllerPrivate>()}
20 17 {
21 qCDebug(LOG_VisualizationController()) << tr("VisualizationController construction")
22 << QThread::currentThread();
18 qCDebug(LOG_VisualizationController())
19 << tr("VisualizationController construction") << QThread::currentThread();
23 20 }
24 21
25 22 VisualizationController::~VisualizationController()
26 23 {
27 qCDebug(LOG_VisualizationController()) << tr("VisualizationController destruction")
28 << QThread::currentThread();
29 this->waitForFinish();
24 qCDebug(LOG_VisualizationController())
25 << tr("VisualizationController destruction") << QThread::currentThread();
26 this->waitForFinish();
30 27 }
31 28
32 29 void VisualizationController::initialize()
33 30 {
34 qCDebug(LOG_VisualizationController()) << tr("VisualizationController init")
35 << QThread::currentThread();
36 impl->m_WorkingMutex.lock();
37 qCDebug(LOG_VisualizationController()) << tr("VisualizationController init END");
31 qCDebug(LOG_VisualizationController())
32 << tr("VisualizationController init") << QThread::currentThread();
33 impl->m_WorkingMutex.lock();
34 qCDebug(LOG_VisualizationController())
35 << tr("VisualizationController init END");
38 36 }
39 37
40 void VisualizationController::finalize()
41 {
42 impl->m_WorkingMutex.unlock();
43 }
38 void VisualizationController::finalize() { impl->m_WorkingMutex.unlock(); }
44 39
45 40 void VisualizationController::waitForFinish()
46 41 {
47 QMutexLocker locker{&impl->m_WorkingMutex};
42 QMutexLocker locker{&impl->m_WorkingMutex};
48 43 }
@@ -1,349 +1,239
1 1 #include "CoreWrappers.h"
2 2
3 3 #include "pywrappers_common.h"
4 4
5 5 #include <Data/DataSeriesType.h>
6 6 #include <Data/IDataProvider.h>
7 #include <Data/OptionalAxis.h>
8 #include <Data/ScalarSeries.h>
9 #include <Data/SpectrogramSeries.h>
10 #include <Data/Unit.h>
11 #include <Data/VectorSeries.h>
12 7 #include <Network/Downloader.h>
13 8 #include <Time/TimeController.h>
14 9 #include <Variable/Variable2.h>
15 10 #include <Variable/VariableController2.h>
16 11 #include <pybind11/chrono.h>
17 12 #include <pybind11/embed.h>
18 13 #include <pybind11/functional.h>
19 14 #include <pybind11/numpy.h>
20 15 #include <pybind11/operators.h>
21 16 #include <pybind11/pybind11.h>
22 17 #include <pybind11/stl.h>
23 18 #include <pybind11/stl_bind.h>
24 19 #include <sstream>
25 20 #include <string>
26 21
27 22 namespace py = pybind11;
28 23 using namespace std::chrono;
29 24
30 25 template<typename T, typename U, bool row_major = true>
31 26 void copy_vector(py::array_t<double>& t, py::array_t<double>& values, T& dest_t,
32 27 U& dest_values)
33 28 {
34 29 auto t_view = t.unchecked<1>();
35 30 auto values_view = values.unchecked<2>();
36 31 if constexpr(row_major)
37 32 {
38 33 for(std::size_t i = 0; i < t.size(); i++)
39 34 {
40 35 dest_t[i] = t_view[i];
41 36 dest_values[i] = {values_view(i, 0), values_view(i, 1),
42 37 values_view(i, 2)};
43 38 }
44 39 }
45 40 else
46 41 {
47 42 for(std::size_t i = 0; i < t.size(); i++)
48 43 {
49 44 dest_t[i] = t_view[i];
50 45 dest_values[i] = {values_view(0, i), values_view(1, i),
51 46 values_view(2, i)};
52 47 }
53 48 }
54 49 }
55 50
56 51 template<typename T, typename U>
57 52 void copy_scalar(py::array_t<double>& t, py::array_t<double>& values, T& dest_t,
58 53 U& dest_values)
59 54 {
60 55 auto t_view = t.unchecked<1>();
61 56 auto values_view = values.unchecked<1>();
62 57 for(std::size_t i = 0; i < t.size(); i++)
63 58 {
64 59 dest_t[i] = t_view[i];
65 60 dest_values[i] = values_view[i];
66 61 }
67 62 }
68 63
69 64 template<typename T, typename U>
70 65 void copy_spectro(py::array_t<double>& t, py::array_t<double>& values,
71 66 T& dest_t, U& dest_values)
72 67 {
73 68 auto t_view = t.unchecked<1>();
74 69 auto values_view = values.unchecked<2>();
75 70 const auto width = values.shape(0);
76 71 for(std::size_t i = 0; i < t.size(); i++)
77 72 {
78 73 dest_t[i] = t_view[i];
79 74 for(int j = 0; j < width; j++)
80 75 {
81 76 dest_values[i * width + j] = values_view(j, i);
82 77 }
83 78 }
84 79 }
85 80
86 81 PYBIND11_MODULE(pysciqlopcore, m)
87 82 {
88 83 pybind11::bind_vector<std::vector<double>>(m, "VectorDouble");
89 84
90 85 py::enum_<DataSeriesType>(m, "DataSeriesType")
91 86 .value("SCALAR", DataSeriesType::SCALAR)
92 87 .value("SPECTROGRAM", DataSeriesType::SPECTROGRAM)
93 88 .value("VECTOR", DataSeriesType::VECTOR)
94 89 .value("NONE", DataSeriesType::NONE)
95 90 .export_values();
96 91
97 py::class_<Unit>(m, "Unit")
98 .def_readwrite("name", &Unit::m_Name)
99 .def_readwrite("time_unit", &Unit::m_TimeUnit)
100 .def(py::self == py::self)
101 .def(py::self != py::self)
102 .def("__repr__", __repr__<Unit>);
103
104 92 py::class_<Response>(m, "Response")
105 93 .def("status_code", &Response::status_code);
106 94
107 95 py::class_<Downloader>(m, "Downloader")
108 96 .def_static("get", Downloader::get)
109 97 .def_static("getAsync", Downloader::getAsync)
110 98 .def_static("downloadFinished", Downloader::downloadFinished);
111 99
112 py::class_<ArrayDataIteratorValue>(m, "ArrayDataIteratorValue")
113 .def_property_readonly("value", &ArrayDataIteratorValue::first);
114
115 py::class_<OptionalAxis>(m, "OptionalAxis")
116 .def("__len__", &OptionalAxis::size)
117 .def_property_readonly("size", &OptionalAxis::size)
118 .def("__getitem__",
119 [](OptionalAxis& ax, int key) {
120 return (*(ax.begin() + key)).first();
121 },
122 py::is_operator())
123 .def("__iter__",
124 [](OptionalAxis& ax) {
125 return py::make_iterator(ax.begin(), ax.end());
126 },
127 py::keep_alive<0, 1>());
128
129 py::class_<DataSeriesIteratorValue>(m, "DataSeriesIteratorValue")
130 .def_property_readonly("x", &DataSeriesIteratorValue::x)
131 .def_property_readonly("y", &DataSeriesIteratorValue::y)
132 .def("value",
133 py::overload_cast<>(&DataSeriesIteratorValue::value, py::const_))
134 .def("value",
135 py::overload_cast<int>(&DataSeriesIteratorValue::value, py::const_))
136 .def("values", &DataSeriesIteratorValue::values);
137
138 py::class_<IDataSeries, std::shared_ptr<IDataSeries>>(m, "IDataSeries")
139 .def("nbPoints", &IDataSeries::nbPoints)
140 .def_property_readonly("xAxisUnit", &IDataSeries::xAxisUnit)
141 .def_property_readonly("yAxisUnit", &IDataSeries::yAxisUnit)
142 .def_property_readonly("valuesUnit", &IDataSeries::valuesUnit)
143 .def("__getitem__",
144 [](IDataSeries& serie, int key) { return *(serie.begin() + key); },
145 py::is_operator())
146 .def("__len__", &IDataSeries::nbPoints)
147 .def("__iter__",
148 [](IDataSeries& serie) {
149 return py::make_iterator(serie.begin(), serie.end());
150 },
151 py::keep_alive<0, 1>())
152 .def("__repr__", __repr__<IDataSeries>);
153
154 py::class_<ArrayData<1>, std::shared_ptr<ArrayData<1>>>(m, "ArrayData1d")
155 .def("cdata", [](ArrayData<1>& array) { return array.cdata(); });
156
157 py::class_<ScalarSeries, std::shared_ptr<ScalarSeries>, IDataSeries>(
158 m, "ScalarSeries")
159 .def("nbPoints", &ScalarSeries::nbPoints);
160
161 py::class_<VectorSeries, std::shared_ptr<VectorSeries>, IDataSeries>(
162 m, "VectorSeries")
163 .def("nbPoints", &VectorSeries::nbPoints);
164
165 py::class_<DataSeries<2>, std::shared_ptr<DataSeries<2>>, IDataSeries>(
166 m, "DataSeries2d")
167 .def_property_readonly(
168 "xAxis", py::overload_cast<>(&DataSeries<2>::xAxisData, py::const_))
169 .def_property_readonly(
170 "yAxis", py::overload_cast<>(&DataSeries<2>::yAxis, py::const_));
171
172 py::class_<SpectrogramSeries, std::shared_ptr<SpectrogramSeries>,
173 DataSeries<2>>(m, "SpectrogramSeries")
174 .def("nbPoints", &SpectrogramSeries::nbPoints)
175 .def("xRes", &SpectrogramSeries::xResolution);
176
177 100 py::class_<IDataProvider, std::shared_ptr<IDataProvider>>(m, "IDataProvider");
178 101
179 py::class_<Variable, std::shared_ptr<Variable>>(m, "Variable")
180 .def(py::init<const QString&>())
181 .def_property("name", &Variable::name, &Variable::setName)
182 .def_property("range", &Variable::range, &Variable::setRange)
183 .def_property("cacheRange", &Variable::cacheRange,
184 &Variable::setCacheRange)
185 .def_property_readonly("nbPoints", &Variable::nbPoints)
186 .def_property_readonly("dataSeries", &Variable::dataSeries)
187 .def("__len__",
188 [](Variable& variable) {
189 auto rng = variable.dataSeries()->xAxisRange(
190 variable.range().m_TStart, variable.range().m_TEnd);
191 return std::distance(rng.first, rng.second);
192 })
193 .def("__iter__",
194 [](Variable& variable) {
195 auto rng = variable.dataSeries()->xAxisRange(
196 variable.range().m_TStart, variable.range().m_TEnd);
197 return py::make_iterator(rng.first, rng.second);
198 },
199 py::keep_alive<0, 1>())
200 .def("__getitem__",
201 [](Variable& variable, int key) {
202 // insane and slow!
203 auto rng = variable.dataSeries()->xAxisRange(
204 variable.range().m_TStart, variable.range().m_TEnd);
205 if(key < 0)
206 return *(rng.second + key);
207 else
208 return *(rng.first + key);
209 })
210 .def("__repr__", __repr__<Variable>);
211
212 102 py::class_<TimeSeries::ITimeSerie, std::shared_ptr<TimeSeries::ITimeSerie>>(
213 103 m, "ITimeSerie")
214 104 .def_property_readonly(
215 105 "size", [](const TimeSeries::ITimeSerie& ts) { return ts.size(); })
216 106 .def("__len__",
217 107 [](const TimeSeries::ITimeSerie& ts) { return ts.size(); })
218 108 .def_property_readonly(
219 109 "shape", [](const TimeSeries::ITimeSerie& ts) { return ts.shape(); })
220 110 .def_property_readonly(
221 111 "t",
222 112 [](TimeSeries::ITimeSerie& ts) -> decltype(ts.axis(0))& {
223 113 return ts.axis(0);
224 114 },
225 115 py::return_value_policy::reference);
226 116
227 117 py::class_<ScalarTimeSerie, TimeSeries::ITimeSerie>(m, "ScalarTimeSerie")
228 118 .def(py::init<>())
229 119 .def(py::init<std::size_t>())
230 120 .def(py::init([](py::array_t<double> t, py::array_t<double> values) {
231 121 assert(t.size() == values.size());
232 122 ScalarTimeSerie::axis_t _t(t.size());
233 123 ScalarTimeSerie::axis_t _values(t.size());
234 124 copy_scalar(t, values, _t, _values);
235 125 return ScalarTimeSerie(_t, _values);
236 126 }))
237 127 .def("__getitem__",
238 128 [](ScalarTimeSerie& ts, std::size_t key) { return ts[key]; })
239 129 .def("__setitem__", [](ScalarTimeSerie& ts, std::size_t key,
240 130 double value) { *(ts.begin() + key) = value; });
241 131
242 132 py::class_<VectorTimeSerie::raw_value_type>(m, "vector")
243 133 .def(py::init<>())
244 134 .def(py::init<double, double, double>())
245 135 .def("__repr__", __repr__<VectorTimeSerie::raw_value_type>)
246 136 .def_readwrite("x", &VectorTimeSerie::raw_value_type::x)
247 137 .def_readwrite("y", &VectorTimeSerie::raw_value_type::y)
248 138 .def_readwrite("z", &VectorTimeSerie::raw_value_type::z);
249 139
250 140 py::class_<VectorTimeSerie, TimeSeries::ITimeSerie>(m, "VectorTimeSerie")
251 141 .def(py::init<>())
252 142 .def(py::init<std::size_t>())
253 143 .def(py::init([](py::array_t<double> t, py::array_t<double> values) {
254 144 assert(t.size() * 3 == values.size());
255 145 VectorTimeSerie::axis_t _t(t.size());
256 146 VectorTimeSerie::container_type<VectorTimeSerie::raw_value_type>
257 147 _values(t.size());
258 148 if(values.shape()[0] == 3 && values.shape(1) != 3)
259 149 {
260 150 copy_vector<decltype(_t), decltype(_values), false>(t, values, _t,
261 151 _values);
262 152 }
263 153 else
264 154 {
265 155 copy_vector(t, values, _t, _values);
266 156 }
267 157
268 158 return VectorTimeSerie(_t, _values);
269 159 }))
270 160 .def("__getitem__",
271 161 [](VectorTimeSerie& ts, std::size_t key)
272 162 -> VectorTimeSerie::raw_value_type& { return ts[key]; },
273 163 py::return_value_policy::reference)
274 164 .def("__setitem__", [](VectorTimeSerie& ts, std::size_t key,
275 165 VectorTimeSerie::raw_value_type value) {
276 166 *(ts.begin() + key) = value;
277 167 });
278 168
279 169 py::class_<SpectrogramTimeSerie::iterator_t>(m, "SpectrogramTimeSerieItem")
280 170 .def("__getitem__", [](SpectrogramTimeSerie::iterator_t& self,
281 171 std::size_t key) { return (*self)[key]; })
282 172 .def("__setitem__",
283 173 [](SpectrogramTimeSerie::iterator_t& self, std::size_t key,
284 174 double value) { (*self)[key] = value; });
285 175
286 176 py::class_<SpectrogramTimeSerie, TimeSeries::ITimeSerie>(
287 177 m, "SpectrogramTimeSerie")
288 178 .def(py::init<>())
289 179 .def(py::init<const std::vector<std::size_t>>())
290 180 .def(py::init([](py::array_t<double> t, py::array_t<double> values) {
291 181 assert(t.size() < values.size()); // TODO check geometry
292 182 SpectrogramTimeSerie::axis_t _t(t.size());
293 183 SpectrogramTimeSerie::container_type<
294 184 SpectrogramTimeSerie::raw_value_type>
295 185 _values(values.size());
296 186 copy_spectro(t, values, _t, _values);
297 187 std::vector<std::size_t> shape;
298 188 shape.push_back(values.shape(1));
299 189 shape.push_back(values.shape(0));
300 190 return SpectrogramTimeSerie(_t, _values, shape);
301 191 }))
302 192 .def("__getitem__",
303 193 [](SpectrogramTimeSerie& ts,
304 194 std::size_t key) -> SpectrogramTimeSerie::iterator_t {
305 195 return ts.begin() + key;
306 196 });
307 197
308 198 py::class_<Variable2, std::shared_ptr<Variable2>>(m, "Variable2")
309 199 .def(py::init<const QString&>())
310 200 .def_property("name", &Variable2::name, &Variable2::setName)
311 201 .def_property_readonly("range", &Variable2::range)
312 202 .def_property_readonly("nbPoints", &Variable2::nbPoints)
313 203 .def_property_readonly(
314 204 "data",
315 205 [](Variable2& var) -> std::shared_ptr<TimeSeries::ITimeSerie> {
316 206 return var.data();
317 207 })
318 208 .def("set_data",
319 209 [](Variable2& var, std::vector<TimeSeries::ITimeSerie*> ts_list,
320 210 const DateTimeRange& range) { var.setData(ts_list, range); })
321 211 .def("__len__", &Variable2::nbPoints)
322 212 .def("__repr__", __repr__<Variable2>);
323 213
324 214 py::class_<DateTimeRange>(m, "SqpRange")
325 215 //.def("fromDateTime", &DateTimeRange::fromDateTime,
326 216 // py::return_value_policy::move)
327 217 .def(py::init([](double start, double stop) {
328 218 return DateTimeRange{start, stop};
329 219 }))
330 220 .def(py::init(
331 221 [](system_clock::time_point start, system_clock::time_point stop) {
332 222 double start_ =
333 223 0.001 *
334 224 duration_cast<milliseconds>(start.time_since_epoch()).count();
335 225 double stop_ =
336 226 0.001 *
337 227 duration_cast<milliseconds>(stop.time_since_epoch()).count();
338 228 return DateTimeRange{start_, stop_};
339 229 }))
340 230 .def_property_readonly("start",
341 231 [](const DateTimeRange& range) {
342 232 return system_clock::from_time_t(range.m_TStart);
343 233 })
344 234 .def_property_readonly("stop",
345 235 [](const DateTimeRange& range) {
346 236 return system_clock::from_time_t(range.m_TEnd);
347 237 })
348 238 .def("__repr__", __repr__<DateTimeRange>);
349 239 }
@@ -1,79 +1,41
1 1 #pragma once
2 2 #include "QtWrappers.h"
3 3 #include "pywrappers_common.h"
4 4
5 5 #include <Data/DataSeriesType.h>
6 6 #include <Data/DateTimeRange.h>
7 #include <Data/IDataSeries.h>
8 #include <Data/Unit.h>
9 #include <Variable/Variable.h>
10 7 #include <Variable/Variable2.h>
11 8 #include <pybind11/pybind11.h>
12 9 #include <sstream>
13 10 #include <string>
14 11
15 12 PYBIND11_MAKE_OPAQUE(std::vector<double>);
16 13
17 std::ostream& operator<<(std::ostream& os, const Unit& u)
18 {
19 os << "=========================" << std::endl
20 << "Unit:" << std::endl
21 << " Name: " << u.m_Name << std::endl
22 << " Is_TimeUnit: " << u.m_TimeUnit << std::endl;
23 return os;
24 }
25
26 std::ostream& operator<<(std::ostream& os, const IDataSeries& ds)
27 {
28 os << "=========================" << std::endl
29 << "DataSerie:" << std::endl
30 << " Number of points:" << ds.nbPoints() << std::endl
31 << " X Axis Unit:" << std::endl
32 << ds.xAxisUnit() << std::endl
33 << " Y Axis Unit:" << std::endl
34 << ds.yAxisUnit() << std::endl
35 << " Values Axis Unit:" << std::endl
36 << ds.valuesUnit() << std::endl;
37 return os;
38 }
39
40 14 std::ostream& operator<<(std::ostream& os, const DateTimeRange& range)
41 15 {
42 16 os << "=========================" << std::endl
43 17 << "SqpRange:" << std::endl
44 18 << " Start date: " << DateUtils::dateTime(range.m_TStart).toString()
45 19 << std::endl
46 20 << " Stop date: " << DateUtils::dateTime(range.m_TEnd).toString()
47 21 << std::endl;
48 22 return os;
49 23 }
50 24
51 std::ostream& operator<<(std::ostream& os, const Variable& variable)
52 {
53 os << "=========================" << std::endl
54 << "Variable:" << std::endl
55 << " Name: " << variable.name() << std::endl
56 << " range: " << std::endl
57 << variable.range() << std::endl
58 << " cache range: " << std::endl
59 << variable.cacheRange() << std::endl;
60 return os;
61 }
62
63 25 std::ostream& operator<<(std::ostream& os, Variable2& variable)
64 26 {
65 27 os << "=========================" << std::endl
66 28 << "Variable:" << std::endl
67 29 << " Name: " << variable.name() << std::endl
68 30 << " range: " << std::endl
69 31 << variable.range() << std::endl;
70 32 return os;
71 33 }
72 34
73 35 std::ostream& operator<<(std::ostream& os,
74 36 const VectorTimeSerie::raw_value_type& value)
75 37 {
76 38 os << "[" << value.x << ", " << value.y << ", " << value.z << "]"
77 39 << std::endl;
78 40 return os;
79 41 }
@@ -1,65 +1,50
1 1 add_definitions(-DCORE_TESTS_RESOURCES_DIR="${CMAKE_CURRENT_LIST_DIR}/../tests-resources")
2 2
3 3 FILE (GLOB_RECURSE TestUtilsSources
4 4 TestUtils/TestProviders.h
5 5 TestUtils/TestProviders.cpp
6 6 )
7 7
8 8 add_library(TestUtils ${TestUtilsSources})
9 9 target_link_libraries(TestUtils sciqlopcore Qt5::Test)
10 10 target_include_directories(TestUtils PUBLIC
11 11 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>/TestUtils
12 12 )
13 13
14 14 declare_test(TestStringUtils TestStringUtils Common/TestStringUtils.cpp "sciqlopcore;Qt5::Test")
15 15
16 16 declare_test(TestContainers TestContainers Common/TestContainers.cpp "sciqlopcore;Qt5::Test")
17 17 declare_test(TestSyncGroup TestSyncGroup Variable/TestSyncGroup.cpp "sciqlopcore;Qt5::Test")
18 18
19 19 declare_test(TestDateTimeRange TestDateTimeRange Data/TestDateTimeRange.cpp "sciqlopcore;Qt5::Test")
20 20
21
22 declare_test(TestDataSeriesUtils TestDataSeriesUtils Data/TestDataSeriesUtils.cpp "sciqlopcore;Qt5::Test")
23 declare_test(TestOptionalAxis TestOptionalAxis Data/TestOptionalAxis.cpp "sciqlopcore;Qt5::Test")
24 declare_test(TestSpectrogramSeries TestSpectrogramSeries
25 "Data/TestSpectrogramSeries.cpp;Data/DataSeriesBuilders.h;Data/DataSeriesBuilders.cpp;Data/DataSeriesTestsUtils.h;Data/DataSeriesTestsUtils.cpp"
26 "sciqlopcore;Qt5::Test")
27 declare_test(TestOneDimArrayData TestOneDimArrayData Data/TestOneDimArrayData.cpp "sciqlopcore;Qt5::Test")
28 declare_test(TestScalarSeries TestScalarSeries
29 "Data/TestScalarSeries.cpp;Data/DataSeriesBuilders.h;Data/DataSeriesBuilders.cpp;Data/DataSeriesTestsUtils.h;Data/DataSeriesTestsUtils.cpp"
30 "sciqlopcore;Qt5::Test")
31 declare_test(TestTwoDimArrayData TestTwoDimArrayData Data/TestTwoDimArrayData.cpp "sciqlopcore;Qt5::Test")
32 declare_test(TestVectorSeries TestVectorSeries
33 "Data/TestVectorSeries.cpp;Data/DataSeriesBuilders.h;Data/DataSeriesBuilders.cpp;Data/DataSeriesTestsUtils.h;Data/DataSeriesTestsUtils.cpp"
34 "sciqlopcore;Qt5::Test")
35
36 21 declare_test(TestDataSourceController TestDataSourceController
37 22 "DataSource/TestDataSourceController.cpp;DataSource/DataSourceItemBuilder.cpp"
38 23 "sciqlopcore;Qt5::Test")
39 24 declare_test(TestDataSourceItem TestDataSourceItem
40 25 "DataSource/TestDataSourceItem.cpp;DataSource/DataSourceItemBuilder.cpp"
41 26 "sciqlopcore;Qt5::Test")
42 27
43 28 declare_test(TestVariable TestVariable Variable/TestVariable.cpp "sciqlopcore;Qt5::Test")
44 29 declare_test(TestDownloader TestDownloader Network/TestDownloader.cpp "sciqlopcore;Qt5::Test;Qt5::Concurrent")
45 30
46 31
47 32 declare_test(TestVariableController2 TestVariableController2 Variable/TestVariableController2.cpp "sciqlopcore;TestUtils;Qt5::Test")
48 33 declare_test(TestVariableController2Async TestVariableController2Async Variable/TestVariableController2Async.cpp "sciqlopcore;TestUtils;Qt5::Test")
49 34 declare_test(TestVariableController2WithSync TestVariableController2WithSync Variable/TestVariableController2WithSync.cpp "sciqlopcore;TestUtils;Qt5::Test")
50 35
51 36 declare_test(TestCatalogueController TestCatalogueController CatalogueController/TestCatalogueController.cpp "sciqlopcore;TestUtils;Qt5::Test")
52 37
53 38 add_executable(TestVariablesEmbed TestUtils/PyTestWrapperExe.cpp)
54 39 target_link_libraries(TestVariablesEmbed PRIVATE pybind11::embed)
55 40 add_test(NAME TestTestVariablesEmbed COMMAND TestVariablesEmbed)
56 41 target_compile_definitions(TestVariablesEmbed PRIVATE -DPYTEST_SCRIPT="${CMAKE_CURRENT_LIST_DIR}/TestVariables.py")
57 42 set_tests_properties(TestTestVariablesEmbed PROPERTIES ENVIRONMENT PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}/../)
58 43
59 44 find_package(PythonInterp 3 REQUIRED)
60 45
61 46 add_test(NAME TestVariables
62 47 COMMAND ${PYTHON_EXECUTABLE}
63 48 ${CMAKE_CURRENT_LIST_DIR}/TestVariables.py
64 49 TestVariables)
65 50 set_tests_properties(TestVariables PROPERTIES ENVIRONMENT PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}/../)
@@ -1,71 +1,69
1 1 #ifndef TESTPROVIDER_H
2 2 #define TESTPROVIDER_H
3 3
4 4 #include <Data/DataProviderParameters.h>
5 #include <Data/DataSeries.h>
6 5 #include <Data/IDataProvider.h>
7 #include <Data/ScalarSeries.h>
8 6 #include <Data/ScalarTimeSerie.h>
9 7 #include <QUuid>
10 8 #include <QtGlobal>
11 9 #include <QtTest>
12 10 #include <TimeSeries.h>
13 11 #include <Variable/Variable2.h>
14 12 #include <algorithm>
15 13 #include <cmath>
16 14 #include <memory>
17 15 #include <numeric>
18 16
19 17 template<int slope> class SimpleRange : public IDataProvider
20 18 {
21 19 public:
22 20 SimpleRange() = default;
23 21
24 22 int callCounter = 0;
25 23 std::shared_ptr<IDataProvider> clone() const override
26 24 {
27 25 return std::make_shared<SimpleRange>();
28 26 }
29 27
30 28 TimeSeries::ITimeSerie*
31 29 getData(const DataProviderParameters& parameters) override
32 30 {
33 31 callCounter += 1;
34 32 std::size_t size =
35 33 static_cast<std::size_t>(floor(parameters.m_Range.m_TEnd) -
36 34 ceil(parameters.m_Range.m_TStart) + 1.);
37 35 auto serie = new ScalarTimeSerie(size);
38 36 std::generate(std::begin(*serie), std::end(*serie),
39 37 [i = ceil(parameters.m_Range.m_TStart)]() mutable {
40 38 return std::pair<double, double>{i, i++ * slope};
41 39 });
42 40 return serie;
43 41 }
44 42 };
45 43
46 44 template<class T> auto sumdiff(T begin, T end)
47 45 {
48 46 std::vector<double> diff_vect(end - begin - 1);
49 47 auto diff = [](auto next, auto item) { return next.value() - item.value(); };
50 48 std::transform(begin + 1, end, begin, diff_vect.begin(), diff);
51 49 return std::accumulate(diff_vect.cbegin(), diff_vect.cend(), 0);
52 50 }
53 51
54 52 template<int slope = 1> struct RangeType
55 53 {
56 54 static void check_properties(std::shared_ptr<Variable2> v, DateTimeRange r)
57 55 {
58 56 // TODO
59 57 }
60 58 };
61 59
62 60 template<class T>
63 61 void check_variable_state(std::shared_ptr<Variable2> v, DateTimeRange r)
64 62 {
65 63 auto range = v->data()->axis_range(0);
66 64 QVERIFY(range.first >= r.m_TStart);
67 65 QVERIFY(range.second <= r.m_TEnd);
68 66 T::check_properties(v, r);
69 67 }
70 68
71 69 #endif
@@ -1,158 +1,157
1 1 #include <Common/containers.h>
2 2 #include <Data/DataProviderParameters.h>
3 3 #include <Data/DateTimeRange.h>
4 4 #include <Data/IDataProvider.h>
5 #include <Data/ScalarSeries.h>
6 5 #include <QObject>
7 6 #include <QtTest>
8 7 #include <TestUtils/TestProviders.h>
9 8 #include <Variable/VariableController2.h>
10 9 #include <algorithm>
11 10 #include <cmath>
12 11 #include <numeric>
13 12
14 13 #define TEST_VC2_FIXTURE(slope) \
15 14 VariableController2 vc; \
16 15 auto provider = std::make_shared<SimpleRange<slope>>();
17 16
18 17 #define TEST_VC2_CREATE_DEFAULT_VAR(name) \
19 18 auto range = DateTimeRange::fromDateTime(QDate(2018, 8, 7), QTime(14, 00), \
20 19 QDate(2018, 8, 7), QTime(16, 00)); \
21 20 auto name = vc.createVariable("name", {}, provider, range); \
22 21 while(!vc.isReady(name)) \
23 22 QCoreApplication::processEvents();
24 23
25 24 Q_DECLARE_METATYPE(DateTimeRangeTransformation);
26 25
27 26 class TestVariableController2 : public QObject
28 27 {
29 28 Q_OBJECT
30 29 public:
31 30 explicit TestVariableController2(QObject* parent = nullptr) : QObject(parent)
32 31 {}
33 32 signals:
34 33
35 34 private slots:
36 35 void initTestCase() {}
37 36 void cleanupTestCase() {}
38 37
39 38 void testCreateVariable()
40 39 {
41 40 TEST_VC2_FIXTURE(2);
42 41 auto range = DateTimeRange::fromDateTime(QDate(2018, 8, 7), QTime(14, 00),
43 42 QDate(2018, 8, 7), QTime(16, 00));
44 43 bool callbackCalled = false;
45 44 connect(&vc, &VariableController2::variableAdded,
46 45 [&callbackCalled](std::shared_ptr<Variable2>) {
47 46 callbackCalled = true;
48 47 });
49 48 QVERIFY(!callbackCalled);
50 49 auto var1 = vc.createVariable("var1", {}, provider, range);
51 50 QVERIFY(SciQLop::containers::contains(vc.variables(), var1));
52 51 QVERIFY(callbackCalled);
53 52 }
54 53
55 54 void testDeleteVariable()
56 55 {
57 56 TEST_VC2_FIXTURE(1);
58 57 auto range = DateTimeRange::fromDateTime(QDate(2018, 8, 7), QTime(14, 00),
59 58 QDate(2018, 8, 7), QTime(16, 00));
60 59 bool callbackCalled = false;
61 60 connect(&vc, &VariableController2::variableDeleted,
62 61 [&callbackCalled](std::shared_ptr<Variable2>) {
63 62 callbackCalled = true;
64 63 });
65 64 auto var1 = vc.createVariable("var1", {}, provider, range);
66 65 while(!vc.isReady(var1))
67 66 QCoreApplication::processEvents();
68 67 QVERIFY(SciQLop::containers::contains(vc.variables(), var1));
69 68 QVERIFY(!callbackCalled);
70 69 vc.deleteVariable(var1);
71 70 QVERIFY(!SciQLop::containers::contains(vc.variables(), var1));
72 71 QVERIFY(callbackCalled);
73 72 }
74 73
75 74 void testGetData()
76 75 {
77 76 TEST_VC2_FIXTURE(10);
78 77 TEST_VC2_CREATE_DEFAULT_VAR(var1);
79 78 check_variable_state<RangeType<10>>(var1, range);
80 79 }
81 80
82 81 void testZoom_data()
83 82 {
84 83 QTest::addColumn<double>("zoom");
85 84 QTest::newRow("Zoom IN 10x") << .1;
86 85 QTest::newRow("Zoom OUT 10x") << 10.;
87 86 QTest::newRow("Zoom IN 1x") << 1.;
88 87 }
89 88 void testZoom()
90 89 {
91 90 TEST_VC2_FIXTURE(100);
92 91 TEST_VC2_CREATE_DEFAULT_VAR(var1);
93 92 check_variable_state<RangeType<100>>(var1, range);
94 93
95 94 QFETCH(double, zoom);
96 95 range *= zoom;
97 96 vc.changeRange(var1, range);
98 97 check_variable_state<RangeType<100>>(var1, range);
99 98 }
100 99
101 100 void testPan_data()
102 101 {
103 102 QTest::addColumn<double>("pan");
104 103 QTest::newRow("Right 1000 seconds") << 1000.;
105 104 QTest::newRow("Left 1000 seconds") << -1000.;
106 105 QTest::newRow("Right 0.1 seconds") << .1;
107 106 QTest::newRow("Left 0.1 seconds") << -.1;
108 107 }
109 108 void testPan()
110 109 {
111 110 TEST_VC2_FIXTURE(10);
112 111 TEST_VC2_CREATE_DEFAULT_VAR(var1);
113 112 check_variable_state<RangeType<10>>(var1, range);
114 113
115 114 QFETCH(double, pan);
116 115
117 116 range += Seconds<double>{pan};
118 117 vc.changeRange(var1, range);
119 118 check_variable_state<RangeType<10>>(var1, range);
120 119 }
121 120
122 121 void testCache_data()
123 122 {
124 123 QTest::addColumn<DateTimeRangeTransformation>("transformation");
125 124 QTest::addColumn<int>("expectedIncrement");
126 125 QTest::newRow("zoom in")
127 126 << DateTimeRangeTransformation{0.8, Seconds<double>(0.)} << 0;
128 127 QTest::newRow("tiny zoom out")
129 128 << DateTimeRangeTransformation{1.01, Seconds<double>(0.)} << 0;
130 129 QTest::newRow("just under cache zoom out")
131 130 << DateTimeRangeTransformation{2.0 / 1.1, Seconds<double>(0.)} << 0;
132 131 QTest::newRow("just over cache zoom out")
133 132 << DateTimeRangeTransformation{2.001 / 1.1, Seconds<double>(0.)} << 2;
134 133 QTest::newRow("tiny pan left")
135 134 << DateTimeRangeTransformation{1., Seconds<double>(-100.)} << 0;
136 135 QTest::newRow("tiny pan right")
137 136 << DateTimeRangeTransformation{1., Seconds<double>(100.)} << 0;
138 137 }
139 138 void testCache()
140 139 {
141 140 QSKIP("The cache is disabled for now");
142 141 TEST_VC2_FIXTURE(10);
143 142 TEST_VC2_CREATE_DEFAULT_VAR(var1);
144 143 check_variable_state<RangeType<10>>(var1, range);
145 144
146 145 QFETCH(DateTimeRangeTransformation, transformation);
147 146 QFETCH(int, expectedIncrement);
148 147 auto initialCount = provider->callCounter;
149 148 range = range.transform(transformation);
150 149 vc.changeRange(var1, range);
151 150 check_variable_state<RangeType<10>>(var1, range);
152 151 QCOMPARE(provider->callCounter - initialCount, expectedIncrement);
153 152 }
154 153 };
155 154
156 155 QTEST_MAIN(TestVariableController2)
157 156
158 157 #include "TestVariableController2.moc"
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
This diff has been collapsed as it changes many lines, (510 lines changed) Show them Hide them
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now