@@ -0,0 +1,19 | |||
|
1 | #include <Data/DateTimeRange.h> | |
|
2 | #include <TimeSeries.h> | |
|
3 | #include <functional> | |
|
4 | #include <iostream> | |
|
5 | #include <memory> | |
|
6 | ||
|
7 | ||
|
8 | class PythonInterpreter | |
|
9 | { | |
|
10 | public: | |
|
11 | PythonInterpreter(); | |
|
12 | void add_register_callback(std::function<void(const std::vector<std::string>&, | |
|
13 | std::function<std::shared_ptr<TimeSeries::ITimeSerie>(std::string&, double, double)>)> | |
|
14 | callback); | |
|
15 | ~PythonInterpreter(); | |
|
16 | void eval(const std::string& file); | |
|
17 | ||
|
18 | private: | |
|
19 | }; |
@@ -0,0 +1,47 | |||
|
1 | #include "python_interpreter.h" | |
|
2 | #include <Data/DateTimeRange.h> | |
|
3 | #include <TimeSeries.h> | |
|
4 | #include <functional> | |
|
5 | #include <iostream> | |
|
6 | #include <pybind11/embed.h> | |
|
7 | #include <pybind11/functional.h> | |
|
8 | #include <pybind11/stl.h> | |
|
9 | ||
|
10 | namespace py = pybind11; | |
|
11 | ||
|
12 | ||
|
13 | PYBIND11_EMBEDDED_MODULE(PythonProviders, m) {} | |
|
14 | static pybind11::gil_scoped_release* _rel = nullptr; | |
|
15 | ||
|
16 | PythonInterpreter::PythonInterpreter() | |
|
17 | { | |
|
18 | py::initialize_interpreter(false); | |
|
19 | } | |
|
20 | ||
|
21 | void PythonInterpreter::add_register_callback(std::function<void(const std::vector<std::string>&, | |
|
22 | std::function<std::shared_ptr<TimeSeries::ITimeSerie>(std::string&, double, double)>)> | |
|
23 | callback) | |
|
24 | { | |
|
25 | py::module PythonProviders = py::module::import("PythonProviders"); | |
|
26 | PythonProviders.attr("register_product") = callback; | |
|
27 | } | |
|
28 | ||
|
29 | PythonInterpreter::~PythonInterpreter() | |
|
30 | { | |
|
31 | if (_rel) | |
|
32 | delete _rel; | |
|
33 | py::finalize_interpreter(); | |
|
34 | } | |
|
35 | ||
|
36 | void PythonInterpreter::eval(const std::string& file) | |
|
37 | { | |
|
38 | try | |
|
39 | { | |
|
40 | py::eval_file(file); | |
|
41 | } | |
|
42 | catch (py::error_already_set const& pythonErr) | |
|
43 | { | |
|
44 | std::cout << pythonErr.what(); | |
|
45 | } | |
|
46 | _rel = new py::gil_scoped_release(); | |
|
47 | } |
@@ -1,1 +1,1 | |||
|
1 | Subproject commit a0c89a70c83c407d12cf22096a0e7ffae4763e00 | |
|
1 | Subproject commit 68c01155acd227b01fa3c9f7926215e8cedd70df |
@@ -1,26 +1,42 | |||
|
1 | 1 | include_directories(include) |
|
2 | FILE (GLOB_RECURSE python_providers | |
|
3 |
include/ |
|
|
4 |
src/ |
|
|
5 |
resources/ |
|
|
2 | FILE (GLOB_RECURSE python_provider_srcs | |
|
3 | include/python_providers.h | |
|
4 | src/python_providers.cpp | |
|
5 | resources/python_providers.qrc | |
|
6 | 6 | ) |
|
7 | 7 | |
|
8 | FILE (GLOB_RECURSE python_interpreter_srcs | |
|
9 | include/python_interpreter.h | |
|
10 | src/python_interpreter.cpp | |
|
11 | ) | |
|
12 | ||
|
13 | add_library(python_interpreter ${python_interpreter_srcs}) | |
|
14 | target_link_libraries(python_interpreter PRIVATE pybind11::embed) | |
|
15 | target_link_libraries(python_interpreter PUBLIC sciqlopcore) | |
|
16 | target_compile_definitions(python_interpreter PRIVATE QT_NO_KEYWORDS) | |
|
17 | SET_TARGET_PROPERTIES(python_interpreter PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE) | |
|
18 | ||
|
8 | 19 | add_definitions(-DQT_PLUGIN) |
|
9 | 20 | add_definitions(-DSCIQLOP_PLUGIN_JSON_FILE_PATH="${CMAKE_CURRENT_SOURCE_DIR}/resources/python_providers.json") |
|
10 | 21 | if(NOT BUILD_SHARED_LIBS) |
|
11 | 22 | add_definitions(-DQT_STATICPLUGIN) |
|
12 | 23 | endif() |
|
13 | 24 | |
|
14 | add_library(python_providers ${python_providers}) | |
|
25 | add_library(python_providers ${python_provider_srcs}) | |
|
15 | 26 | SET_TARGET_PROPERTIES(python_providers PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE) |
|
16 | 27 | |
|
17 | 28 | target_link_libraries(python_providers PUBLIC sciqlopgui) |
|
18 |
target_link_libraries(python_providers PRIVATE py |
|
|
19 | ADD_DEFINITIONS(-DQT_NO_KEYWORDS) | |
|
29 | target_link_libraries(python_providers PRIVATE python_interpreter) | |
|
30 | ||
|
20 | 31 | install(TARGETS python_providers |
|
21 | 32 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/SciQlop |
|
22 | 33 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/SciQlop |
|
23 | 34 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) |
|
24 | 35 | |
|
36 | install(TARGETS python_interpreter | |
|
37 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/SciQlop | |
|
38 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/SciQlop | |
|
39 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) | |
|
40 | ||
|
25 | 41 | include(sciqlop_tests) |
|
26 | 42 |
@@ -2,9 +2,10 | |||
|
2 | 2 | #define PYTHON_PROVIDERS_H |
|
3 | 3 | |
|
4 | 4 | #include <Plugin/IPlugin.h> |
|
5 | ||
|
5 | #include <QUuid> | |
|
6 | 6 | |
|
7 | 7 | #include <memory> |
|
8 | #include <python_interpreter.h> | |
|
8 | 9 | |
|
9 | 10 | #ifndef SCIQLOP_PLUGIN_JSON_FILE_PATH |
|
10 | 11 | #define SCIQLOP_PLUGIN_JSON_FILE_PATH "python_providers.json" |
@@ -21,6 +22,12 public: | |||
|
21 | 22 | /// @sa IPlugin::initialize() |
|
22 | 23 | void initialize() override; |
|
23 | 24 | ~PythonProviders(); |
|
25 | ||
|
26 | private: | |
|
27 | void register_product(const std::vector<std::string>& path_list, | |
|
28 | std::function<std::shared_ptr<TimeSeries::ITimeSerie>(std::string& name, double, double)> | |
|
29 | f); | |
|
30 | PythonInterpreter _interpreter; | |
|
24 | 31 | }; |
|
25 | 32 | |
|
26 | 33 | #endif // PYTHON_PROVIDERS_H |
@@ -1,17 +1,158 | |||
|
1 | 1 | #include "python_providers.h" |
|
2 | #include <pybind11/embed.h> | |
|
3 | namespace py = pybind11; | |
|
2 | #include <Data/DataProviderParameters.h> | |
|
3 | #include <Data/DateTimeRange.h> | |
|
4 | #include <Data/IDataProvider.h> | |
|
5 | #include <Data/ScalarTimeSerie.h> | |
|
6 | #include <Data/SpectrogramTimeSerie.h> | |
|
7 | #include <Data/VectorTimeSerie.h> | |
|
8 | #include <DataSource/DataSourceController.h> | |
|
9 | #include <DataSource/DataSourceItem.h> | |
|
10 | #include <DataSource/DataSourceItemAction.h> | |
|
11 | #include <QDir> | |
|
12 | #include <QStandardPaths> | |
|
13 | #include <QStringList> | |
|
14 | #include <SqpApplication.h> | |
|
15 | #include <TimeSeries.h> | |
|
16 | #include <functional> | |
|
17 | #include <iostream> | |
|
18 | ||
|
19 | ||
|
20 | const auto DATA_SOURCE_NAME = QStringLiteral("PythonProviders"); | |
|
21 | ||
|
22 | struct noop_deleter | |
|
23 | { | |
|
24 | void operator()(TimeSeries::ITimeSerie*) {} | |
|
25 | }; | |
|
26 | ||
|
27 | class PythonProvider : public IDataProvider | |
|
28 | { | |
|
29 | public: | |
|
30 | PythonProvider( | |
|
31 | std::function<std::shared_ptr<TimeSeries::ITimeSerie>(std::string&, double, double)> f) | |
|
32 | : _pythonFunction { f } | |
|
33 | { | |
|
34 | } | |
|
35 | ||
|
36 | PythonProvider(const PythonProvider& other) : _pythonFunction { other._pythonFunction } {} | |
|
37 | ||
|
38 | std::shared_ptr<IDataProvider> clone() const override | |
|
39 | { | |
|
40 | return std::make_shared<PythonProvider>(*this); | |
|
41 | } | |
|
42 | virtual TimeSeries::ITimeSerie* getData(const DataProviderParameters& parameters) override | |
|
43 | { | |
|
44 | auto product = parameters.m_Data.value("PRODUCT", "").toString().toStdString(); | |
|
45 | auto range = parameters.m_Range; | |
|
46 | auto result = _pythonFunction(product, range.m_TStart, range.m_TEnd); | |
|
47 | if (auto ts = std::dynamic_pointer_cast<VectorTimeSerie>(result)) | |
|
48 | { | |
|
49 | return new VectorTimeSerie(*ts); | |
|
50 | } | |
|
51 | if (auto ts = std::dynamic_pointer_cast<ScalarTimeSerie>(result)) | |
|
52 | { | |
|
53 | return new ScalarTimeSerie(*ts); | |
|
54 | } | |
|
55 | if (auto ts = std::dynamic_pointer_cast<SpectrogramTimeSerie>(result)) | |
|
56 | { | |
|
57 | return new SpectrogramTimeSerie(*ts); | |
|
58 | } | |
|
59 | return nullptr; | |
|
60 | } | |
|
61 | ||
|
62 | private: | |
|
63 | std::function<std::shared_ptr<TimeSeries::ITimeSerie>(std::string&, double, double)> | |
|
64 | _pythonFunction; | |
|
65 | }; | |
|
66 | ||
|
4 | 67 | |
|
5 | 68 | void PythonProviders::initialize() |
|
6 | 69 | { |
|
7 | py::initialize_interpreter(false); | |
|
8 | py::print("Hello, World!"); | |
|
9 | py::print("Hello, World!"); | |
|
10 | py::print("Hello, World!"); | |
|
11 | py::print("Hello, World!"); | |
|
70 | _interpreter.add_register_callback( | |
|
71 | [this](const std::vector<std::string>& path_list, | |
|
72 | std::function<std::shared_ptr<TimeSeries::ITimeSerie>(std::string&, double, double)> | |
|
73 | f) { this->register_product(path_list, f); }); | |
|
74 | ||
|
75 | for (const auto& path : QStandardPaths::standardLocations(QStandardPaths::AppLocalDataLocation)) | |
|
76 | { | |
|
77 | auto dir = QDir(path + "/python"); | |
|
78 | if (dir.exists()) | |
|
79 | { | |
|
80 | for (const auto& entry : | |
|
81 | dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot, QDir::Name)) | |
|
82 | { | |
|
83 | if (entry.isFile() && entry.suffix() == "py") | |
|
84 | { | |
|
85 | _interpreter.eval(entry.absoluteFilePath().toStdString()); | |
|
86 | } | |
|
87 | } | |
|
88 | } | |
|
89 | } | |
|
90 | } | |
|
91 | ||
|
92 | PythonProviders::~PythonProviders() {} | |
|
93 | ||
|
94 | std::unique_ptr<DataSourceItem> make_folder_item(const QString& name) | |
|
95 | { | |
|
96 | return std::make_unique<DataSourceItem>(DataSourceItemType::NODE, name); | |
|
97 | } | |
|
98 | ||
|
99 | template <typename T> | |
|
100 | DataSourceItem* make_path_items( | |
|
101 | const T& path_list_begin, const T& path_list_end, DataSourceItem* root) | |
|
102 | { | |
|
103 | std::for_each(path_list_begin, path_list_end, [&root](const auto& folder_name) mutable { | |
|
104 | auto folder_ptr = root->findItem(folder_name); | |
|
105 | if (folder_ptr == nullptr) | |
|
106 | { | |
|
107 | auto folder = make_folder_item(folder_name); | |
|
108 | folder_ptr = folder.get(); | |
|
109 | root->appendChild(std::move(folder)); | |
|
110 | } | |
|
111 | root = folder_ptr; | |
|
112 | }); | |
|
113 | return root; | |
|
114 | } | |
|
115 | ||
|
116 | std::unique_ptr<DataSourceItem> make_product_item( | |
|
117 | const QVariantHash& metaData, const QUuid& dataSourceUid) | |
|
118 | { | |
|
119 | auto result = std::make_unique<DataSourceItem>(DataSourceItemType::PRODUCT, metaData); | |
|
120 | ||
|
121 | // Adds plugin name to product metadata | |
|
122 | result->setData(DataSourceItem::PLUGIN_DATA_KEY, DATA_SOURCE_NAME); | |
|
123 | result->setData(DataSourceItem::ID_DATA_KEY, metaData.value(DataSourceItem::NAME_DATA_KEY)); | |
|
124 | ||
|
125 | auto productName = metaData.value(DataSourceItem::NAME_DATA_KEY).toString(); | |
|
126 | ||
|
127 | // Add action to load product from DataSourceController | |
|
128 | result->addAction( | |
|
129 | std::make_unique<DataSourceItemAction>(QObject::tr("Load %1 product").arg(productName), | |
|
130 | [productName, dataSourceUid](DataSourceItem& item) { | |
|
131 | if (auto app = sqpApp) | |
|
132 | { | |
|
133 | app->dataSourceController().loadProductItem(dataSourceUid, item); | |
|
134 | } | |
|
135 | })); | |
|
136 | ||
|
137 | return result; | |
|
12 | 138 | } |
|
13 | 139 | |
|
14 | PythonProviders::~PythonProviders() | |
|
140 | void PythonProviders::register_product(const std::vector<std::string>& path_list, | |
|
141 | std::function<std::shared_ptr<TimeSeries::ITimeSerie>(std::string&, double, double)> f) | |
|
15 | 142 | { |
|
16 | py::finalize_interpreter(); | |
|
143 | auto& dataSourceController = sqpApp->dataSourceController(); | |
|
144 | auto id = dataSourceController.registerDataSource(DATA_SOURCE_NAME); | |
|
145 | auto root = make_folder_item(DATA_SOURCE_NAME); | |
|
146 | std::for_each( | |
|
147 | std::cbegin(path_list), std::cend(path_list), [id, f, root = root.get()](const auto& path) { | |
|
148 | auto path_list = QString::fromStdString(path).split('/'); | |
|
149 | auto name = *(std::cend(path_list) - 1); | |
|
150 | auto path_item | |
|
151 | = make_path_items(std::cbegin(path_list), std::cend(path_list) - 1, root); | |
|
152 | path_item->appendChild( | |
|
153 | make_product_item({ { DataSourceItem::NAME_DATA_KEY, name } }, id)); | |
|
154 | }); | |
|
155 | dataSourceController.setDataSourceItem(id, std::move(root)); | |
|
156 | dataSourceController.setDataProvider(id, std::make_unique<PythonProvider>(f)); | |
|
157 | std::cout << "Gone there" << std::endl; | |
|
17 | 158 | } |
General Comments 0
You need to be logged in to leave comments.
Login now