##// END OF EJS Templates
Added ultra preliminary version of python providers...
jeandet -
r1428:1ec2a74a0739
parent child
Show More
@@ -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/*.h
4 src/*.cpp
5 resources/*.qrc
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 pybind11::embed)
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
@@ -1,26 +1,33
1 1 #ifndef PYTHON_PROVIDERS_H
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"
11 12 #endif
12 13
13 14 class DataSourceItem;
14 15
15 16 class PythonProviders : public QObject, public IPlugin
16 17 {
17 18 Q_OBJECT
18 19 Q_INTERFACES(IPlugin)
19 20 Q_PLUGIN_METADATA(IID "sciqlop.plugin.IPlugin" FILE SCIQLOP_PLUGIN_JSON_FILE_PATH)
20 21 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