##// END OF EJS Templates
Some refactoring on PB11 wrappers...
jeandet -
r1341:f18e017310bc
parent child
Show More
@@ -0,0 +1,115
1 #include <pybind11/pybind11.h>
2 #include <pybind11/operators.h>
3 #include <pybind11/embed.h>
4 #include <pybind11/numpy.h>
5 #include <pybind11/chrono.h>
6
7 #include <string>
8 #include <sstream>
9
10 #include "pywrappers_common.h"
11 #include "CoreWrappers.h"
12
13 #include <Data/DataSeriesType.h>
14 #include <Data/ScalarSeries.h>
15 #include <Data/VectorSeries.h>
16 #include <Data/Unit.h>
17 #include <Data/IDataProvider.h>
18
19 #include <Variable/VariableController.h>
20
21 #include <Time/TimeController.h>
22
23
24
25 namespace py = pybind11;
26 using namespace std::chrono;
27
28 PYBIND11_MODULE(pysciqlopcore,m){
29
30 py::enum_<DataSeriesType>(m, "DataSeriesType")
31 .value("SCALAR", DataSeriesType::SCALAR)
32 .value("SPECTROGRAM", DataSeriesType::SPECTROGRAM)
33 .value("UNKNOWN", DataSeriesType::UNKNOWN)
34 .export_values();
35
36 py::class_<Unit>(m, "Unit")
37 .def_readwrite("name", &Unit::m_Name)
38 .def_readwrite("time_unit", &Unit::m_TimeUnit)
39 .def(py::self == py::self)
40 .def(py::self != py::self)
41 .def("__repr__",__repr__<Unit>);
42
43 py::class_<DataSeriesIteratorValue>(m,"DataSeriesIteratorValue")
44 .def_property_readonly("x", &DataSeriesIteratorValue::x)
45 .def("value", py::overload_cast<>(&DataSeriesIteratorValue::value, py::const_))
46 .def("value", py::overload_cast<int>(&DataSeriesIteratorValue::value, py::const_));
47
48 py::class_<IDataSeries, std::shared_ptr<IDataSeries>>(m, "IDataSeries")
49 .def("nbPoints", &IDataSeries::nbPoints)
50 .def_property_readonly("xAxisUnit", &IDataSeries::xAxisUnit)
51 .def_property_readonly("yAxisUnit", &IDataSeries::yAxisUnit)
52 .def_property_readonly("valuesUnit", &IDataSeries::valuesUnit)
53 .def("__getitem__", [](IDataSeries& serie, int key) {
54 return *(serie.begin()+key);
55 }, py::is_operator())
56 .def("__len__", &IDataSeries::nbPoints)
57 .def("__iter__", [](IDataSeries& serie) {
58 return py::make_iterator(serie.begin(), serie.end());
59 }, py::keep_alive<0, 1>())
60 .def("__repr__",__repr__<IDataSeries>);
61
62 py::class_<ScalarSeries, std::shared_ptr<ScalarSeries>, IDataSeries>(m, "ScalarSeries")
63 .def("nbPoints", &ScalarSeries::nbPoints);
64
65 py::class_<VectorSeries, std::shared_ptr<VectorSeries>, IDataSeries>(m, "VectorSeries")
66 .def("nbPoints", &VectorSeries::nbPoints);
67
68
69 py::class_<IDataProvider, std::shared_ptr<IDataProvider>>(m, "IDataProvider");
70
71
72 py::class_<Variable,std::shared_ptr<Variable>>(m, "Variable")
73 .def(py::init<const QString&>())
74 .def_property("name", &Variable::name, &Variable::setName)
75 .def_property("range", &Variable::range, &Variable::setRange)
76 .def_property("cacheRange", &Variable::cacheRange, &Variable::setCacheRange)
77 .def_property_readonly("nbPoints", &Variable::nbPoints)
78 .def_property_readonly("dataSeries", &Variable::dataSeries)
79 .def("__len__", [](Variable& variable) {
80 auto rng = variable.dataSeries()->xAxisRange(variable.range().m_TStart,variable.range().m_TEnd);
81 return std::distance(rng.first,rng.second);
82 })
83 .def("__iter__", [](Variable& variable) {
84 auto rng = variable.dataSeries()->xAxisRange(variable.range().m_TStart,variable.range().m_TEnd);
85 return py::make_iterator(rng.first, rng.second);
86 }, py::keep_alive<0, 1>())
87 .def("__getitem__", [](Variable& variable, int key) {
88 //insane and slow!
89 auto rng = variable.dataSeries()->xAxisRange(variable.range().m_TStart,variable.range().m_TEnd);
90 if(key<0)
91 return *(rng.second+key);
92 else
93 return *(rng.first+key);
94 })
95 .def("__repr__",__repr__<Variable>);
96
97
98 py::class_<SqpRange>(m,"SqpRange")
99 .def("fromDateTime", &SqpRange::fromDateTime, py::return_value_policy::move)
100 .def(py::init([](double start, double stop){return SqpRange{start, stop};}))
101 .def(py::init([](system_clock::time_point start, system_clock::time_point stop)
102 {
103 double start_ = 0.001 * duration_cast<milliseconds>(start.time_since_epoch()).count();
104 double stop_ = 0.001 * duration_cast<milliseconds>(stop.time_since_epoch()).count();
105 return SqpRange{start_, stop_};
106 }))
107 .def_property_readonly("start", [](const SqpRange& range){
108 return system_clock::from_time_t(range.m_TStart);
109 })
110 .def_property_readonly("stop", [](const SqpRange& range){
111 return system_clock::from_time_t(range.m_TEnd);
112 })
113 .def("__repr__", __repr__<SqpRange>);
114
115 }
@@ -0,0 +1,54
1 #pragma once
2 #include <pybind11/pybind11.h>
3 #include <pybind11/operators.h>
4
5 #include <string>
6 #include <sstream>
7 #include "pywrappers_common.h"
8 #include "QtWrappers.h"
9 #include <Data/DataSeriesType.h>
10 #include <Data/Unit.h>
11 #include <Data/IDataSeries.h>
12 #include <Variable/Variable.h>
13 #include <Data/SqpRange.h>
14
15
16 std::ostream &operator <<(std::ostream& os, const Unit& u)
17 {
18 os << "=========================" << std::endl
19 << "Unit:" << std::endl
20 << " Name: " << u.m_Name << std::endl
21 << " Is_TimeUnit: " << u.m_TimeUnit << std::endl;
22 return os;
23 }
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 << ds.xAxisUnit() << std::endl
32 << " Y Axis Unit:" << std::endl << ds.yAxisUnit()<< std::endl
33 << " Values Axis Unit:" << std::endl << ds.valuesUnit()<< std::endl;
34 return os;
35 }
36
37 std::ostream &operator <<(std::ostream& os, const SqpRange& range)
38 {
39 os << "=========================" << std::endl
40 << "SqpRange:" << std::endl
41 << " Start date: " << DateUtils::dateTime(range.m_TStart).toString() << std::endl
42 << " Stop date: " << DateUtils::dateTime(range.m_TEnd).toString() << std::endl;
43 return os;
44 }
45
46 std::ostream &operator <<(std::ostream& os, const Variable& variable)
47 {
48 os << "=========================" << std::endl
49 << "Variable:" << std::endl
50 << " Name: " << variable.name() << std::endl
51 << " range: " << std::endl << variable.range() << std::endl
52 << " cache range: " << std::endl << variable.cacheRange() << std::endl;
53 return os;
54 }
@@ -0,0 +1,33
1 #include <QString>
2 #include <QUuid>
3 #include <QDate>
4 #include <QTime>
5 #include <string>
6 #include <sstream>
7 #include "pywrappers_common.h"
8 #include <pybind11/pybind11.h>
9 #include "QtWrappers.h"
10
11 namespace py = pybind11;
12
13
14
15 PYBIND11_MODULE(sciqlopqt,m){
16 py::class_<QString>(m, "QString")
17 .def(py::init([](const std::string& value){return QString::fromStdString(value);}))
18 .def("__repr__", __repr__<QString>);
19
20 py::class_<QUuid>(m,"QUuid")
21 .def(py::init([](){return QUuid::createUuid();}))
22 .def("__repr__",__repr__<QUuid>);
23
24 py::class_<QDate>(m,"QDate")
25 .def(py::init<int,int,int>());
26
27 py::class_<QTime>(m,"QTime")
28 .def(py::init<int,int,int>());
29
30
31 py::implicitly_convertible<std::string, QString>();
32 }
33
@@ -0,0 +1,19
1 #pragma once
2 #include <QString>
3 #include <QUuid>
4 #include <QDate>
5 #include <QTime>
6 #include <string>
7 #include <sstream>
8
9 std::ostream &operator <<(std::ostream& os, const QString& qstr)
10 {
11 os << qstr.toStdString();
12 return os;
13 }
14
15 std::ostream &operator <<(std::ostream& os, const QUuid& uuid)
16 {
17 os << "QUuid:" << uuid.toString() << std::endl;
18 return os;
19 }
@@ -0,0 +1,18
1 #ifndef PYWRAPPERS_COMMON_H
2 #define PYWRAPPERS_COMMON_H
3 #include <QString>
4 #include <string>
5 #include <sstream>
6 #include <QUuid>
7 #include <pybind11/pybind11.h>
8
9
10 template <typename T>
11 std::string __repr__(const T& obj)
12 {
13 std::stringstream sstr;
14 sstr << obj;
15 return sstr.str();
16 }
17
18 #endif //PYWRAPPERS_COMMON_H
@@ -0,0 +1,284
1 import sys
2 import os
3 import copy
4
5 if not hasattr(sys, 'argv'):
6 sys.argv = ['']
7 current_script_path = os.path.dirname(os.path.realpath(__file__))
8 sys.path.append(current_script_path)
9 import amda
10 import pytestamda
11 import pysciqlopcore
12 import sciqlopqt
13
14 import datetime
15 import random
16 import string
17 import jsonpickle
18 import argparse
19
20 class Variable:
21 class Range:
22 def __init__(self, start, stop):
23 self.start = start
24 self.stop = stop
25
26 def __init__(self, name, t_start, t_stop):
27 self.name = name
28 self.range = Variable.Range(t_start, t_stop)
29
30
31 class OperationCtx:
32 def __init__(self, prev_ctx=None):
33 if prev_ctx is None:
34 self.t_start = datetime.datetime(2012, 10, 20, 8, 10, 00)
35 self.t_stop = datetime.datetime(2012, 10, 20, 12, 0, 0)
36 self.variables = dict()
37 self.sync_group = set()
38 else:
39 self.t_start = copy.deepcopy(prev_ctx.t_start)
40 self.t_stop = copy.deepcopy(prev_ctx.t_stop)
41 self.variables = copy.deepcopy(prev_ctx.variables)
42 self.sync_group = copy.deepcopy(prev_ctx.sync_group)
43
44
45 __variables__ = dict()
46
47 __variables_in_sync__ = set()
48
49 __OPS__ = {}
50 __WEIGHTS__ = {}
51
52 sync_group = sciqlopqt.QUuid()
53 pytestamda.VariableController.addSynchronizationGroup(sync_group)
54
55
56 def register(weight):
57 def register_(cls):
58 __OPS__[cls.__name__] = cls()
59 __WEIGHTS__[cls.__name__] = weight
60 return cls
61
62 return register_
63
64
65 def random_var(ctx):
66 if len(ctx.variables):
67 return random.choice(list(ctx.variables.keys()))
68 else:
69 return None
70
71
72 @register(2)
73 class CreateVar:
74 @staticmethod
75 def prepare(ctx, *args, **kwargs):
76 new_random_name = ''.join(random.choices(string.ascii_letters + string.digits, k=random.randint(1, 40)))
77 ctx.variables[new_random_name] = Variable(new_random_name, ctx.t_start, ctx.t_stop)
78 return {"var_name": new_random_name}
79
80 @staticmethod
81 def do(var_name, *args, **kwargs):
82 __variables__[var_name] = pytestamda.VariableController.createVariable(var_name,
83 pytestamda.amda_provider())
84
85
86 @register(1)
87 class DeleteVar:
88 @staticmethod
89 def prepare(ctx, *args, **kwargs):
90 var_name = random_var(ctx)
91 if var_name:
92 ctx.variables.pop(var_name)
93 ctx.sync_group.discard(var_name)
94 return {"var_name": var_name}
95
96 @staticmethod
97 def do(var_name, *args, **kwargs):
98 if var_name:
99 variable = __variables__.pop(var_name)
100 pytestamda.VariableController.deleteVariable(variable)
101
102
103 class Zoom:
104 @staticmethod
105 def _compute_zoom_ranges(factor, variable):
106 delta = variable.range.stop - variable.range.start
107 center = variable.range.start + (delta / 2)
108 new_delta = delta * factor
109 t_start = center - new_delta / 2
110 t_stop = center + new_delta / 2
111 return t_start, t_stop
112
113 @staticmethod
114 def _zoom(factor, var_name, ctx):
115 var_list = ctx.sync_group if var_name in ctx.sync_group else [var_name]
116 for var_name in var_list:
117 variable = ctx.variables[var_name]
118 t_start, t_stop = Zoom._compute_zoom_ranges(variable=variable, factor=factor)
119 ctx.variables[var_name].range.start = t_start
120 ctx.variables[var_name].range.stop = t_stop
121
122 @staticmethod
123 def prepare(ctx, min, max):
124 var_name = random_var(ctx)
125 factor = random.uniform(min, max)
126 if var_name:
127 Zoom._zoom(factor, var_name, ctx)
128 return {"var_name": var_name, "factor": factor}
129
130 @staticmethod
131 def do(var_name, factor):
132 variable = __variables__[var_name]
133 t_start, t_stop = Zoom._compute_zoom_ranges(variable = variable, factor = factor)
134 sync = True if var_name in __variables_in_sync__ else False
135 pytestamda.VariableController.update_range(variable, pytestamda.SqpRange(t_start, t_stop), sync)
136
137
138 @register(10)
139 class ZoomIn:
140 @staticmethod
141 def prepare(ctx, *args, **kwargs):
142 return Zoom.prepare(ctx, min=1, max=2)
143
144 @staticmethod
145 def do(var_name, factor, *args, **kwargs):
146 if var_name:
147 Zoom.do(var_name, factor)
148
149
150 @register(10)
151 class ZoomOut:
152 @staticmethod
153 def prepare(ctx, *args, **kwargs):
154 return Zoom.prepare(ctx, min=.1, max=1)
155
156 @staticmethod
157 def do(var_name, factor, *args, **kwargs):
158 if var_name:
159 Zoom.do(var_name, factor)
160
161
162 @register(10)
163 class Shift:
164 @staticmethod
165 def _compute_range(variable, direction, factor):
166 delta = variable.range.stop - variable.range.start
167 offset = delta * factor * direction
168 return variable.range.start + offset, variable.range.stop + offset
169
170 @staticmethod
171 def prepare(ctx, *args, **kwargs):
172 var_name = random_var(ctx)
173 direction = random.choice([1, -1])
174 factor = random.random()
175 if var_name:
176 var_list = ctx.sync_group if var_name in ctx.sync_group else [var_name]
177 for var_name in var_list:
178 variable = ctx.variables[var_name]
179 delta = variable.range.stop - variable.range.start
180 offset = delta * factor * direction
181 variable.range.start , variable.range.stop = Shift._compute_range(variable, direction, factor)
182 return {"var_name": var_name, "direction": direction, "factor": factor}
183
184 @staticmethod
185 def do(var_name, direction, factor, *args, **kwargs):
186 if var_name:
187 variable = __variables__[var_name]
188 t_start, t_stop = Shift._compute_range(variable, direction, factor)
189 sync = True if var_name in __variables_in_sync__ else False
190 pytestamda.VariableController.update_range(variable, pytestamda.SqpRange(t_start, t_stop), sync)
191
192
193 @register(3)
194 class WaitForDl:
195 @staticmethod
196 def prepare(ctx, *args, **kwargs):
197 return {}
198
199 @staticmethod
200 def do(*args, **kwargs):
201 pytestamda.VariableController.wait_for_downloads()
202
203
204 @register(2)
205 class SyncVar:
206 @staticmethod
207 def prepare(ctx, *args, **kwargs):
208 var_name = random_var(ctx)
209 if var_name:
210 ctx.sync_group.add(var_name)
211 return {"var_name": var_name}
212
213 @staticmethod
214 def do(var_name, *args, **kwargs):
215 if var_name:
216 pytestamda.VariableController.synchronizeVar(__variables__[var_name], sync_group)
217 __variables_in_sync__.add(var_name)
218
219
220 @register(2)
221 class DeSyncVar:
222 @staticmethod
223 def prepare(ctx, *args, **kwargs):
224 var_name = random_var(ctx)
225 if var_name:
226 ctx.sync_group.discard(var_name)
227 return {"var_name": var_name}
228
229 @staticmethod
230 def do(var_name, *args, **kwargs):
231 if var_name:
232 pytestamda.VariableController.deSynchronizeVar(__variables__[var_name], sync_group)
233 __variables_in_sync__.discard(var_name)
234
235
236 #parser = argparse.ArgumentParser()
237 #parser.add_argument("-r", "--reload", help="reload")
238 #cli_args = parser.parse_args()
239
240
241 def run_scenario(args,ops):
242 t_start, t_stop = datetime.datetime(2012, 10, 20, 8, 10, 00), datetime.datetime(2012, 10, 20, 12, 0, 0)
243 pytestamda.TimeController.setTime(pytestamda.SqpRange(t_start, t_stop))
244
245 for op_name,arg in zip(ops,args):
246 operation = __OPS__[op_name]
247 operation.do(**arg)
248
249
250 def build_scenario(name, steps=100):
251 context_stack = [OperationCtx()]
252 ops = [CreateVar.__name__] # start with one variable minimum
253 ops += random.choices(list(__OPS__.keys()), weights=list(__WEIGHTS__.values()), k=steps)
254 ops.append(SyncVar.__name__)
255 for op_name in ops:
256 ctx = OperationCtx(context_stack[-1])
257 operation = __OPS__[op_name]
258 args.append(operation.prepare(ctx))
259 context_stack.append(ctx)
260 os.makedirs(name)
261 js = jsonpickle.encode({"args": args, "context_stack": context_stack, "operations": ops})
262 with open(name+"/input.json", "w") as file:
263 file.write(js)
264 return ops, args, context_stack
265
266
267 def load_scenario(name):
268 with open(name+"/input.json", "r") as file:
269 js = file.read()
270 data = jsonpickle.decode(js)
271 return data["operations"], data["args"], data["context_stack"]
272
273
274 if __name__ == '__main__':
275 scenario = ''.join(random.choices(string.ascii_letters + string.digits, k=32))
276 #ops,args, context_stack = build_scenario(scenario, 300)
277 #print("Generated scenario {}".format(scenario))
278 name = "EuI9qFMLZJ4k7vf8seTww8Z4wGBpspd8"
279 ops, args, context_stack = load_scenario(name)
280 syncs = [WaitForDl.__name__]*len(ops)
281 syncs_args = [{}]*len(ops)
282 ops2 = [op for pair in zip(ops,syncs) for op in pair]
283 args2 = [arg for pair in zip(args,syncs_args) for arg in pair]
284 run_scenario(args=args2, ops=ops2)
@@ -0,0 +1,10
1 [wrap-file]
2 directory = pybind11-2.2.2
3
4 source_url = https://github.com/pybind/pybind11/archive/v2.2.2.zip
5 source_filename = pybind11-2.2.2.zip
6 source_hash = 20314968531faa4c8579da2c46c2ce13aecd68ae79b6dd8cf9b99698b2304348
7
8 patch_url = https://wrapdb.mesonbuild.com/v1/projects/pybind11/2.2.2/1/get_zip
9 patch_filename = pybind11-2.2.2-1-wrap.zip
10 patch_hash = 18a273260a59368b59ae754838d76a606ea6be6126e40c59fff5214252b1e26d
@@ -1,6 +1,84
1 1 FILE (GLOB_RECURSE core_SRCS
2 include/*.h
3 src/*.cpp
2 ./include/DataSource/DataSourceItemMergeHelper.h
3 ./include/DataSource/DataSourceItemAction.h
4 ./include/DataSource/DataSourceItem.h
5 ./include/DataSource/DataSourceController.h
6 ./include/Common/SortUtils.h
7 ./include/Common/spimpl.h
8 ./include/Common/MimeTypesDef.h
9 ./include/Common/MetaTypes.h
10 ./include/Common/StringUtils.h
11 ./include/Common/SignalWaiter.h
12 ./include/Common/DateUtils.h
13 ./include/Plugin/IPlugin.h
14 ./include/Data/ArrayDataIterator.h
15 ./include/Data/VariableRequest.h
16 ./include/Data/VectorSeries.h
17 ./include/Data/SqpRange.h
18 ./include/Data/ScalarSeries.h
19 ./include/Data/DataSeriesMergeHelper.h
20 ./include/Data/DataSeries.h
21 ./include/Data/AcquisitionDataPacket.h
22 ./include/Data/DataSeriesType.h
23 ./include/Data/AcquisitionRequest.h
24 ./include/Data/SqpIterator.h
25 ./include/Data/ArrayData.h
26 ./include/Data/DataSeriesIterator.h
27 ./include/Data/DataSeriesUtils.h
28 ./include/Data/SpectrogramSeries.h
29 ./include/Data/Unit.h
30 ./include/Data/DataProviderParameters.h
31 ./include/Data/OptionalAxis.h
32 ./include/Data/IDataProvider.h
33 ./include/Data/IDataSeries.h
34 ./include/Network/NetworkController.h
35 ./include/Version.h
36 ./include/CoreGlobal.h
37 ./include/Catalogue/CatalogueController.h
38 ./include/Visualization/VisualizationController.h
39 ./include/PluginManager/PluginManager.h
40 ./include/Variable/VariableModel.h
41 ./include/Variable/VariableAcquisitionWorker.h
42 ./include/Variable/VariableCacheStrategy.h
43 ./include/Variable/VariableSynchronizationGroup.h
44 ./include/Variable/VariableSingleThresholdCacheStrategy.h
45 ./include/Variable/VariableCacheStrategyFactory.h
46 ./include/Variable/Variable.h
47 ./include/Variable/VariableCacheController.h
48 ./include/Variable/VariableController.h
49 ./include/Time/TimeController.h
50 ./include/Settings/ISqpSettingsBindable.h
51 ./include/Settings/SqpSettingsDefs.h
52
53 ./src/DataSource/DataSourceItem.cpp
54 ./src/DataSource/DataSourceItemAction.cpp
55 ./src/DataSource/DataSourceItemMergeHelper.cpp
56 ./src/DataSource/DataSourceController.cpp
57 ./src/Common/DateUtils.cpp
58 ./src/Common/MimeTypesDef.cpp
59 ./src/Common/StringUtils.cpp
60 ./src/Common/SignalWaiter.cpp
61 ./src/Data/ScalarSeries.cpp
62 ./src/Data/DataSeriesIterator.cpp
63 ./src/Data/OptionalAxis.cpp
64 ./src/Data/ArrayDataIterator.cpp
65 ./src/Data/SpectrogramSeries.cpp
66 ./src/Data/DataSeriesUtils.cpp
67 ./src/Data/VectorSeries.cpp
68 ./src/Network/NetworkController.cpp
69 ./src/Catalogue/CatalogueController.cpp
70 ./src/Visualization/VisualizationController.cpp
71 ./src/PluginManager/PluginManager.cpp
72 ./src/Variable/VariableController.cpp
73 ./src/Variable/VariableModel.cpp
74 ./src/Variable/VariableCacheController.cpp
75 ./src/Variable/VariableSynchronizationGroup.cpp
76 ./src/Variable/Variable.cpp
77 ./src/Variable/VariableAcquisitionWorker.cpp
78 ./src/Version.cpp
79 ./src/Time/TimeController.cpp
80 ./src/Settings/SqpSettingsDefs.cpp
81
4 82 )
5 83
6 84 add_definitions(-DCORE_STATIC)
@@ -19,6 +97,23 target_link_libraries(sciqlopcore PUBLIC
19 97 catalogs
20 98 )
21 99
100
101 pybind11_add_module(sciqlopqt src/pybind11_wrappers/QtWrappers.cpp)
102 target_link_libraries(sciqlopqt PUBLIC Qt5::Core)
103
104 pybind11_add_module(pysciqlopcore src/pybind11_wrappers/CoreWrappers.cpp)
105 target_link_libraries(pysciqlopcore PUBLIC sciqlopcore)
106
107 add_library(pysciqlop src/pybind11_wrappers/pywrappers_common.h)
108 target_link_libraries(pysciqlop PUBLIC Qt5::Core)
109 target_include_directories(pysciqlop PUBLIC
110 $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/pybind11_wrappers/>
111 $<INSTALL_INTERFACE:include/SciQLOP/py_wrappers>
112 )
113
114 SET_PROPERTY(GLOBAL PROPERTY CORE_PYTHON_PATH ${CMAKE_CURRENT_BINARY_DIR})
115
116
22 117 install(TARGETS sciqlopcore EXPORT SciQLOPCoreConfig
23 118 ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
24 119 LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
@@ -41,18 +41,31 declare_test(TestAmdaFuzzing TestAmdaFuzzing "tests/TestAmdaFuzzing.cpp;tests/Fu
41 41
42 42 pybind11_add_module(pytestamda tests/PyTestAmdaWrapper.cpp)
43 43 target_link_libraries(pytestamda PUBLIC amdaplugin)
44 target_link_libraries(pytestamda PUBLIC pysciqlop)
45
44 46
45 47 #pybind11_add_module(pytestamdalib SHARED tests/PyTestAmdaWrapper.cpp)
46 48 add_library(pytestamdalib tests/PyTestAmdaWrapper.cpp)
47 49 target_link_libraries(pytestamdalib PUBLIC pybind11::module)
48 50 target_link_libraries(pytestamdalib PUBLIC pybind11::embed)
49 51 target_link_libraries(pytestamdalib PUBLIC amdaplugin)
52 target_link_libraries(pytestamdalib PUBLIC pysciqlop)
53
54 GET_PROPERTY(CORE_PYTHON_PATH GLOBAL PROPERTY CORE_PYTHON_PATH)
50 55
51 56 declare_test(TestAmdaFileParserEmbed TestAmdaFileParserEmbed "tests/PyTestAmdaWrapperExe.cpp" "amdaplugin;pytestamdalib")
52 57 target_compile_definitions(TestAmdaFileParserEmbed PRIVATE -DPYTESTAMDA_SCRIPT="${CMAKE_CURRENT_LIST_DIR}/tests/TestAmdaFileParser.py")
58 set_tests_properties(TestAmdaFileParserEmbed PROPERTIES ENVIRONMENT PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}:${CORE_PYTHON_PATH})
59
53 60
54 61 declare_test(TestAmdaDownloadEmbed TestAmdaDownloadEmbed "tests/PyTestAmdaWrapperExe.cpp" "amdaplugin;pytestamdalib")
55 62 target_compile_definitions(TestAmdaDownloadEmbed PRIVATE -DPYTESTAMDA_SCRIPT="${CMAKE_CURRENT_LIST_DIR}/tests/TestAmdaDownload.py")
63 set_tests_properties(TestAmdaDownloadEmbed PROPERTIES ENVIRONMENT PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}:${CORE_PYTHON_PATH})
64
65
66 declare_test(TestAmdaMiniFuzzEmbed TestAmdaMiniFuzzEmbed "tests/PyTestAmdaWrapperExe.cpp" "amdaplugin;pytestamdalib")
67 target_compile_definitions(TestAmdaMiniFuzzEmbed PRIVATE -DPYTESTAMDA_SCRIPT="${CMAKE_CURRENT_LIST_DIR}/tests/TestAmdaMiniFuzz.py")
68 set_tests_properties(TestAmdaMiniFuzzEmbed PROPERTIES ENVIRONMENT PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}:${CORE_PYTHON_PATH})
56 69
57 70
58 71 find_package(PythonInterp 3 REQUIRED)
@@ -61,13 +74,11 add_test(NAME TestAmdaFileParser
61 74 COMMAND ${PYTHON_EXECUTABLE}
62 75 ${CMAKE_CURRENT_LIST_DIR}/tests/TestAmdaFileParser.py
63 76 TestAmdaFileParser)
64 set_tests_properties(TestAmdaFileParser PROPERTIES ENVIRONMENT PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR})
77 set_tests_properties(TestAmdaFileParser PROPERTIES ENVIRONMENT PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}:${CORE_PYTHON_PATH})
65 78
66 79
67 80 add_test(NAME TestAmdaDownload
68 81 COMMAND ${PYTHON_EXECUTABLE}
69 82 ${CMAKE_CURRENT_LIST_DIR}/tests/TestAmdaDownload.py
70 83 TestAmdaDownload)
71 set_tests_properties(TestAmdaDownload PROPERTIES ENVIRONMENT PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR})
72
73
84 set_tests_properties(TestAmdaDownload PROPERTIES ENVIRONMENT PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}:${CORE_PYTHON_PATH})
@@ -42,66 +42,24
42 42 #include <AmdaProvider.h>
43 43 #include <AmdaResultParser.h>
44 44
45 #include <QDate>
46 #include <QTime>
47 #include <QUuid>
48 #include <QString>
45 //#include <QDate>
46 //#include <QTime>
47 //#include <QUuid>
48 //#include <QString>
49 49 #include <QFile>
50 50
51 using namespace std::chrono;
52 namespace py = pybind11;
53
54 std::ostream &operator <<(std::ostream& os, const Unit& u)
55 {
56 os << "=========================" << std::endl
57 << "Unit:" << std::endl
58 << " Name: " << u.m_Name.toStdString() << std::endl
59 << " Is_TimeUnit: " << u.m_TimeUnit << std::endl;
60 return os;
61 }
62
63 std::ostream &operator <<(std::ostream& os, const IDataSeries& ds)
64 {
65 os << "=========================" << std::endl
66 << "DataSerie:" << std::endl
67 << " Number of points:" << ds.nbPoints() << std::endl
68 << " X Axis Unit:" << std::endl << ds.xAxisUnit() << std::endl
69 << " Y Axis Unit:" << std::endl << ds.yAxisUnit()<< std::endl
70 << " Values Axis Unit:" << std::endl << ds.valuesUnit()<< std::endl;
71 return os;
72 }
73
74 std::ostream &operator <<(std::ostream& os, const SqpRange& range)
75 {
76 os << "=========================" << std::endl
77 << "SqpRange:" << std::endl
78 << " Start date: " << DateUtils::dateTime(range.m_TStart).toString().toStdString() << std::endl
79 << " Stop date: " << DateUtils::dateTime(range.m_TEnd).toString().toStdString() << std::endl;
80 return os;
81 }
51 #include <pywrappers_common.h>
52 #include <CoreWrappers.h>
82 53
83 std::ostream &operator <<(std::ostream& os, const Variable& variable)
84 {
85 os << "=========================" << std::endl
86 << "Variable:" << std::endl
87 << " Name: " << variable.name().toStdString() << std::endl
88 << " range: " << std::endl << variable.range() << std::endl
89 << " cache range: " << std::endl << variable.cacheRange() << std::endl;
90 return os;
91 }
92 54
93 template <typename T>
94 std::string __repr__(const T& obj)
95 {
96 std::stringstream sstr;
97 sstr << obj;
98 return sstr.str();
99 }
55 using namespace std::chrono;
56 namespace py = pybind11;
100 57
101 58
102 59
103 60
104 61 PYBIND11_MODULE(pytestamda, m){
62
105 63 int argc = 0;
106 64 char ** argv=nullptr;
107 65 SqpApplication::setOrganizationName("LPP");
@@ -109,52 +67,10 PYBIND11_MODULE(pytestamda, m){
109 67 SqpApplication::setApplicationName("SciQLop");
110 68 static SqpApplication app(argc, argv);
111 69
112 m.doc() = "hello";
70 auto qtmod = py::module::import("sciqlopqt");
71 auto sciqlopmod = py::module::import("pysciqlopcore");
113 72
114 auto amda_provider = std::make_shared<AmdaProvider>();
115 m.def("amda_provider",[amda_provider](){return amda_provider;}, py::return_value_policy::copy);
116
117 py::enum_<DataSeriesType>(m, "DataSeriesType")
118 .value("SCALAR", DataSeriesType::SCALAR)
119 .value("SPECTROGRAM", DataSeriesType::SPECTROGRAM)
120 .value("UNKNOWN", DataSeriesType::UNKNOWN)
121 .export_values();
122
123 py::class_<Unit>(m, "Unit")
124 .def_readwrite("name", &Unit::m_Name)
125 .def_readwrite("time_unit", &Unit::m_TimeUnit)
126 .def(py::self == py::self)
127 .def(py::self != py::self)
128 .def("__repr__",__repr__<Unit>);
129
130 py::class_<DataSeriesIteratorValue>(m,"DataSeriesIteratorValue")
131 .def_property_readonly("x", &DataSeriesIteratorValue::x)
132 .def("value", py::overload_cast<>(&DataSeriesIteratorValue::value, py::const_))
133 .def("value", py::overload_cast<int>(&DataSeriesIteratorValue::value, py::const_));
134
135 py::class_<IDataSeries, std::shared_ptr<IDataSeries>>(m, "IDataSeries")
136 .def("nbPoints", &IDataSeries::nbPoints)
137 .def_property_readonly("xAxisUnit", &IDataSeries::xAxisUnit)
138 .def_property_readonly("yAxisUnit", &IDataSeries::yAxisUnit)
139 .def_property_readonly("valuesUnit", &IDataSeries::valuesUnit)
140 .def("__getitem__", [](IDataSeries& serie, int key) {
141 return *(serie.begin()+key);
142 }, py::is_operator())
143 .def("__len__", &IDataSeries::nbPoints)
144 .def("__iter__", [](IDataSeries& serie) {
145 return py::make_iterator(serie.begin(), serie.end());
146 }, py::keep_alive<0, 1>())
147 .def("__repr__",__repr__<IDataSeries>);
148
149 py::class_<ScalarSeries, std::shared_ptr<ScalarSeries>, IDataSeries>(m, "ScalarSeries")
150 .def("nbPoints", &ScalarSeries::nbPoints);
151
152 py::class_<VectorSeries, std::shared_ptr<VectorSeries>, IDataSeries>(m, "VectorSeries")
153 .def("nbPoints", &VectorSeries::nbPoints);
154
155 py::class_<QString>(m, "QString")
156 .def(py::init([](const std::string& value){return QString::fromStdString(value);}))
157 .def("__repr__", &QString::toStdString);
73 m.doc() = "hello";
158 74
159 75 py::class_<VariableController>(m, "VariableController")
160 76 .def_static("createVariable",[](const QString &name,
@@ -163,12 +79,38 PYBIND11_MODULE(pytestamda, m){
163 79 })
164 80 .def_static("hasPendingDownloads",
165 81 [](){return sqpApp->variableController().hasPendingDownloads();}
166 );
82 )
83 .def_static("addSynchronizationGroup",
84 [](QUuid uuid){sqpApp->variableController().onAddSynchronizationGroupId(uuid);}
85 )
86 .def_static("removeSynchronizationGroup",
87 [](QUuid uuid){sqpApp->variableController().onRemoveSynchronizationGroupId(uuid);}
88 )
89 .def_static("synchronizeVar",
90 [](std::shared_ptr<Variable> variable, QUuid uuid){sqpApp->variableController().onAddSynchronized(variable, uuid);}
91 )
92 .def_static("deSynchronizeVar",
93 [](std::shared_ptr<Variable> variable, QUuid uuid){sqpApp->variableController().desynchronize(variable, uuid);}
94 )
95 .def_static("deleteVariable",
96 [](std::shared_ptr<Variable> variable){
97 sqpApp->variableController().deleteVariable(variable);}
98 )
99 .def_static("update_range",[](std::shared_ptr<Variable> variable, const SqpRange &range, bool synchronise){
100 sqpApp->variableController().onRequestDataLoading({variable}, range, synchronise);
101 })
102 .def_static("wait_for_downloads",[](){
103 while (sqpApp->variableController().hasPendingDownloads()) {
104 usleep(100);
105 }
106 });
167 107
168 108 py::class_<TimeController>(m,"TimeController")
169 109 .def_static("setTime", [](SqpRange range){sqpApp->timeController().onTimeToUpdate(range);});
170 110
171 py::class_<IDataProvider, std::shared_ptr<IDataProvider>>(m, "IDataProvider");
111
112 auto amda_provider = std::make_shared<AmdaProvider>();
113 m.def("amda_provider",[amda_provider](){return amda_provider;}, py::return_value_policy::copy);
172 114
173 115 py::class_<AmdaProvider, std::shared_ptr<AmdaProvider>, IDataProvider>(m, "AmdaProvider");
174 116
@@ -178,58 +120,6 PYBIND11_MODULE(pytestamda, m){
178 120 return std::dynamic_pointer_cast<ScalarSeries>(AmdaResultParser::readTxt(path, DataSeriesType::SCALAR));
179 121 }, py::return_value_policy::copy);
180 122
181 py::class_<Variable,std::shared_ptr<Variable>>(m, "Variable")
182 .def(py::init<const QString&>())
183 .def_property("name", &Variable::name, &Variable::setName)
184 .def_property("range", &Variable::range, &Variable::setRange)
185 .def_property("cacheRange", &Variable::cacheRange, &Variable::setCacheRange)
186 .def_property_readonly("nbPoints", &Variable::nbPoints)
187 .def_property_readonly("dataSeries", &Variable::dataSeries)
188 .def("__len__", [](Variable& variable) {
189 auto rng = variable.dataSeries()->xAxisRange(variable.range().m_TStart,variable.range().m_TEnd);
190 return std::distance(rng.first,rng.second);
191 })
192 .def("__iter__", [](Variable& variable) {
193 auto rng = variable.dataSeries()->xAxisRange(variable.range().m_TStart,variable.range().m_TEnd);
194 return py::make_iterator(rng.first, rng.second);
195 }, py::keep_alive<0, 1>())
196 .def("__getitem__", [](Variable& variable, int key) {
197 //insane and slow!
198 auto rng = variable.dataSeries()->xAxisRange(variable.range().m_TStart,variable.range().m_TEnd);
199 if(key<0)
200 return *(rng.second+key);
201 else
202 return *(rng.first+key);
203 })
204 .def("__repr__",__repr__<Variable>);
205
206 py::implicitly_convertible<std::string, QString>();
207
208
209 py::class_<SqpRange>(m,"SqpRange")
210 .def("fromDateTime", &SqpRange::fromDateTime, py::return_value_policy::move)
211 .def(py::init([](double start, double stop){return SqpRange{start, stop};}))
212 .def(py::init([](system_clock::time_point start, system_clock::time_point stop)
213 {
214 double start_ = 0.001 * duration_cast<milliseconds>(start.time_since_epoch()).count();
215 double stop_ = 0.001 * duration_cast<milliseconds>(stop.time_since_epoch()).count();
216 return SqpRange{start_, stop_};
217 }))
218 .def_property_readonly("start", [](const SqpRange& range){
219 return system_clock::from_time_t(range.m_TStart);
220 })
221 .def_property_readonly("stop", [](const SqpRange& range){
222 return system_clock::from_time_t(range.m_TEnd);
223 })
224 .def("__repr__", __repr__<SqpRange>);
225
226 py::class_<QUuid>(m,"QUuid");
227
228 py::class_<QDate>(m,"QDate")
229 .def(py::init<int,int,int>());
230
231 py::class_<QTime>(m,"QTime")
232 .def(py::init<int,int,int>());
233 123
234 124 }
235 125
@@ -242,3 +132,4 int pytestamda_test(const char* testScriptPath )
242 132 return 0;
243 133 }
244 134
135
@@ -4,8 +4,9 if not hasattr(sys, 'argv'):
4 4 sys.argv = ['']
5 5 current_script_path = os.path.dirname(os.path.realpath(__file__))
6 6 sys.path.append(current_script_path)
7 import amda
8 7 import pytestamda
8 import pysciqlopcore
9 import amda
9 10
10 11 import numpy as np
11 12 import datetime
@@ -13,23 +14,6 import time
13 14 import unittest
14 15 import ddt
15 16
16 def wait_for_downloads():
17 while pytestamda.VariableController.hasPendingDownloads():
18 time.sleep(0.1)
19
20 def extract_vector(variable):
21 return zip(*[(pt.x, pt.value(0), pt.value(1), pt.value(2)) for pt in variable])
22
23 def compare_with_ref(var, ref):
24 t_ref, x_ref, y_ref, z_ref = ref
25 t,x,y,z = extract_vector(var)
26 return all([
27 all([t_ref[i].astype(float)/1000000 == t[i] for i in range(len(t))]),
28 all([x_ref[i] == x[i] for i in range(len(x))]),
29 all([y_ref[i] == y[i] for i in range(len(y))]),
30 all([z_ref[i] == z[i] for i in range(len(z))])
31 ])
32
33 17 @ddt.ddt
34 18 class FunctionalTests(unittest.TestCase):
35 19 def setUp(self):
@@ -43,11 +27,11 class FunctionalTests(unittest.TestCase):
43 27 def test_simple_download(self, case):
44 28 tstart = case[0]
45 29 tstop = case[1]
46 pytestamda.TimeController.setTime(pytestamda.SqpRange(tstart, tstop))
30 pytestamda.TimeController.setTime(pysciqlopcore.SqpRange(tstart, tstop))
47 31 variable = pytestamda.VariableController.createVariable("bx_gse",pytestamda.amda_provider())
48 wait_for_downloads()
32 pytestamda.VariableController.wait_for_downloads()
49 33 t_ref, x_ref, y_ref, z_ref = amda.generate_data(np.datetime64(tstart), np.datetime64(tstop), 4)
50 self.assertTrue( compare_with_ref(variable,(t_ref, x_ref, y_ref, z_ref) ) )
34 self.assertTrue( amda.compare_with_ref(variable,(t_ref, x_ref, y_ref, z_ref) ) )
51 35
52 36
53 37 if __name__ == '__main__':
@@ -15,6 +15,10 def load_scalar(fname):
15 15 float(line.split()[1])]
16 16 for line in f if "#" not in line]
17 17
18 def extract_vector(variable):
19 return zip(*[(pt.x, pt.value(0), pt.value(1), pt.value(2)) for pt in variable])
20
21
18 22 """
19 23 Copied from myAMDA should be factored in somehow
20 24 """
@@ -27,3 +31,13 def generate_data(tstart, tstop, dt):
27 31 y = [(x0 + (i+1) * delta).astype('float')/1000000 for i in range(vector_size)]
28 32 z = [(x0 + (i+2) * delta).astype('float')/1000000 for i in range(vector_size)]
29 33 return t,x,y,z
34
35 def compare_with_ref(var, ref):
36 t_ref, x_ref, y_ref, z_ref = ref
37 t,x,y,z = extract_vector(var)
38 return all([
39 all([t_ref[i].astype(float)/1000000 == t[i] for i in range(len(t))]),
40 all([x_ref[i] == x[i] for i in range(len(x))]),
41 all([y_ref[i] == y[i] for i in range(len(y))]),
42 all([z_ref[i] == z[i] for i in range(len(z))])
43 ])
General Comments 0
You need to be logged in to leave comments. Login now