CoreWrappers.cpp
297 lines
| 11.2 KiB
| text/x-c
|
CppLexer
r60 | #include "CoreWrappers.h" | |||
r0 | ||||
#include "pywrappers_common.h" | ||||
r85 | #include <Common/debug.h> | |||
r0 | #include <Data/DataSeriesType.h> | |||
r60 | #include <Data/IDataProvider.h> | |||
r0 | #include <Network/Downloader.h> | |||
r60 | #include <Time/TimeController.h> | |||
r62 | #include <Variable/Variable2.h> | |||
r60 | #include <Variable/VariableController2.h> | |||
#include <pybind11/chrono.h> | ||||
#include <pybind11/embed.h> | ||||
#include <pybind11/functional.h> | ||||
#include <pybind11/numpy.h> | ||||
#include <pybind11/operators.h> | ||||
#include <pybind11/pybind11.h> | ||||
#include <pybind11/stl.h> | ||||
r62 | #include <pybind11/stl_bind.h> | |||
r60 | #include <sstream> | |||
#include <string> | ||||
r0 | ||||
namespace py = pybind11; | ||||
using namespace std::chrono; | ||||
r65 | template<typename T, typename U, bool row_major = true> | |||
void copy_vector(py::array_t<double>& t, py::array_t<double>& values, T& dest_t, | ||||
U& dest_values) | ||||
{ | ||||
auto t_view = t.unchecked<1>(); | ||||
auto values_view = values.unchecked<2>(); | ||||
r78 | for(std::size_t i = 0; i < t.size(); i++) | |||
r65 | { | |||
r78 | dest_t[i] = t_view[i]; | |||
dest_values[i] = {values_view(i, 0), values_view(i, 1), values_view(i, 2)}; | ||||
} | ||||
} | ||||
template<typename T, typename U> | ||||
void copy_scalar(py::array_t<double>& t, py::array_t<double>& values, T& dest_t, | ||||
U& dest_values) | ||||
{ | ||||
auto t_view = t.unchecked<1>(); | ||||
if(values.ndim() == 1) | ||||
{ | ||||
auto values_view = values.unchecked<1>(); | ||||
r65 | for(std::size_t i = 0; i < t.size(); i++) | |||
{ | ||||
dest_t[i] = t_view[i]; | ||||
r78 | dest_values[i] = values_view[i]; | |||
r65 | } | |||
} | ||||
r78 | else if(values.ndim() == 2 && values.shape(1) == 1) | |||
r65 | { | |||
r78 | auto values_view = values.unchecked<2>(); | |||
r65 | for(std::size_t i = 0; i < t.size(); i++) | |||
{ | ||||
dest_t[i] = t_view[i]; | ||||
r78 | dest_values[i] = values_view(i, 0); | |||
r65 | } | |||
} | ||||
} | ||||
r83 | template<typename T, typename U> | |||
void copy_multicomp(py::array_t<double>& t, py::array_t<double>& values, | ||||
T& dest_t, U& dest_values) | ||||
{ | ||||
auto t_view = t.unchecked<1>(); | ||||
auto values_view = values.unchecked<2>(); | ||||
const auto width = values.shape(1); | ||||
for(std::size_t i = 0; i < t.size(); i++) | ||||
{ | ||||
dest_t[i] = t_view[i]; | ||||
for(int j = 0; j < width; j++) | ||||
{ | ||||
dest_values[i * width + j] = values_view(i, j); | ||||
} | ||||
} | ||||
} | ||||
r65 | ||||
template<typename T, typename U> | ||||
r83 | void copy_spectro(py::array_t<double>& t, py::array_t<double>& y, | |||
py::array_t<double>& values, T& dest_t, T& dest_y, | ||||
U& dest_values) | ||||
r65 | { | |||
auto t_view = t.unchecked<1>(); | ||||
r83 | auto y_view = y.unchecked<1>(); | |||
r65 | auto values_view = values.unchecked<2>(); | |||
r78 | const auto width = values.shape(1); | |||
r83 | for(std::size_t i = 0; i < y.size(); i++) | |||
{ | ||||
dest_y[i] = y_view[i]; | ||||
} | ||||
r65 | for(std::size_t i = 0; i < t.size(); i++) | |||
{ | ||||
dest_t[i] = t_view[i]; | ||||
for(int j = 0; j < width; j++) | ||||
{ | ||||
r78 | dest_values[i * width + j] = values_view(i, j); | |||
r65 | } | |||
} | ||||
} | ||||
r60 | PYBIND11_MODULE(pysciqlopcore, m) | |||
{ | ||||
r62 | pybind11::bind_vector<std::vector<double>>(m, "VectorDouble"); | |||
r60 | py::enum_<DataSeriesType>(m, "DataSeriesType") | |||
.value("SCALAR", DataSeriesType::SCALAR) | ||||
.value("SPECTROGRAM", DataSeriesType::SPECTROGRAM) | ||||
.value("VECTOR", DataSeriesType::VECTOR) | ||||
r76 | .value("MULTICOMPONENT", DataSeriesType::MULTICOMPONENT) | |||
r62 | .value("NONE", DataSeriesType::NONE) | |||
r60 | .export_values(); | |||
py::class_<Response>(m, "Response") | ||||
.def("status_code", &Response::status_code); | ||||
py::class_<Downloader>(m, "Downloader") | ||||
.def_static("get", Downloader::get) | ||||
.def_static("getAsync", Downloader::getAsync) | ||||
.def_static("downloadFinished", Downloader::downloadFinished); | ||||
py::class_<IDataProvider, std::shared_ptr<IDataProvider>>(m, "IDataProvider"); | ||||
r68 | py::class_<TimeSeries::ITimeSerie, std::shared_ptr<TimeSeries::ITimeSerie>>( | |||
m, "ITimeSerie") | ||||
r62 | .def_property_readonly( | |||
"size", [](const TimeSeries::ITimeSerie& ts) { return ts.size(); }) | ||||
r65 | .def("__len__", | |||
[](const TimeSeries::ITimeSerie& ts) { return ts.size(); }) | ||||
r63 | .def_property_readonly( | |||
"shape", [](const TimeSeries::ITimeSerie& ts) { return ts.shape(); }) | ||||
r62 | .def_property_readonly( | |||
"t", | ||||
[](TimeSeries::ITimeSerie& ts) -> decltype(ts.axis(0))& { | ||||
return ts.axis(0); | ||||
}, | ||||
r83 | py::return_value_policy::reference) | |||
.def( | ||||
"axis", | ||||
[](TimeSeries::ITimeSerie& ts, unsigned int index) | ||||
-> decltype(ts.axis(0))& { return ts.axis(index); }, | ||||
r62 | py::return_value_policy::reference); | |||
r73 | py::class_<ScalarTimeSerie, TimeSeries::ITimeSerie, | |||
std::shared_ptr<ScalarTimeSerie>>(m, "ScalarTimeSerie") | ||||
r62 | .def(py::init<>()) | |||
.def(py::init<std::size_t>()) | ||||
r63 | .def(py::init([](py::array_t<double> t, py::array_t<double> values) { | |||
assert(t.size() == values.size()); | ||||
ScalarTimeSerie::axis_t _t(t.size()); | ||||
ScalarTimeSerie::axis_t _values(t.size()); | ||||
r65 | copy_scalar(t, values, _t, _values); | |||
r63 | return ScalarTimeSerie(_t, _values); | |||
})) | ||||
r62 | .def("__getitem__", | |||
[](ScalarTimeSerie& ts, std::size_t key) { return ts[key]; }) | ||||
.def("__setitem__", [](ScalarTimeSerie& ts, std::size_t key, | ||||
double value) { *(ts.begin() + key) = value; }); | ||||
py::class_<VectorTimeSerie::raw_value_type>(m, "vector") | ||||
.def(py::init<>()) | ||||
.def(py::init<double, double, double>()) | ||||
.def("__repr__", __repr__<VectorTimeSerie::raw_value_type>) | ||||
.def_readwrite("x", &VectorTimeSerie::raw_value_type::x) | ||||
.def_readwrite("y", &VectorTimeSerie::raw_value_type::y) | ||||
.def_readwrite("z", &VectorTimeSerie::raw_value_type::z); | ||||
r73 | py::class_<VectorTimeSerie, TimeSeries::ITimeSerie, | |||
std::shared_ptr<VectorTimeSerie>>(m, "VectorTimeSerie") | ||||
r62 | .def(py::init<>()) | |||
.def(py::init<std::size_t>()) | ||||
r64 | .def(py::init([](py::array_t<double> t, py::array_t<double> values) { | |||
assert(t.size() * 3 == values.size()); | ||||
VectorTimeSerie::axis_t _t(t.size()); | ||||
r88 | VectorTimeSerie::data_t _values(t.size()); | |||
r78 | copy_vector(t, values, _t, _values); | |||
r64 | return VectorTimeSerie(_t, _values); | |||
})) | ||||
r83 | .def( | |||
"__getitem__", | ||||
[](VectorTimeSerie& ts, std::size_t key) | ||||
-> VectorTimeSerie::raw_value_type& { return ts[key]; }, | ||||
py::return_value_policy::reference) | ||||
r62 | .def("__setitem__", [](VectorTimeSerie& ts, std::size_t key, | |||
VectorTimeSerie::raw_value_type value) { | ||||
*(ts.begin() + key) = value; | ||||
}); | ||||
r76 | py::class_<MultiComponentTimeSerie::iterator_t>(m, | |||
"MultiComponentTimeSerieItem") | ||||
r75 | .def("__getitem__", [](MultiComponentTimeSerie::iterator_t& self, | |||
std::size_t key) { return (*self)[key]; }) | ||||
.def("__setitem__", | ||||
[](MultiComponentTimeSerie::iterator_t& self, std::size_t key, | ||||
double value) { (*self)[key] = value; }); | ||||
py::class_<MultiComponentTimeSerie, TimeSeries::ITimeSerie, | ||||
std::shared_ptr<MultiComponentTimeSerie>>( | ||||
m, "MultiComponentTimeSerie") | ||||
.def(py::init<>()) | ||||
.def(py::init<const std::vector<std::size_t>>()) | ||||
.def(py::init([](py::array_t<double> t, py::array_t<double> values) { | ||||
r76 | assert((t.size() < values.size()) | | |||
(t.size() == 0)); // TODO check geometry | ||||
r75 | MultiComponentTimeSerie::axis_t _t(t.size()); | |||
r88 | MultiComponentTimeSerie::data_t _values(values.size()); | |||
r83 | copy_multicomp(t, values, _t, _values); | |||
r75 | std::vector<std::size_t> shape; | |||
shape.push_back(values.shape(0)); | ||||
r78 | shape.push_back(values.shape(1)); | |||
r75 | return MultiComponentTimeSerie(_t, _values, shape); | |||
})) | ||||
.def("__getitem__", | ||||
[](MultiComponentTimeSerie& ts, | ||||
std::size_t key) -> MultiComponentTimeSerie::iterator_t { | ||||
return ts.begin() + key; | ||||
}); | ||||
r66 | py::class_<SpectrogramTimeSerie::iterator_t>(m, "SpectrogramTimeSerieItem") | |||
.def("__getitem__", [](SpectrogramTimeSerie::iterator_t& self, | ||||
std::size_t key) { return (*self)[key]; }) | ||||
.def("__setitem__", | ||||
[](SpectrogramTimeSerie::iterator_t& self, std::size_t key, | ||||
double value) { (*self)[key] = value; }); | ||||
r65 | ||||
r73 | py::class_<SpectrogramTimeSerie, TimeSeries::ITimeSerie, | |||
std::shared_ptr<SpectrogramTimeSerie>>(m, "SpectrogramTimeSerie") | ||||
r63 | .def(py::init<>()) | |||
r65 | .def(py::init<const std::vector<std::size_t>>()) | |||
r83 | .def(py::init([](py::array_t<double> t, py::array_t<double> y, | |||
r85 | py::array_t<double> values, double min_sampling, | |||
r87 | double max_sampling, bool y_is_log) { | |||
r85 | if(t.size() >= values.size() and t.size() != 0) | |||
SCIQLOP_ERROR(decltype(py::self), "Doesn't look like a Spectrogram"); | ||||
if(y.size() != values.shape(1)) | ||||
SCIQLOP_ERROR(decltype(py::self), | ||||
"Y axis size and data shape are incompatible"); | ||||
r65 | SpectrogramTimeSerie::axis_t _t(t.size()); | |||
r83 | SpectrogramTimeSerie::axis_t _y(y.size()); | |||
r88 | SpectrogramTimeSerie::data_t _values(values.size()); | |||
r83 | copy_spectro(t, y, values, _t, _y, _values); | |||
r65 | std::vector<std::size_t> shape; | |||
shape.push_back(values.shape(0)); | ||||
r78 | shape.push_back(values.shape(1)); | |||
r84 | return SpectrogramTimeSerie(std::move(_t), std::move(_y), | |||
r85 | std::move(_values), shape, min_sampling, | |||
r87 | max_sampling, y_is_log); | |||
r65 | })) | |||
.def("__getitem__", | ||||
r66 | [](SpectrogramTimeSerie& ts, | |||
std::size_t key) -> SpectrogramTimeSerie::iterator_t { | ||||
return ts.begin() + key; | ||||
}); | ||||
r63 | ||||
r62 | py::class_<Variable2, std::shared_ptr<Variable2>>(m, "Variable2") | |||
.def(py::init<const QString&>()) | ||||
.def_property("name", &Variable2::name, &Variable2::setName) | ||||
.def_property_readonly("range", &Variable2::range) | ||||
.def_property_readonly("nbPoints", &Variable2::nbPoints) | ||||
r68 | .def_property_readonly( | |||
"data", | ||||
[](Variable2& var) -> std::shared_ptr<TimeSeries::ITimeSerie> { | ||||
return var.data(); | ||||
}) | ||||
r63 | .def("set_data", | |||
[](Variable2& var, std::vector<TimeSeries::ITimeSerie*> ts_list, | ||||
const DateTimeRange& range) { var.setData(ts_list, range); }) | ||||
r62 | .def("__len__", &Variable2::nbPoints) | |||
.def("__repr__", __repr__<Variable2>); | ||||
r60 | py::class_<DateTimeRange>(m, "SqpRange") | |||
//.def("fromDateTime", &DateTimeRange::fromDateTime, | ||||
r62 | // py::return_value_policy::move) | |||
r60 | .def(py::init([](double start, double stop) { | |||
return DateTimeRange{start, stop}; | ||||
})) | ||||
.def(py::init( | ||||
[](system_clock::time_point start, system_clock::time_point stop) { | ||||
double start_ = | ||||
0.001 * | ||||
duration_cast<milliseconds>(start.time_since_epoch()).count(); | ||||
double stop_ = | ||||
0.001 * | ||||
duration_cast<milliseconds>(stop.time_since_epoch()).count(); | ||||
return DateTimeRange{start_, stop_}; | ||||
})) | ||||
.def_property_readonly("start", | ||||
[](const DateTimeRange& range) { | ||||
return system_clock::from_time_t(range.m_TStart); | ||||
}) | ||||
.def_property_readonly("stop", | ||||
[](const DateTimeRange& range) { | ||||
return system_clock::from_time_t(range.m_TEnd); | ||||
}) | ||||
.def("__repr__", __repr__<DateTimeRange>); | ||||
r0 | } | |||