##// END OF EJS Templates
New TimeSeries classes mostly usable from Python...
jeandet -
r65:00b9e6e4b7f5
parent child
Show More
@@ -0,0 +1,41
1 /*------------------------------------------------------------------------------
2 -- This file is a part of the SciQLOP Software
3 -- Copyright (C) 2019, Plasma Physics Laboratory - CNRS
4 --
5 -- This program is free software; you can redistribute it and/or modify
6 -- it under the terms of the GNU General Public License as published by
7 -- the Free Software Foundation; either version 2 of the License, or
8 -- (at your option) any later version.
9 --
10 -- This program is distributed in the hope that it will be useful,
11 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 -- GNU General Public License for more details.
14 --
15 -- You should have received a copy of the GNU General Public License
16 -- along with this program; if not, write to the Free Software
17 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 -------------------------------------------------------------------------------*/
19 /*-- Author : Alexis Jeandet
20 -- Mail : alexis.jeandet@member.fsf.org
21 ----------------------------------------------------------------------------*/
22 #include <iostream>
23 #include <pybind11/embed.h>
24 #include <pybind11/pybind11.h>
25 #include <string>
26
27 namespace py = pybind11;
28
29 int main(int argc, char** argv)
30 {
31 py::scoped_interpreter guard{};
32 py::globals()["__file__"] = py::str(PYTEST_SCRIPT);
33 try
34 {
35 py::eval_file(PYTEST_SCRIPT);
36 } catch(py::error_already_set const& pythonErr)
37 {
38 std::cout << pythonErr.what();
39 }
40 return 0;
41 }
@@ -1,1 +1,1
1 Subproject commit b8442947c778c24a35d33c5f8eed8548cbf9fead
1 Subproject commit 2146d47985f44d6914b224c3b99ebf9e16e87b3f
@@ -1,1 +1,1
1 Subproject commit f7bc18f528bb35cd06c93d0a58c17e6eea3fa68c
1 Subproject commit 25abf7efba0b2990f5a6dfb0a31bc65c0f2f4d17
@@ -9,6 +9,8 class SCIQLOP_CORE_EXPORT SpectrogramTimeSerie
9 : public TimeSeries::TimeSerie<double, SpectrogramTimeSerie, 2>
9 : public TimeSeries::TimeSerie<double, SpectrogramTimeSerie, 2>
10 {
10 {
11 public:
11 public:
12 using item_t =
13 decltype(TimeSeries::TimeSerie<double, SpectrogramTimeSerie, 2>()[0]);
12 SpectrogramTimeSerie() {}
14 SpectrogramTimeSerie() {}
13 ~SpectrogramTimeSerie() = default;
15 ~SpectrogramTimeSerie() = default;
14 using TimeSerie::TimeSerie;
16 using TimeSerie::TimeSerie;
@@ -27,6 +27,65
27 namespace py = pybind11;
27 namespace py = pybind11;
28 using namespace std::chrono;
28 using namespace std::chrono;
29
29
30 template<typename T, typename U, bool row_major = true>
31 void copy_vector(py::array_t<double>& t, py::array_t<double>& values, T& dest_t,
32 U& dest_values)
33 {
34 auto t_view = t.unchecked<1>();
35 auto values_view = values.unchecked<2>();
36 if constexpr(row_major)
37 {
38 for(std::size_t i = 0; i < t.size(); i++)
39 {
40 dest_t[i] = t_view[i];
41 dest_values[i] = {values_view(i, 0), values_view(i, 1),
42 values_view(i, 2)};
43 }
44 }
45 else
46 {
47 for(std::size_t i = 0; i < t.size(); i++)
48 {
49 dest_t[i] = t_view[i];
50 dest_values[i] = {values_view(0, i), values_view(1, i),
51 values_view(2, i)};
52 }
53 }
54 }
55
56 template<typename T, typename U>
57 void copy_scalar(py::array_t<double>& t, py::array_t<double>& values, T& dest_t,
58 U& dest_values)
59 {
60 auto t_view = t.unchecked<1>();
61 auto values_view = values.unchecked<1>();
62 for(std::size_t i = 0; i < t.size(); i++)
63 {
64 dest_t[i] = t_view[i];
65 dest_values[i] = values_view[i];
66 }
67 }
68
69 template<typename T, typename U>
70 void copy_spectro(py::array_t<double>& t, py::array_t<double>& values,
71 T& dest_t, U& dest_values)
72 {
73 auto t_view = t.unchecked<1>();
74 auto values_view = values.unchecked<2>();
75 const auto width = values.shape(0);
76 std::cout << "WIDTH" << width << std::endl;
77 for(std::size_t i = 0; i < t.size(); i++)
78 {
79 dest_t[i] = t_view[i];
80 for(int j = 0; j < width; j++)
81 {
82 dest_values[i * width + j] = values_view(j, i);
83 std::cout << "dest_values[" << i * width + j << "] = values_view(" << j
84 << ", " << i << ") = " << values_view(j, i) << std::endl;
85 }
86 }
87 }
88
30 PYBIND11_MODULE(pysciqlopcore, m)
89 PYBIND11_MODULE(pysciqlopcore, m)
31 {
90 {
32 pybind11::bind_vector<std::vector<double>>(m, "VectorDouble");
91 pybind11::bind_vector<std::vector<double>>(m, "VectorDouble");
@@ -156,6 +215,8 PYBIND11_MODULE(pysciqlopcore, m)
156 py::class_<TimeSeries::ITimeSerie>(m, "ITimeSerie")
215 py::class_<TimeSeries::ITimeSerie>(m, "ITimeSerie")
157 .def_property_readonly(
216 .def_property_readonly(
158 "size", [](const TimeSeries::ITimeSerie& ts) { return ts.size(); })
217 "size", [](const TimeSeries::ITimeSerie& ts) { return ts.size(); })
218 .def("__len__",
219 [](const TimeSeries::ITimeSerie& ts) { return ts.size(); })
159 .def_property_readonly(
220 .def_property_readonly(
160 "shape", [](const TimeSeries::ITimeSerie& ts) { return ts.shape(); })
221 "shape", [](const TimeSeries::ITimeSerie& ts) { return ts.shape(); })
161 .def_property_readonly(
222 .def_property_readonly(
@@ -172,13 +233,7 PYBIND11_MODULE(pysciqlopcore, m)
172 assert(t.size() == values.size());
233 assert(t.size() == values.size());
173 ScalarTimeSerie::axis_t _t(t.size());
234 ScalarTimeSerie::axis_t _t(t.size());
174 ScalarTimeSerie::axis_t _values(t.size());
235 ScalarTimeSerie::axis_t _values(t.size());
175 auto t_vew = t.unchecked<1>();
236 copy_scalar(t, values, _t, _values);
176 auto values_vew = values.unchecked<1>();
177 for(std::size_t i = 0; i < t.size(); i++)
178 {
179 _t[i] = t_vew[i];
180 _values[i] = values_vew[i];
181 }
182 return ScalarTimeSerie(_t, _values);
237 return ScalarTimeSerie(_t, _values);
183 }))
238 }))
184 .def("__getitem__",
239 .def("__getitem__",
@@ -202,14 +257,16 PYBIND11_MODULE(pysciqlopcore, m)
202 VectorTimeSerie::axis_t _t(t.size());
257 VectorTimeSerie::axis_t _t(t.size());
203 VectorTimeSerie::container_type<VectorTimeSerie::raw_value_type>
258 VectorTimeSerie::container_type<VectorTimeSerie::raw_value_type>
204 _values(t.size());
259 _values(t.size());
205 auto t_vew = t.unchecked<1>();
260 if(values.shape()[0] == 3 && values.shape(1) != 3)
206 auto values_vew = values.unchecked<2>();
207 for(std::size_t i = 0; i < t.size(); i++)
208 {
261 {
209 _t[i] = t_vew[i];
262 copy_vector<decltype(_t), decltype(_values), false>(t, values, _t,
210 _values[i] = VectorTimeSerie::raw_value_type{
263 _values);
211 values_vew(0, i), values_vew(1, i), values_vew(2, i)};
212 }
264 }
265 else
266 {
267 copy_vector(t, values, _t, _values);
268 }
269
213 return VectorTimeSerie(_t, _values);
270 return VectorTimeSerie(_t, _values);
214 }))
271 }))
215 .def("__getitem__",
272 .def("__getitem__",
@@ -221,10 +278,28 PYBIND11_MODULE(pysciqlopcore, m)
221 *(ts.begin() + key) = value;
278 *(ts.begin() + key) = value;
222 });
279 });
223
280
281 py::class_<SpectrogramTimeSerie::item_t>(m, "SpectrogramTimeSerieItem")
282 .def("__getitem__", [](SpectrogramTimeSerie::item_t& self,
283 std::size_t key) { return self[key]; });
284
224 py::class_<SpectrogramTimeSerie, TimeSeries::ITimeSerie>(
285 py::class_<SpectrogramTimeSerie, TimeSeries::ITimeSerie>(
225 m, "SpectrogramTimeSerie")
286 m, "SpectrogramTimeSerie")
226 .def(py::init<>())
287 .def(py::init<>())
227 .def(py::init<const std::vector<std::size_t>>());
288 .def(py::init<const std::vector<std::size_t>>())
289 .def(py::init([](py::array_t<double> t, py::array_t<double> values) {
290 assert(t.size() < values.size()); // TODO check geometry
291 SpectrogramTimeSerie::axis_t _t(t.size());
292 SpectrogramTimeSerie::container_type<
293 SpectrogramTimeSerie::raw_value_type>
294 _values(values.size());
295 copy_spectro(t, values, _t, _values);
296 std::vector<std::size_t> shape;
297 shape.push_back(values.shape(1));
298 shape.push_back(values.shape(0));
299 return SpectrogramTimeSerie(_t, _values, shape);
300 }))
301 .def("__getitem__",
302 [](SpectrogramTimeSerie& ts, std::size_t key) { return ts[key]; });
228
303
229 py::class_<Variable2, std::shared_ptr<Variable2>>(m, "Variable2")
304 py::class_<Variable2, std::shared_ptr<Variable2>>(m, "Variable2")
230 .def(py::init<const QString&>())
305 .def(py::init<const QString&>())
@@ -50,6 +50,11 declare_test(TestVariableController2WithSync TestVariableController2WithSync Var
50
50
51 declare_test(TestCatalogueController TestCatalogueController CatalogueController/TestCatalogueController.cpp "sciqlopcore;TestUtils;Qt5::Test")
51 declare_test(TestCatalogueController TestCatalogueController CatalogueController/TestCatalogueController.cpp "sciqlopcore;TestUtils;Qt5::Test")
52
52
53 add_executable(TestVariablesEmbed TestUtils/PyTestWrapperExe.cpp)
54 target_link_libraries(TestVariablesEmbed PRIVATE pybind11::embed)
55 add_test(NAME TestTestVariablesEmbed COMMAND TestVariablesEmbed)
56 target_compile_definitions(TestVariablesEmbed PRIVATE -DPYTEST_SCRIPT="${CMAKE_CURRENT_LIST_DIR}/TestVariables.py")
57 set_tests_properties(TestTestVariablesEmbed PROPERTIES ENVIRONMENT PYTHONPATH=${CMAKE_CURRENT_BINARY_DIR}/../)
53
58
54 find_package(PythonInterp 3 REQUIRED)
59 find_package(PythonInterp 3 REQUIRED)
55
60
@@ -1,10 +1,15
1 import sys
1 import sys
2 import os
2 import os
3 if not hasattr(sys, 'argv') or len(sys.argv)==0:
4 sys.argv = ['']
5 current_script_path = os.path.dirname(os.path.realpath(__file__))
6 sys.path.append(current_script_path)
3
7
4 import sciqlopqt
8 import sciqlopqt
5 import pysciqlopcore
9 import pysciqlopcore
6
10
7 import numpy as np
11 import numpy as np
12 import pandas as pds
8 import datetime
13 import datetime
9 import time
14 import time
10 import unittest
15 import unittest
@@ -20,7 +25,7 class TimeSeriesCtors(unittest.TestCase):
20 @ddt.data(
25 @ddt.data(
21 (pysciqlopcore.ScalarTimeSerie,10),
26 (pysciqlopcore.ScalarTimeSerie,10),
22 (pysciqlopcore.VectorTimeSerie,10),
27 (pysciqlopcore.VectorTimeSerie,10),
23 (pysciqlopcore.SpectrogramTimeSerie,[10,10]),
28 (pysciqlopcore.SpectrogramTimeSerie,[10,10])
24 )
29 )
25 def test_construct(self, case):
30 def test_construct(self, case):
26 ts = case[0](case[1])
31 ts = case[0](case[1])
@@ -35,10 +40,50 class TimeSeriesData(unittest.TestCase):
35 self.assertEqual(ts[0],123.)
40 self.assertEqual(ts[0],123.)
36
41
37 def test_build_ScalarTimeSerie_from_np_arrays(self):
42 def test_build_ScalarTimeSerie_from_np_arrays(self):
38 ts = pysciqlopcore.ScalarTimeSerie(np.arange(10),np.zeros(10))
43 ts = pysciqlopcore.ScalarTimeSerie(np.arange(10), np.arange(10)*10)
44 for i in range(len(ts)):
45 self.assertEqual(ts[i],i*10.)
39
46
40 def test_build_VectorTimeSerie_from_np_arrays(self):
47 def test_build_VectorTimeSerie_from_np_arrays(self):
41 ts = pysciqlopcore.VectorTimeSerie(np.arange(10),np.zeros((3,10)))
48 v=np.ones((3,10))
49 for i in range(3):
50 v[:][i] = np.arange(10)*10**i
51 ts = pysciqlopcore.VectorTimeSerie(np.arange(10), v)
52 for i in range(len(ts)):
53 self.assertEqual(ts[i].x,i)
54 self.assertEqual(ts[i].y,i*10.)
55 self.assertEqual(ts[i].z,i*100.)
56
57 def test_build_VectorTimeSerie_from_np_arrays_row(self):
58 v=np.ones((10,3))
59 for i in range(3):
60 v.transpose()[:][i] = np.arange(10)*10**i
61 ts = pysciqlopcore.VectorTimeSerie(np.arange(10), v)
62 for i in range(len(ts)):
63 self.assertEqual(ts[i].x,i)
64 self.assertEqual(ts[i].y,i*10.)
65 self.assertEqual(ts[i].z,i*100.)
66
67 def test_build_VectorTimeSerie_from_np_dataframe(self):
68 df = pds.DataFrame(data=np.zeros((10,3)),index=np.arange(10))
69 for i in range(3):
70 df[i] = np.arange(10)*10**i
71 ts = pysciqlopcore.VectorTimeSerie(df.index.values, df.values)
72 for i in range(len(ts)):
73 self.assertEqual(ts[i].x,i)
74 self.assertEqual(ts[i].y,i*10.)
75 self.assertEqual(ts[i].z,i*100.)
76
77 def test_build_SpectrogramTimeSerie_from_np_arrays(self):
78 v=np.ones((4,10))
79 for i in range(4):
80 v[:][i] = np.arange(10)*10**i
81 ts = pysciqlopcore.SpectrogramTimeSerie(np.arange(10), v)
82 for i in range(len(ts)):
83 for j in range(4):
84 print(f"ts[{i}][{j}] = " + str(ts[i][j]))
85
42
86
43 if __name__ == '__main__':
87 if __name__ == '__main__':
44 unittest.main()
88 unittest.main(exit=False)
89
General Comments 0
You need to be logged in to leave comments. Login now