##// END OF EJS Templates
Ported MockPlugin to new Variable2 impl and added dummy python plugin...
jeandet -
r1423:31110df2feb2
parent child
Show More
@@ -0,0 +1,26
1 include_directories(include)
2 FILE (GLOB_RECURSE python_providers
3 include/*.h
4 src/*.cpp
5 resources/*.qrc
6 )
7
8 add_definitions(-DQT_PLUGIN)
9 add_definitions(-DSCIQLOP_PLUGIN_JSON_FILE_PATH="${CMAKE_CURRENT_SOURCE_DIR}/resources/python_providers.json")
10 if(NOT BUILD_SHARED_LIBS)
11 add_definitions(-DQT_STATICPLUGIN)
12 endif()
13
14 add_library(python_providers ${python_providers})
15 SET_TARGET_PROPERTIES(python_providers PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
16
17 target_link_libraries(python_providers PUBLIC sciqlopgui)
18 target_link_libraries(python_providers PRIVATE pybind11::embed)
19 ADD_DEFINITIONS(-DQT_NO_KEYWORDS)
20 install(TARGETS python_providers
21 ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/SciQlop
22 LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/SciQlop
23 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
24
25 include(sciqlop_tests)
26
@@ -0,0 +1,25
1 #ifndef PYTHON_PROVIDERS_H
2 #define PYTHON_PROVIDERS_H
3
4 #include <Plugin/IPlugin.h>
5
6
7 #include <memory>
8
9 #ifndef SCIQLOP_PLUGIN_JSON_FILE_PATH
10 #define SCIQLOP_PLUGIN_JSON_FILE_PATH "python_providers.json"
11 #endif
12
13 class DataSourceItem;
14
15 class PythonProviders : public QObject, public IPlugin
16 {
17 Q_OBJECT
18 Q_INTERFACES(IPlugin)
19 Q_PLUGIN_METADATA(IID "sciqlop.plugin.IPlugin" FILE SCIQLOP_PLUGIN_JSON_FILE_PATH)
20 public:
21 /// @sa IPlugin::initialize()
22 void initialize() override;
23 };
24
25 #endif // PYTHON_PROVIDERS_H
@@ -0,0 +1,3
1 {
2 "name" : "python_providers"
3 }
@@ -0,0 +1,9
1 #include "python_providers.h"
2 #include <pybind11/embed.h>
3 namespace py = pybind11;
4
5 void PythonProviders::initialize()
6 {
7 py::scoped_interpreter guard {};
8 py::print("Hello, World!");
9 }
@@ -1,41 +1,42
1 1 include_directories(include)
2 2
3 3 FILE (GLOB_RECURSE app_SRCS
4 4 include/*.h
5 5 src/*.cpp
6 6 resources/*.qrc
7 7 )
8 8
9 9 QT5_WRAP_UI(UiGenerated_SRCS
10 10 ui/MainWindow.ui
11 11 )
12 12
13 13 add_executable(sciqlopapp WIN32 ${app_SRCS} ${UiGenerated_SRCS})
14 14 if(NOT BUILD_SHARED_LIBS)
15 15 add_definitions(-DQT_STATICPLUGIN)
16 16 if(BUILD_PLUGINS)
17 17 target_link_libraries(sciqlopapp mockplugin)
18 target_link_libraries(sciqlopapp amdaplugin)
18 #target_link_libraries(sciqlopapp amdaplugin)
19 target_link_libraries(sciqlopapp python_providers)
19 20 endif()
20 21 endif()
21 22
22 23 if(NOT BUILD_PLUGINS)
23 24 add_definitions(-DSQP_NO_PLUGINS)
24 25 endif()
25 26
26 27 target_link_libraries(sciqlopapp
27 28 Qt5::Core
28 29 Qt5::Widgets
29 30 Qt5::Network
30 31 Qt5::PrintSupport
31 32 Qt5::Svg
32 33 sciqlopgui
33 34 sciqlopcore
34 35 )
35 36
36 37 install(TARGETS sciqlopapp DESTINATION ${CMAKE_INSTALL_BINDIR})
37 38 install(FILES resources/SciQLOP.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications/)
38 39 install(FILES resources/SciQLOP.appdata.xml DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/metainfo/)
39 40 install(FILES resources/sciqlopLOGO.svg DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/SciQLOP/icons/)
40 41
41 42
@@ -1,99 +1,100
1 1 /*------------------------------------------------------------------------------
2 2 -- This file is a part of the QLop Software
3 3 -- Copyright (C) 2015, Plasma Physics Laboratory - CNRS
4 4 --
5 5 -- This program is free software; you can redistribute it and/or modify
6 6 -- it under the terms of the GNU General Public License as published by
7 7 -- the Free Software Foundation; either version 2 of the License, or
8 8 -- (at your option) any later version.
9 9 --
10 10 -- This program is distributed in the hope that it will be useful,
11 11 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 13 -- GNU General Public License for more details.
14 14 --
15 15 -- You should have received a copy of the GNU General Public License
16 16 -- along with this program; if not, write to the Free Software
17 17 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 18 -------------------------------------------------------------------------------*/
19 19 /*-- Author : Alexis Jeandet
20 20 -- Mail : alexis.jeandet@member.fsf.org
21 21 ----------------------------------------------------------------------------*/
22 22 #include "MainWindow.h"
23 23 #include <QProcessEnvironment>
24 24 #include <QThread>
25 25 #include <SqpApplication.h>
26 26 #include <qglobal.h>
27 27
28 28 #include <PluginManager/PluginManager.h>
29 29 #include <QDir>
30 30 #include <QtPlugin>
31 31
32 32 #include <QLoggingCategory>
33 33
34 34 Q_LOGGING_CATEGORY(LOG_Main, "Main")
35 35
36 36 namespace
37 37 {
38 38
39 39 const auto PLUGIN_DIRECTORY_NAME = QStringLiteral("plugins");
40 40
41 41
42 42 } // namespace
43 43
44 44 int main(int argc, char* argv[])
45 45 {
46 46 #ifdef QT_STATICPLUGIN
47 47 #ifndef SQP_NO_PLUGINS
48 48 Q_IMPORT_PLUGIN(MockPlugin)
49 Q_IMPORT_PLUGIN(AmdaPlugin)
50 Q_INIT_RESOURCE(amdaresources);
49 Q_IMPORT_PLUGIN(PythonProviders)
50 // Q_IMPORT_PLUGIN(AmdaPlugin)
51 // Q_INIT_RESOURCE(amdaresources);
51 52 #endif
52 53 #endif
53 54 Q_INIT_RESOURCE(sqpguiresources);
54 55
55 56 SqpApplication::setOrganizationName("LPP");
56 57 SqpApplication::setOrganizationDomain("lpp.fr");
57 58 SqpApplication::setApplicationName("SciQLop");
58 59
59 60 QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
60 61
61 62 SqpApplication a { argc, argv };
62 63
63 64 MainWindow w;
64 65 w.show();
65 66
66 67 // Loads plugins
67 68 auto pluginDir = QDir { a.applicationDirPath() };
68 69 auto pluginLookupPath = {
69 70 #if _WIN32 || _WIN64
70 71 a.applicationDirPath() + "/SciQLop"
71 72 #else
72 73 a.applicationDirPath() + "/../lib64/SciQLop",
73 74 a.applicationDirPath() + "/../lib64/sciqlop",
74 75 a.applicationDirPath() + "/../lib/SciQLop",
75 76 a.applicationDirPath() + "/../lib/sciqlop",
76 77 #endif
77 78 };
78 79
79 80 #if _WIN32 || _WIN64
80 81 pluginDir.mkdir(PLUGIN_DIRECTORY_NAME);
81 82 pluginDir.cd(PLUGIN_DIRECTORY_NAME);
82 83 #endif
83 84
84 85 PluginManager pluginManager {};
85 86
86 87 for (auto&& path : pluginLookupPath)
87 88 {
88 89 QDir directory { path };
89 90 if (directory.exists())
90 91 {
91 92 qCDebug(LOG_Main())
92 93 << QObject::tr("Plugin directory: %1").arg(directory.absolutePath());
93 94 pluginManager.loadPlugins(directory);
94 95 }
95 96 }
96 97 pluginManager.loadStaticPlugins();
97 98
98 99 return a.exec();
99 100 }
@@ -1,395 +1,395
1 1 /*------------------------------------------------------------------------------
2 2 -- This file is a part of the SciQLop Software
3 3 -- Copyright (C) 2017, Plasma Physics Laboratory - CNRS
4 4 --
5 5 -- This program is free software; you can redistribute it and/or modify
6 6 -- it under the terms of the GNU General Public License as published by
7 7 -- the Free Software Foundation; either version 2 of the License, or
8 8 -- (at your option) any later version.
9 9 --
10 10 -- This program is distributed in the hope that it will be useful,
11 11 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 13 -- GNU General Public License for more details.
14 14 --
15 15 -- You should have received a copy of the GNU General Public License
16 16 -- along with this program; if not, write to the Free Software
17 17 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 18 -------------------------------------------------------------------------------*/
19 19 /*-- Author : Alexis Jeandet
20 20 -- Mail : alexis.jeandet@member.fsf.org
21 21 ----------------------------------------------------------------------------*/
22 22 #include "MainWindow.h"
23 23 #include "ui_MainWindow.h"
24 24
25 25 #include <Catalogue/CatalogueController.h>
26 26 //#include <Catalogue/CatalogueExplorer.h>
27 27 #include <DataSource/DataSourceController.h>
28 28 #include <DataSource/DataSourceWidget.h>
29 29 #include <Settings/SqpSettingsDialog.h>
30 30 #include <Settings/SqpSettingsGeneralWidget.h>
31 31 #include <SidePane/SqpSidePane.h>
32 32 #include <SqpApplication.h>
33 33 #include <Time/TimeController.h>
34 34 #include <TimeWidget/TimeWidget.h>
35 35 #include <Visualization/VisualizationController.h>
36 36
37 37 #include <QAction>
38 38 #include <QCloseEvent>
39 39 #include <QDate>
40 40 #include <QDir>
41 41 #include <QFileDialog>
42 42 #include <QMessageBox>
43 43 #include <QToolBar>
44 44 #include <QToolButton>
45 45 #include <memory.h>
46 46
47 47 #include "iostream"
48 48
49 49 Q_LOGGING_CATEGORY(LOG_MainWindow, "MainWindow")
50 50
51 51 namespace
52 52 {
53 53 const auto LEFTMAININSPECTORWIDGETSPLITTERINDEX = 0;
54 54 const auto LEFTINSPECTORSIDEPANESPLITTERINDEX = 1;
55 55 const auto VIEWPLITTERINDEX = 2;
56 56 const auto RIGHTINSPECTORSIDEPANESPLITTERINDEX = 3;
57 57 const auto RIGHTMAININSPECTORWIDGETSPLITTERINDEX = 4;
58 58 }
59 59
60 60 class MainWindow::MainWindowPrivate
61 61 {
62 62 public:
63 63 explicit MainWindowPrivate(MainWindow* mainWindow)
64 64 : m_LastOpenLeftInspectorSize {}
65 65 , m_LastOpenRightInspectorSize {}
66 66 , m_GeneralSettingsWidget { new SqpSettingsGeneralWidget { mainWindow } }
67 67 , m_SettingsDialog { new SqpSettingsDialog { mainWindow } }
68 68 //, m_CatalogExplorer { new CatalogueExplorer { mainWindow } }
69 69 {
70 70 }
71 71
72 72 QSize m_LastOpenLeftInspectorSize;
73 73 QSize m_LastOpenRightInspectorSize;
74 74 /// General settings widget. MainWindow has the ownership
75 75 SqpSettingsGeneralWidget* m_GeneralSettingsWidget;
76 76 /// Settings dialog. MainWindow has the ownership
77 77 SqpSettingsDialog* m_SettingsDialog;
78 78 /// Catalogue dialog. MainWindow has the ownership
79 79 // CatalogueExplorer* m_CatalogExplorer;
80 80
81 81 bool checkDataToSave(QWidget* parentWidget);
82 82 };
83 83
84 84 MainWindow::MainWindow(QWidget* parent)
85 85 : QMainWindow { parent }
86 86 , m_Ui { new Ui::MainWindow }
87 87 , impl { spimpl::make_unique_impl<MainWindowPrivate>(this) }
88 88 {
89 89 m_Ui->setupUi(this);
90 90
91 91 m_Ui->splitter->setCollapsible(LEFTINSPECTORSIDEPANESPLITTERINDEX, false);
92 92 m_Ui->splitter->setCollapsible(RIGHTINSPECTORSIDEPANESPLITTERINDEX, false);
93 93
94 94 // impl->m_CatalogExplorer->setVisualizationWidget(m_Ui->view);
95 95
96 96
97 97 auto spacerLeftTop = new QWidget {};
98 98 spacerLeftTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
99 99
100 100 auto spacerLeftBottom = new QWidget {};
101 101 spacerLeftBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
102 102
103 103
104 104 auto spacerRightTop = new QWidget {};
105 105 spacerRightTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
106 106
107 107 auto spacerRightBottom = new QWidget {};
108 108 spacerRightBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
109 109
110 110
111 111 auto openInspector = [this](bool checked, bool right, auto action) {
112 112 action->setIcon(
113 113 QIcon { (checked ^ right) ? ":/icones/next.png" : ":/icones/previous.png" });
114 114
115 115 auto& lastInspectorSize
116 116 = right ? impl->m_LastOpenRightInspectorSize : impl->m_LastOpenLeftInspectorSize;
117 117
118 118 auto nextInspectorSize = right ? m_Ui->rightMainInspectorWidget->size()
119 119 : m_Ui->leftMainInspectorWidget->size();
120 120
121 121 // Update of the last opened geometry
122 122 if (checked)
123 123 {
124 124 lastInspectorSize = nextInspectorSize;
125 125 }
126 126
127 127 auto startSize = lastInspectorSize;
128 128 auto endSize = startSize;
129 129 endSize.setWidth(0);
130 130
131 131 auto splitterInspectorIndex
132 132 = right ? RIGHTMAININSPECTORWIDGETSPLITTERINDEX : LEFTMAININSPECTORWIDGETSPLITTERINDEX;
133 133
134 134 auto currentSizes = m_Ui->splitter->sizes();
135 135 if (checked)
136 136 {
137 137 // adjust sizes individually here, e.g.
138 138 currentSizes[splitterInspectorIndex] -= lastInspectorSize.width();
139 139 currentSizes[VIEWPLITTERINDEX] += lastInspectorSize.width();
140 140 m_Ui->splitter->setSizes(currentSizes);
141 141 }
142 142 else
143 143 {
144 144 // adjust sizes individually here, e.g.
145 145 currentSizes[splitterInspectorIndex] += lastInspectorSize.width();
146 146 currentSizes[VIEWPLITTERINDEX] -= lastInspectorSize.width();
147 147 m_Ui->splitter->setSizes(currentSizes);
148 148 }
149 149 };
150 150
151 151
152 152 // //////////////// //
153 153 // Menu and Toolbar //
154 154 // //////////////// //
155 155 this->menuBar()->addAction(tr("File"));
156 156 auto toolsMenu = this->menuBar()->addMenu(tr("Tools"));
157 157 toolsMenu->addAction(tr("Settings..."), [this]() {
158 158 // Loads settings
159 159 impl->m_SettingsDialog->loadSettings();
160 160
161 161 // Open settings dialog and save settings if the dialog is accepted
162 162 if (impl->m_SettingsDialog->exec() == QDialog::Accepted)
163 163 {
164 164 impl->m_SettingsDialog->saveSettings();
165 165 }
166 166 });
167 167
168 168 auto mainToolBar = this->addToolBar(QStringLiteral("MainToolBar"));
169 169
170 170 auto timeWidget = new TimeWidget {};
171 171 mainToolBar->addWidget(timeWidget);
172 172
173 173 // Interaction modes
174 174 auto actionPointerMode = new QAction { QIcon(":/icones/pointer.png"), "Move", this };
175 175 actionPointerMode->setCheckable(true);
176 176 actionPointerMode->setChecked(
177 177 sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::None);
178 178 connect(actionPointerMode, &QAction::triggered,
179 179 []() { sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::None); });
180 180
181 181 auto actionZoomMode = new QAction { QIcon(":/icones/zoom.png"), "Zoom", this };
182 182 actionZoomMode->setCheckable(true);
183 183 actionZoomMode->setChecked(
184 184 sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox);
185 185 connect(actionZoomMode, &QAction::triggered,
186 186 []() { sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::ZoomBox); });
187 187
188 188 auto actionOrganisationMode = new QAction { QIcon(":/icones/drag.png"), "Organize", this };
189 189 actionOrganisationMode->setCheckable(true);
190 190 actionOrganisationMode->setChecked(
191 191 sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::DragAndDrop);
192 192 connect(actionOrganisationMode, &QAction::triggered, []() {
193 193 sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::DragAndDrop);
194 194 });
195 195
196 196 auto actionZonesMode = new QAction { QIcon(":/icones/rectangle.png"), "Zones", this };
197 197 actionZonesMode->setCheckable(true);
198 198 actionZonesMode->setChecked(
199 199 sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones);
200 200 connect(actionZonesMode, &QAction::triggered, []() {
201 201 sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::SelectionZones);
202 202 });
203 203
204 204 auto modeActionGroup = new QActionGroup { this };
205 205 modeActionGroup->addAction(actionZoomMode);
206 206 modeActionGroup->addAction(actionZonesMode);
207 207 modeActionGroup->addAction(actionOrganisationMode);
208 208 modeActionGroup->addAction(actionPointerMode);
209 209 modeActionGroup->setExclusive(true);
210 210
211 211 mainToolBar->addSeparator();
212 212 mainToolBar->addAction(actionPointerMode);
213 213 mainToolBar->addAction(actionZoomMode);
214 214 mainToolBar->addAction(actionOrganisationMode);
215 215 mainToolBar->addAction(actionZonesMode);
216 216 mainToolBar->addSeparator();
217 217
218 218 // Cursors
219 219 auto btnCursor = new QToolButton { this };
220 220 btnCursor->setIcon(QIcon(":/icones/cursor.png"));
221 221 btnCursor->setText("Cursor");
222 222 btnCursor->setToolTip("Cursor");
223 223 btnCursor->setPopupMode(QToolButton::InstantPopup);
224 224 auto cursorMenu = new QMenu("CursorMenu", this);
225 225 btnCursor->setMenu(cursorMenu);
226 226
227 227 auto noCursorAction = cursorMenu->addAction("No Cursor");
228 228 noCursorAction->setCheckable(true);
229 229 noCursorAction->setChecked(
230 230 sqpApp->plotsCursorMode() == SqpApplication::PlotsCursorMode::NoCursor);
231 231 connect(noCursorAction, &QAction::triggered,
232 232 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::NoCursor); });
233 233
234 234 cursorMenu->addSeparator();
235 235 auto verticalCursorAction = cursorMenu->addAction("Vertical Cursor");
236 236 verticalCursorAction->setCheckable(true);
237 237 verticalCursorAction->setChecked(
238 238 sqpApp->plotsCursorMode() == SqpApplication::PlotsCursorMode::Vertical);
239 239 connect(verticalCursorAction, &QAction::triggered,
240 240 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Vertical); });
241 241
242 242 auto temporalCursorAction = cursorMenu->addAction("Temporal Cursor");
243 243 temporalCursorAction->setCheckable(true);
244 244 temporalCursorAction->setChecked(
245 245 sqpApp->plotsCursorMode() == SqpApplication::PlotsCursorMode::Temporal);
246 246 connect(temporalCursorAction, &QAction::triggered,
247 247 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Temporal); });
248 248
249 249 auto horizontalCursorAction = cursorMenu->addAction("Horizontal Cursor");
250 250 horizontalCursorAction->setCheckable(true);
251 251 horizontalCursorAction->setChecked(
252 252 sqpApp->plotsCursorMode() == SqpApplication::PlotsCursorMode::Horizontal);
253 253 connect(horizontalCursorAction, &QAction::triggered,
254 254 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Horizontal); });
255 255
256 256 auto crossCursorAction = cursorMenu->addAction("Cross Cursor");
257 257 crossCursorAction->setCheckable(true);
258 258 crossCursorAction->setChecked(
259 259 sqpApp->plotsCursorMode() == SqpApplication::PlotsCursorMode::Cross);
260 260 connect(crossCursorAction, &QAction::triggered,
261 261 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Cross); });
262 262
263 263 mainToolBar->addWidget(btnCursor);
264 264
265 265 auto cursorModeActionGroup = new QActionGroup { this };
266 266 cursorModeActionGroup->setExclusive(true);
267 267 cursorModeActionGroup->addAction(noCursorAction);
268 268 cursorModeActionGroup->addAction(verticalCursorAction);
269 269 cursorModeActionGroup->addAction(temporalCursorAction);
270 270 cursorModeActionGroup->addAction(horizontalCursorAction);
271 271 cursorModeActionGroup->addAction(crossCursorAction);
272 272
273 273 // Catalog
274 274 mainToolBar->addSeparator();
275 275 // mainToolBar->addAction(QIcon(":/icones/catalogue.png"), "Catalogues",
276 276 // [this]() { impl->m_CatalogExplorer->show(); });
277 277
278 278 // //////// //
279 279 // Settings //
280 280 // //////// //
281 281
282 282 // Registers "general settings" widget to the settings dialog
283 283 impl->m_SettingsDialog->registerWidget(
284 284 QStringLiteral("General"), impl->m_GeneralSettingsWidget);
285 285
286 286 // /////////// //
287 287 // Connections //
288 288 // /////////// //
289 289
290 290 // Controllers / controllers connections
291 291 // connect(&sqpApp->timeController(), SIGNAL(timeUpdated(DateTimeRange)),
292 292 // &sqpApp->variableController(),
293 293 // SLOT(onDateTimeOnSelection(DateTimeRange)));
294 294
295 295 // Widgets / controllers connections
296 296
297 297 // DataSource
298 298 connect(&sqpApp->dataSourceController(), SIGNAL(dataSourceItemSet(DataSourceItem*)),
299 299 m_Ui->dataSourceWidget, SLOT(addDataSource(DataSourceItem*)));
300 300
301 301 // Time
302 302 connect(timeWidget, SIGNAL(timeUpdated(DateTimeRange)), &sqpApp->timeController(),
303 303 SLOT(onTimeToUpdate(DateTimeRange)));
304 304
305 305 // Visualization
306 306 connect(&sqpApp->visualizationController(),
307 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), m_Ui->view,
308 SLOT(onVariableAboutToBeDeleted(std::shared_ptr<Variable>)));
307 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable2>)), m_Ui->view,
308 SLOT(onVariableAboutToBeDeleted(std::shared_ptr<Variable2>)));
309 309
310 310 connect(&sqpApp->visualizationController(),
311 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const DateTimeRange&)), m_Ui->view,
312 SLOT(onRangeChanged(std::shared_ptr<Variable>, const DateTimeRange&)));
311 SIGNAL(rangeChanged(std::shared_ptr<Variable2>, const DateTimeRange&)), m_Ui->view,
312 SLOT(onRangeChanged(std::shared_ptr<Variable2>, const DateTimeRange&)));
313 313
314 314 // Widgets / widgets connections
315 315
316 316 // For the following connections, we use DirectConnection to allow each widget that can
317 317 // potentially attach a menu to the variable's menu to do so before this menu is displayed.
318 318 // The order of connections is also important, since it determines the order in which each
319 319 // widget will attach its menu
320 320 connect(m_Ui->variableInspectorWidget,
321 321 SIGNAL(tableMenuAboutToBeDisplayed(QMenu*, const QVector<std::shared_ptr<Variable>>&)),
322 322 m_Ui->view, SLOT(attachVariableMenu(QMenu*, const QVector<std::shared_ptr<Variable>>&)),
323 323 Qt::DirectConnection);
324 324 }
325 325
326 326 MainWindow::~MainWindow() {}
327 327
328 328 void MainWindow::changeEvent(QEvent* e)
329 329 {
330 330 QMainWindow::changeEvent(e);
331 331 switch (e->type())
332 332 {
333 333 case QEvent::LanguageChange:
334 334 m_Ui->retranslateUi(this);
335 335 break;
336 336 default:
337 337 break;
338 338 }
339 339 }
340 340
341 341 void MainWindow::closeEvent(QCloseEvent* event)
342 342 {
343 343 if (!impl->checkDataToSave(this))
344 344 {
345 345 event->ignore();
346 346 }
347 347 else
348 348 {
349 349 event->accept();
350 350 }
351 351 }
352 352
353 353 void MainWindow::keyPressEvent(QKeyEvent* event)
354 354 {
355 355 switch (event->key())
356 356 {
357 357 case Qt::Key_F11:
358 358 if (this->isFullScreen())
359 359 {
360 360 this->showNormal();
361 361 }
362 362 else
363 363 {
364 364 this->showFullScreen();
365 365 }
366 366 break;
367 367 default:
368 368 break;
369 369 }
370 370 }
371 371
372 372 bool MainWindow::MainWindowPrivate::checkDataToSave(QWidget* parentWidget)
373 373 {
374 374 // auto hasChanges = sqpApp->catalogueController().hasChanges();
375 375 // if (hasChanges)
376 376 // {
377 377 // // There are some unsaved changes
378 378 // switch (QMessageBox::question(parentWidget, tr("Save changes"),
379 379 // tr("The catalogue controller has unsaved changes.\nDo you want to save them ?"),
380 380 // QMessageBox::SaveAll | QMessageBox::Discard | QMessageBox::Cancel,
381 381 // QMessageBox::SaveAll))
382 382 // {
383 383 // case QMessageBox::SaveAll:
384 384 // sqpApp->catalogueController().saveAll();
385 385 // break;
386 386 // case QMessageBox::Discard:
387 387 // break;
388 388 // case QMessageBox::Cancel:
389 389 // default:
390 390 // return false;
391 391 // }
392 392 // }
393 393
394 394 return true;
395 395 }
@@ -1,1 +1,1
1 Subproject commit cc26524fb5d10feca3820e6921c9cd3cfb1a3591
1 Subproject commit 00ce7df31d3e11df8a418988c601247f6dc64d13
@@ -1,90 +1,90
1 1 #ifndef SCIQLOP_VISUALIZATIONTABWIDGET_H
2 2 #define SCIQLOP_VISUALIZATIONTABWIDGET_H
3 3
4 4 #include "Visualization/IVisualizationWidget.h"
5 5
6 6 #include <Common/spimpl.h>
7 7
8 8 #include <QLoggingCategory>
9 9 #include <QMimeData>
10 10 #include <QWidget>
11 11
12 12 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationTabWidget)
13 13
14 class Variable;
14 class Variable2;
15 15 class VisualizationZoneWidget;
16 16
17 17 namespace Ui
18 18 {
19 19 class VisualizationTabWidget;
20 20 } // namespace Ui
21 21
22 22 class VisualizationTabWidget : public QWidget, public IVisualizationWidget
23 23 {
24 24 Q_OBJECT
25 25
26 26 public:
27 27 explicit VisualizationTabWidget(const QString& name = {}, QWidget* parent = 0);
28 28 virtual ~VisualizationTabWidget();
29 29
30 30 /// Adds a zone widget
31 31 void addZone(VisualizationZoneWidget* zoneWidget);
32 32
33 33 /// Inserts a zone widget at the specified position
34 34 void insertZone(int index, VisualizationZoneWidget* zoneWidget);
35 35
36 36 /// Returns the list of zone widget names in the order they are displayed
37 37 QStringList availableZoneWidgets() const;
38 38
39 39 /// Returns the zone with the specified name.
40 40 /// If multiple zone with the same name exist, the first one is returned.
41 41 VisualizationZoneWidget* getZoneWithName(const QString& zoneName);
42 42
43 43 /**
44 44 * Creates a zone using a variable. The variable will be displayed in a new graph of the new
45 45 * zone. The zone is added at the end.
46 46 * @param variable the variable for which to create the zone
47 47 * @return the pointer to the created zone
48 48 */
49 49 VisualizationZoneWidget* createZone(std::shared_ptr<Variable2> variable);
50 50
51 51 /**
52 52 * Creates a zone using a list of variables. The variables will be displayed in a new graph of
53 53 * the new zone. The zone is inserted at the specified index.
54 54 * @param variables the variables for which to create the zone
55 55 * @param index The index where the zone should be inserted in the layout
56 56 * @return the pointer to the created zone
57 57 */
58 58 VisualizationZoneWidget* createZone(
59 59 const std::vector<std::shared_ptr<Variable2>>& variables, int index);
60 60
61 61 /**
62 62 * Creates a zone which is empty (no variables). The zone is inserted at the specified index.
63 63 * @param index The index where the zone should be inserted in the layout
64 64 * @return the pointer to the created zone
65 65 */
66 66 VisualizationZoneWidget* createEmptyZone(int index);
67 67
68 68 // IVisualizationWidget interface
69 69 void accept(IVisualizationWidgetVisitor* visitor) override;
70 70 bool canDrop(Variable2& variable) const override;
71 71 bool contains(Variable2& variable) const override;
72 72 QString name() const override;
73 73
74 74 protected:
75 75 void closeEvent(QCloseEvent* event) override;
76 76
77 77 private:
78 78 /// @return the layout of tab in which zones are added
79 79 QLayout& tabLayout() const noexcept;
80 80
81 81 Ui::VisualizationTabWidget* ui;
82 82
83 83 class VisualizationTabWidgetPrivate;
84 84 spimpl::unique_impl_ptr<VisualizationTabWidgetPrivate> impl;
85 85
86 86 private slots:
87 87 void dropMimeData(int index, const QMimeData* mimeData);
88 88 };
89 89
90 90 #endif // SCIQLOP_VISUALIZATIONTABWIDGET_H
@@ -1,442 +1,445
1 1 #include "Visualization/VisualizationGraphHelper.h"
2 2 #include "Visualization/qcustomplot.h"
3 3
4 4 #include <Data/ScalarTimeSerie.h>
5 5 #include <Data/SpectrogramTimeSerie.h>
6 6 #include <Data/VectorTimeSerie.h>
7 7
8 8 #include <Variable/Variable2.h>
9 9
10 10 Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper")
11 11
12 12 namespace
13 13 {
14 14
15 15 class SqpDataContainer : public QCPGraphDataContainer
16 16 {
17 17 public:
18 18 void appendGraphData(const QCPGraphData& data) { mData.append(data); }
19 19 };
20 20
21 21 /**
22 22 * Struct used to create plottables, depending on the type of the data series from which to create
23 23 * them
24 24 * @tparam T the data series' type
25 25 * @remarks Default implementation can't create plottables
26 26 */
27 27 template <typename T, typename Enabled = void>
28 28 struct PlottablesCreator
29 29 {
30 30 static PlottablesMap createPlottables(QCustomPlot&) { return {}; }
31 31 };
32 32
33 33 PlottablesMap createGraphs(QCustomPlot& plot, int nbGraphs)
34 34 {
35 35 PlottablesMap result {};
36 36
37 37 // Creates {nbGraphs} QCPGraph to add to the plot
38 38 for (auto i = 0; i < nbGraphs; ++i)
39 39 {
40 40 auto graph = plot.addGraph();
41 41 result.insert({ i, graph });
42 42 }
43 43
44 44 plot.replot();
45 45
46 46 return result;
47 47 }
48 48
49 49 /**
50 50 * Specialization of PlottablesCreator for scalars
51 51 * @sa ScalarSeries
52 52 */
53 53 template <typename T>
54 54 struct PlottablesCreator<T, typename std::enable_if_t<std::is_base_of<ScalarTimeSerie, T>::value>>
55 55 {
56 56 static PlottablesMap createPlottables(QCustomPlot& plot) { return createGraphs(plot, 1); }
57 57 };
58 58
59 59 /**
60 60 * Specialization of PlottablesCreator for vectors
61 61 * @sa VectorSeries
62 62 */
63 63 template <typename T>
64 64 struct PlottablesCreator<T, typename std::enable_if_t<std::is_base_of<VectorTimeSerie, T>::value>>
65 65 {
66 66 static PlottablesMap createPlottables(QCustomPlot& plot) { return createGraphs(plot, 3); }
67 67 };
68 68
69 69 /**
70 70 * Specialization of PlottablesCreator for spectrograms
71 71 * @sa SpectrogramSeries
72 72 */
73 73 template <typename T>
74 74 struct PlottablesCreator<T,
75 75 typename std::enable_if_t<std::is_base_of<SpectrogramTimeSerie, T>::value>>
76 76 {
77 77 static PlottablesMap createPlottables(QCustomPlot& plot)
78 78 {
79 79 PlottablesMap result {};
80 80 result.insert({ 0, new QCPColorMap { plot.xAxis, plot.yAxis } });
81 81
82 82 plot.replot();
83 83
84 84 return result;
85 85 }
86 86 };
87 87
88 88 /**
89 89 * Struct used to update plottables, depending on the type of the data series from which to update
90 90 * them
91 91 * @tparam T the data series' type
92 92 * @remarks Default implementation can't update plottables
93 93 */
94 94 template <typename T, typename Enabled = void>
95 95 struct PlottablesUpdater
96 96 {
97 97 static void setPlotYAxisRange(T&, const DateTimeRange&, QCustomPlot&)
98 98 {
99 99 qCCritical(LOG_VisualizationGraphHelper())
100 100 << QObject::tr("Can't set plot y-axis range: unmanaged data series type");
101 101 }
102 102
103 103 static void updatePlottables(T&, PlottablesMap&, const DateTimeRange&, bool)
104 104 {
105 105 qCCritical(LOG_VisualizationGraphHelper())
106 106 << QObject::tr("Can't update plottables: unmanaged data series type");
107 107 }
108 108 };
109 109
110 110 /**
111 111 * Specialization of PlottablesUpdater for scalars and vectors
112 112 * @sa ScalarSeries
113 113 * @sa VectorSeries
114 114 */
115 115 template <typename T>
116 116 struct PlottablesUpdater<T, typename std::enable_if_t<std::is_base_of<ScalarTimeSerie, T>::value>>
117 117 {
118 118 static void setPlotYAxisRange(T& dataSeries, const DateTimeRange& xAxisRange, QCustomPlot& plot)
119 119 {
120 120 auto minValue = 0., maxValue = 0.;
121 121 if (auto serie = dynamic_cast<ScalarTimeSerie*>(&dataSeries))
122 122 {
123 maxValue = (*std::max_element(std::begin(*serie), std::end(*serie))).v();
124 minValue = (*std::min_element(std::begin(*serie), std::end(*serie))).v();
123 if (serie->size())
124 {
125 maxValue = (*std::max_element(std::begin(*serie), std::end(*serie))).v();
126 minValue = (*std::min_element(std::begin(*serie), std::end(*serie))).v();
127 }
125 128 }
126 129 plot.yAxis->setRange(QCPRange { minValue, maxValue });
127 130 }
128 131
129 132 static void updatePlottables(
130 133 T& dataSeries, PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes)
131 134 {
132 135
133 136 // For each plottable to update, resets its data
134 137 for (const auto& plottable : plottables)
135 138 {
136 139 if (auto graph = dynamic_cast<QCPGraph*>(plottable.second))
137 140 {
138 141 auto dataContainer = QSharedPointer<SqpDataContainer>::create();
139 142 if (auto serie = dynamic_cast<ScalarTimeSerie*>(&dataSeries))
140 143 {
141 144 std::for_each(
142 145 std::begin(*serie), std::end(*serie), [&dataContainer](const auto& value) {
143 146 dataContainer->appendGraphData(QCPGraphData(value.t(), value.v()));
144 147 });
145 148 }
146 149 graph->setData(dataContainer);
147 150 }
148 151 }
149 152
150 153 if (!plottables.empty())
151 154 {
152 155 auto plot = plottables.begin()->second->parentPlot();
153 156
154 157 if (rescaleAxes)
155 158 {
156 159 plot->rescaleAxes();
157 160 }
158 161 }
159 162 }
160 163 };
161 164
162 165
163 166 template <typename T>
164 167 struct PlottablesUpdater<T, typename std::enable_if_t<std::is_base_of<VectorTimeSerie, T>::value>>
165 168 {
166 169 static void setPlotYAxisRange(T& dataSeries, const DateTimeRange& xAxisRange, QCustomPlot& plot)
167 170 {
168 171 double minValue = 0., maxValue = 0.;
169 172 if (auto serie = dynamic_cast<VectorTimeSerie*>(&dataSeries))
170 173 {
171 174 std::for_each(
172 175 std::begin(*serie), std::end(*serie), [&minValue, &maxValue](const auto& v) {
173 176 minValue = std::min({ minValue, v.v().x, v.v().y, v.v().z });
174 177 maxValue = std::max({ maxValue, v.v().x, v.v().y, v.v().z });
175 178 });
176 179 }
177 180
178 181 plot.yAxis->setRange(QCPRange { minValue, maxValue });
179 182 }
180 183
181 184 static void updatePlottables(
182 185 T& dataSeries, PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes)
183 186 {
184 187
185 188 // For each plottable to update, resets its data
186 189 for (const auto& plottable : plottables)
187 190 {
188 191 if (auto graph = dynamic_cast<QCPGraph*>(plottable.second))
189 192 {
190 193 auto dataContainer = QSharedPointer<SqpDataContainer>::create();
191 194 if (auto serie = dynamic_cast<VectorTimeSerie*>(&dataSeries))
192 195 {
193 196 switch (plottable.first)
194 197 {
195 198 case 0:
196 199 std::for_each(std::begin(*serie), std::end(*serie),
197 200 [&dataContainer](const auto& value) {
198 201 dataContainer->appendGraphData(
199 202 QCPGraphData(value.t(), value.v().x));
200 203 });
201 204 break;
202 205 case 1:
203 206 std::for_each(std::begin(*serie), std::end(*serie),
204 207 [&dataContainer](const auto& value) {
205 208 dataContainer->appendGraphData(
206 209 QCPGraphData(value.t(), value.v().y));
207 210 });
208 211 break;
209 212 case 2:
210 213 std::for_each(std::begin(*serie), std::end(*serie),
211 214 [&dataContainer](const auto& value) {
212 215 dataContainer->appendGraphData(
213 216 QCPGraphData(value.t(), value.v().z));
214 217 });
215 218 break;
216 219 default:
217 220 break;
218 221 }
219 222 }
220 223 graph->setData(dataContainer);
221 224 }
222 225 }
223 226
224 227 if (!plottables.empty())
225 228 {
226 229 auto plot = plottables.begin()->second->parentPlot();
227 230
228 231 if (rescaleAxes)
229 232 {
230 233 plot->rescaleAxes();
231 234 }
232 235 }
233 236 }
234 237 };
235 238
236 239 /**
237 240 * Specialization of PlottablesUpdater for spectrograms
238 241 * @sa SpectrogramSeries
239 242 */
240 243 template <typename T>
241 244 struct PlottablesUpdater<T,
242 245 typename std::enable_if_t<std::is_base_of<SpectrogramTimeSerie, T>::value>>
243 246 {
244 247 static void setPlotYAxisRange(T& dataSeries, const DateTimeRange& xAxisRange, QCustomPlot& plot)
245 248 {
246 249 // TODO
247 250 // double min, max;
248 251 // std::tie(min, max) = dataSeries.yBounds();
249 252
250 253 // if (!std::isnan(min) && !std::isnan(max))
251 254 // {
252 255 // plot.yAxis->setRange(QCPRange { min, max });
253 256 // }
254 257 }
255 258
256 259 static void updatePlottables(
257 260 T& dataSeries, PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes)
258 261 {
259 262 // TODO
260 263 // if (plottables.empty())
261 264 // {
262 265 // qCDebug(LOG_VisualizationGraphHelper())
263 266 // << QObject::tr("Can't update spectrogram: no colormap has been
264 267 // associated");
265 268 // return;
266 269 // }
267 270
268 271 // // Gets the colormap to update (normally there is only one colormap)
269 272 // Q_ASSERT(plottables.size() == 1);
270 273 // auto colormap = dynamic_cast<QCPColorMap*>(plottables.at(0));
271 274 // Q_ASSERT(colormap != nullptr);
272 275
273 276 // dataSeries.lockRead();
274 277
275 278 // // Processing spectrogram data for display in QCustomPlot
276 279 // auto its = dataSeries.xAxisRange(range.m_TStart, range.m_TEnd);
277 280
278 281 // // Computes logarithmic y-axis resolution for the spectrogram
279 282 // auto yData = its.first->y();
280 283 // auto yResolution = DataSeriesUtils::resolution(yData.begin(), yData.end(), true);
281 284
282 285 // // Generates mesh for colormap
283 286 // auto mesh = DataSeriesUtils::regularMesh(its.first, its.second,
284 287 // DataSeriesUtils::Resolution { dataSeries.xResolution() }, yResolution);
285 288
286 289 // dataSeries.unlock();
287 290
288 291 // colormap->data()->setSize(mesh.m_NbX, mesh.m_NbY);
289 292 // if (!mesh.isEmpty())
290 293 // {
291 294 // colormap->data()->setRange(QCPRange { mesh.m_XMin, mesh.xMax() },
292 295 // // y-axis range is converted to linear values
293 296 // QCPRange { std::pow(10, mesh.m_YMin), std::pow(10, mesh.yMax()) });
294 297
295 298 // // Sets values
296 299 // auto index = 0;
297 300 // for (auto it = mesh.m_Data.begin(), end = mesh.m_Data.end(); it != end; ++it,
298 301 // ++index)
299 302 // {
300 303 // auto xIndex = index % mesh.m_NbX;
301 304 // auto yIndex = index / mesh.m_NbX;
302 305
303 306 // colormap->data()->setCell(xIndex, yIndex, *it);
304 307
305 308 // // Makes the NaN values to be transparent in the colormap
306 309 // if (std::isnan(*it))
307 310 // {
308 311 // colormap->data()->setAlpha(xIndex, yIndex, 0);
309 312 // }
310 313 // }
311 314 // }
312 315
313 316 // // Rescales axes
314 317 // auto plot = colormap->parentPlot();
315 318
316 319 // if (rescaleAxes)
317 320 // {
318 321 // plot->rescaleAxes();
319 322 // }
320 323 }
321 324 };
322 325
323 326 /**
324 327 * Helper used to create/update plottables
325 328 */
326 329 struct IPlottablesHelper
327 330 {
328 331 virtual ~IPlottablesHelper() noexcept = default;
329 332 virtual PlottablesMap create(QCustomPlot& plot) const = 0;
330 333 virtual void setYAxisRange(const DateTimeRange& xAxisRange, QCustomPlot& plot) const = 0;
331 334 virtual void update(
332 335 PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes = false) const = 0;
333 336 };
334 337
335 338 /**
336 339 * Default implementation of IPlottablesHelper, which takes data series to create/update plottables
337 340 * @tparam T the data series' type
338 341 */
339 342 template <typename T>
340 343 struct PlottablesHelper : public IPlottablesHelper
341 344 {
342 345 explicit PlottablesHelper(std::shared_ptr<T> dataSeries) : m_DataSeries { dataSeries } {}
343 346
344 347 PlottablesMap create(QCustomPlot& plot) const override
345 348 {
346 349 return PlottablesCreator<T>::createPlottables(plot);
347 350 }
348 351
349 352 void update(
350 353 PlottablesMap& plottables, const DateTimeRange& range, bool rescaleAxes) const override
351 354 {
352 355 if (m_DataSeries)
353 356 {
354 357 PlottablesUpdater<T>::updatePlottables(*m_DataSeries, plottables, range, rescaleAxes);
355 358 }
356 359 else
357 360 {
358 361 qCCritical(LOG_VisualizationGraphHelper()) << "Can't update plottables: inconsistency "
359 362 "between the type of data series and the "
360 363 "type supposed";
361 364 }
362 365 }
363 366
364 367 void setYAxisRange(const DateTimeRange& xAxisRange, QCustomPlot& plot) const override
365 368 {
366 369 if (m_DataSeries)
367 370 {
368 371 PlottablesUpdater<T>::setPlotYAxisRange(*m_DataSeries, xAxisRange, plot);
369 372 }
370 373 else
371 374 {
372 375 qCCritical(LOG_VisualizationGraphHelper()) << "Can't update plottables: inconsistency "
373 376 "between the type of data series and the "
374 377 "type supposed";
375 378 }
376 379 }
377 380
378 381 std::shared_ptr<T> m_DataSeries;
379 382 };
380 383
381 384 /// Creates IPlottablesHelper according to the type of data series a variable holds
382 385 std::unique_ptr<IPlottablesHelper> createHelper(std::shared_ptr<Variable2> variable) noexcept
383 386 {
384 387 switch (variable->type())
385 388 {
386 389 case DataSeriesType::SCALAR:
387 390 return std::make_unique<PlottablesHelper<ScalarTimeSerie>>(
388 391 std::dynamic_pointer_cast<ScalarTimeSerie>(variable->data()));
389 392 case DataSeriesType::SPECTROGRAM:
390 393 return std::make_unique<PlottablesHelper<SpectrogramTimeSerie>>(
391 394 std::dynamic_pointer_cast<SpectrogramTimeSerie>(variable->data()));
392 395 case DataSeriesType::VECTOR:
393 396 return std::make_unique<PlottablesHelper<VectorTimeSerie>>(
394 397 std::dynamic_pointer_cast<VectorTimeSerie>(variable->data()));
395 398 default:
396 399 // Creates default helper
397 400 break;
398 401 }
399 402
400 403 return std::make_unique<PlottablesHelper<TimeSeries::ITimeSerie>>(nullptr);
401 404 }
402 405
403 406 } // namespace
404 407
405 408 PlottablesMap VisualizationGraphHelper::create(
406 409 std::shared_ptr<Variable2> variable, QCustomPlot& plot) noexcept
407 410 {
408 411 if (variable)
409 412 {
410 413 auto helper = createHelper(variable);
411 414 auto plottables = helper->create(plot);
412 415 return plottables;
413 416 }
414 417 else
415 418 {
416 419 qCDebug(LOG_VisualizationGraphHelper())
417 420 << QObject::tr("Can't create graph plottables : the variable is null");
418 421 return PlottablesMap {};
419 422 }
420 423 }
421 424
422 425 void VisualizationGraphHelper::setYAxisRange(
423 426 std::shared_ptr<Variable2> variable, QCustomPlot& plot) noexcept
424 427 {
425 428 if (variable)
426 429 {
427 430 auto helper = createHelper(variable);
428 431 helper->setYAxisRange(variable->range(), plot);
429 432 }
430 433 else
431 434 {
432 435 qCDebug(LOG_VisualizationGraphHelper())
433 436 << QObject::tr("Can't set y-axis range of plot: the variable is null");
434 437 }
435 438 }
436 439
437 440 void VisualizationGraphHelper::updateData(
438 441 PlottablesMap& plottables, std::shared_ptr<Variable2> variable, const DateTimeRange& dateTime)
439 442 {
440 443 auto helper = createHelper(variable);
441 444 helper->update(plottables, dateTime);
442 445 }
@@ -1,3 +1,4
1 1 add_subdirectory(mockplugin)
2 add_subdirectory(amda)
3 add_subdirectory(generic_ws)
2 add_subdirectory(python_providers)
3 #add_subdirectory(amda)
4 #add_subdirectory(generic_ws)
@@ -1,30 +1,30
1 1 #ifndef SCIQLOP_AMDAPROVIDER_H
2 2 #define SCIQLOP_AMDAPROVIDER_H
3 3
4 4 #include "AmdaGlobal.h"
5 5
6 6 #include <Data/IDataProvider.h>
7 7
8 8 #include <QLoggingCategory>
9 9
10 10 #include <map>
11 11
12 12 Q_DECLARE_LOGGING_CATEGORY(LOG_AmdaProvider)
13 13
14 14 class QNetworkReply;
15 15 class QNetworkRequest;
16 16
17 17 /**
18 18 * @brief The AmdaProvider class is an example of how a data provider can generate data
19 19 */
20 class SCIQLOP_AMDA_EXPORT AmdaProvider : public IDataProvider {
20 class SCIQLOP_AMDA_EXPORT AmdaProvider : public IDataProvider
21 {
21 22 Q_OBJECT
22 23 public:
23 24 explicit AmdaProvider();
24 25 std::shared_ptr<IDataProvider> clone() const override;
25 26
26 virtual IDataSeries *getData(const DataProviderParameters &parameters)override;
27
27 virtual TimeSeries::ITimeSerie* getData(const DataProviderParameters& parameters) override;
28 28 };
29 29
30 30 #endif // SCIQLOP_AMDAPROVIDER_H
@@ -1,88 +1,85
1 1 #include "AmdaProvider.h"
2 2 #include "AmdaDefs.h"
3 3 #include "AmdaResultParser.h"
4 4 #include "AmdaServer.h"
5 5
6 6 #include <Common/DateUtils.h>
7 7 #include <Data/DataProviderParameters.h>
8 8 #include <Network/NetworkController.h>
9 9 #include <SqpApplication.h>
10 #include <Variable/Variable.h>
11 10
11 #include <Network/Downloader.h>
12 #include <QJsonDocument>
12 13 #include <QNetworkAccessManager>
13 14 #include <QNetworkReply>
14 15 #include <QTemporaryFile>
15 16 #include <QThread>
16 #include <QJsonDocument>
17 #include <Network/Downloader.h>
18 17
19 18 Q_LOGGING_CATEGORY(LOG_AmdaProvider, "AmdaProvider")
20 19
21 namespace {
20 namespace
21 {
22 22
23 23 /// URL format for a request on AMDA server. The parameters are as follows:
24 24 /// - %1: server URL
25 25 /// - %2: start date
26 26 /// - %3: end date
27 27 /// - %4: parameter id
28 28 /// AMDA V2: http://amdatest.irap.omp.eu/php/rest/
29 29 const auto AMDA_URL_FORMAT = QStringLiteral(
30 30 "http://%1/php/rest/"
31 31 "getParameter.php?startTime=%2&stopTime=%3&parameterID=%4&outputFormat=ASCII&"
32 32 "timeFormat=ISO8601&gzip=0");
33 33
34 34 const auto AMDA_URL_FORMAT_WITH_TOKEN = QStringLiteral(
35 35 "http://%1/php/rest/"
36 36 "getParameter.php?startTime=%2&stopTime=%3&parameterID=%4&outputFormat=ASCII&"
37 37 "timeFormat=ISO8601&gzip=0&"
38 38 "token=%5");
39 39
40 40 const auto AMDA_TOKEN_URL_FORMAT = QStringLiteral(
41 41 "http://%1/php/rest/"
42 42 "auth.php");
43 43
44 44 /// Dates format passed in the URL (e.g 2013-09-23T09:00)
45 45 const auto AMDA_TIME_FORMAT = QStringLiteral("yyyy-MM-ddThh:mm:ss");
46 46
47 47 /// Formats a time to a date that can be passed in URL
48 48 QString dateFormat(double sqpRange) noexcept
49 49 {
50 50 auto dateTime = DateUtils::dateTime(sqpRange);
51 51 return dateTime.toString(AMDA_TIME_FORMAT);
52 52 }
53 53
54 54
55 55 } // namespace
56 56
57 AmdaProvider::AmdaProvider()
58 {
59
60 }
57 AmdaProvider::AmdaProvider() {}
61 58
62 59 std::shared_ptr<IDataProvider> AmdaProvider::clone() const
63 60 {
64 61 // No copy is made in the clone
65 62 return std::make_shared<AmdaProvider>();
66 63 }
67 64
68 IDataSeries* AmdaProvider::getData(const DataProviderParameters &parameters)
65 TimeSeries::ITimeSerie* AmdaProvider::getData(const DataProviderParameters& parameters)
69 66 {
70 67 auto range = parameters.m_Range;
71 68 auto metaData = parameters.m_Data;
72 69 auto productId = metaData.value(AMDA_XML_ID_KEY).toString();
73 70 auto productValueType
74 71 = DataSeriesTypeUtils::fromString(metaData.value(AMDA_DATA_TYPE_KEY).toString());
75 72 auto startDate = dateFormat(range.m_TStart);
76 73 auto endDate = dateFormat(range.m_TEnd);
77 QVariantHash urlProperties{{AMDA_SERVER_KEY, metaData.value(AMDA_SERVER_KEY)}};
78 auto token_url = QString{AMDA_TOKEN_URL_FORMAT}.arg(AmdaServer::instance().url(urlProperties));
74 QVariantHash urlProperties { { AMDA_SERVER_KEY, metaData.value(AMDA_SERVER_KEY) } };
75 auto token_url
76 = QString { AMDA_TOKEN_URL_FORMAT }.arg(AmdaServer::instance().url(urlProperties));
79 77 auto response = Downloader::get(token_url);
80 auto url = QString{AMDA_URL_FORMAT_WITH_TOKEN}.arg(AmdaServer::instance().url(urlProperties),
81 startDate, endDate, productId, QString(response.data()));
78 auto url = QString { AMDA_URL_FORMAT_WITH_TOKEN }.arg(AmdaServer::instance().url(urlProperties),
79 startDate, endDate, productId, QString(response.data()));
82 80 response = Downloader::get(url);
83 81 auto test = QJsonDocument::fromJson(response.data());
84 82 url = test["dataFileURLs"].toString();
85 83 response = Downloader::get(url);
86 return AmdaResultParser::readTxt(QTextStream{response.data()},productValueType);
84 return nullptr; // AmdaResultParser::readTxt(QTextStream { response.data() }, productValueType);
87 85 }
88
@@ -1,150 +1,149
1 1 #include "AmdaResultParser.h"
2 2
3 3 #include "AmdaResultParserHelper.h"
4 4
5 5 #include <QFile>
6 6
7 #include <Data/IDataSeries.h>
8 7 #include <cmath>
9 8
10 9 Q_LOGGING_CATEGORY(LOG_AmdaResultParser, "AmdaResultParser")
11 10
12 11 namespace
13 12 {
14 13
15 14 /// Message in result file when the file was not found on server
16 15 const auto FILE_NOT_FOUND_MESSAGE = QStringLiteral("Not Found");
17 16
18 17 /// Checks if a line is a comment line
19 18 bool isCommentLine(const QString& line)
20 19 {
21 20 return line.startsWith("#");
22 21 }
23 22
24 23 /**
25 24 * Creates helper that will be used to read AMDA file, according to the type passed as parameter
26 25 * @param valueType the type of values expected in the AMDA file (scalars, vectors, spectrograms...)
27 26 * @return the helper created
28 27 */
29 28 std::unique_ptr<IAmdaResultParserHelper> createHelper(DataSeriesType valueType)
30 29 {
31 30 switch (valueType)
32 31 {
33 32 case DataSeriesType::SCALAR:
34 33 return std::make_unique<ScalarParserHelper>();
35 34 case DataSeriesType::SPECTROGRAM:
36 35 return std::make_unique<SpectrogramParserHelper>();
37 36 case DataSeriesType::VECTOR:
38 37 return std::make_unique<VectorParserHelper>();
39 38 case DataSeriesType::NONE:
40 39 // Invalid case
41 40 break;
42 41 }
43 42
44 43 // Invalid cases
45 44 qCCritical(LOG_AmdaResultParser())
46 45 << QObject::tr("Can't create helper to read result file: unsupported type");
47 46 return nullptr;
48 47 }
49 48
50 49 /**
51 50 * Reads properties of the stream passed as parameter
52 51 * @param helper the helper used to read properties line by line
53 52 * @param stream the stream to read
54 53 */
55 54 void readProperties(IAmdaResultParserHelper& helper, QTextStream& stream)
56 55 {
57 56 // Searches properties in the comment lines (as long as the reading has not reached the data)
58 57 // AMDA V2: while (stream.readLineInto(&line) && !line.contains(DATA_HEADER_REGEX)) {
59 58 QString line {};
60 59 while (stream.readLineInto(&line) && isCommentLine(line))
61 60 {
62 61 helper.readPropertyLine(line);
63 62 }
64 63 }
65 64
66 65 /**
67 66 * Reads results of the stream passed as parameter
68 67 * @param helper the helper used to read results line by line
69 68 * @param stream the stream to read
70 69 */
71 70 void readResults(IAmdaResultParserHelper& helper, QTextStream& stream)
72 71 {
73 72 QString line {};
74 73
75 74 // Skip comment lines
76 75 while (stream.readLineInto(&line) && isCommentLine(line))
77 76 {
78 77 }
79 78
80 79 if (!stream.atEnd())
81 80 {
82 81 do
83 82 {
84 83 helper.readResultLine(line);
85 84 } while (stream.readLineInto(&line));
86 85 }
87 86 }
88 87
89 88 } // namespace
90 89
91 90 std::shared_ptr<IDataSeries> AmdaResultParser::readTxt(
92 91 const QString& filePath, DataSeriesType type) noexcept
93 92 {
94 93 if (type == DataSeriesType::NONE)
95 94 {
96 95 qCCritical(LOG_AmdaResultParser())
97 96 << QObject::tr("Can't retrieve AMDA data: the type of values to be read is unknown");
98 97 return nullptr;
99 98 }
100 99
101 100 QFile file { filePath };
102 101
103 102 if (!file.open(QFile::ReadOnly | QIODevice::Text))
104 103 {
105 104 qCCritical(LOG_AmdaResultParser())
106 105 << QObject::tr("Can't retrieve AMDA data from file %1: %2")
107 106 .arg(filePath, file.errorString());
108 107 return nullptr;
109 108 }
110 109
111 110 return std::shared_ptr<IDataSeries> { AmdaResultParser::readTxt(QTextStream { &file }, type) };
112 111 }
113 112
114 113 IDataSeries* AmdaResultParser::readTxt(QTextStream stream, DataSeriesType type) noexcept
115 114 {
116 115 if (type == DataSeriesType::NONE)
117 116 {
118 117 return nullptr;
119 118 }
120 119
121 120 // Checks if the file was found on the server
122 121 auto firstLine = stream.readLine();
123 122 if (firstLine.compare(FILE_NOT_FOUND_MESSAGE) == 0)
124 123 {
125 124 return nullptr;
126 125 }
127 126
128 127 auto helper = createHelper(type);
129 128 Q_ASSERT(helper != nullptr);
130 129
131 130 // Reads header file to retrieve properties
132 131 stream.seek(0); // returns to the beginning of the file
133 132 readProperties(*helper, stream);
134 133
135 134 // Checks properties
136 135 if (helper->checkProperties())
137 136 {
138 137 // Reads results
139 138 // AMDA V2: remove line
140 139 stream.seek(0); // returns to the beginning of the file
141 140 readResults(*helper, stream);
142 141
143 142 // Creates data series
144 143 return helper->createSeries();
145 144 }
146 145 else
147 146 {
148 147 return nullptr;
149 148 }
150 149 }
@@ -1,128 +1,131
1 1 #ifndef SCIQLOP_FUZZINGDEFS_H
2 2 #define SCIQLOP_FUZZINGDEFS_H
3 3
4 4 #include <Data/DateTimeRange.h>
5 5
6 6 #include <QString>
7 7 #include <QUuid>
8 8 #include <QVariantHash>
9 9
10 10 #include <memory>
11 11 #include <set>
12 12
13 13 // /////// //
14 14 // Aliases //
15 15 // /////// //
16 16
17 17 using MetadataPool = std::vector<QVariantHash>;
18 18 Q_DECLARE_METATYPE(MetadataPool)
19 19
20 20 using Properties = QVariantHash;
21 21
22 22 // ///////// //
23 23 // Constants //
24 24 // ///////// //
25 25
26 26 /// Timeout set for data acquisition for an operation (in ms)
27 27 extern const QString ACQUISITION_TIMEOUT_PROPERTY;
28 28
29 29 /// Max number of operations to generate
30 30 extern const QString NB_MAX_OPERATIONS_PROPERTY;
31 31
32 32 /// Max number of sync groups to create through operations
33 33 extern const QString NB_MAX_SYNC_GROUPS_PROPERTY;
34 34
35 35 /// Max number of variables to manipulate through operations
36 36 extern const QString NB_MAX_VARIABLES_PROPERTY;
37 37
38 38 /// Set of operations available for the test
39 39 extern const QString AVAILABLE_OPERATIONS_PROPERTY;
40 40
41 41 /// Tolerance used for variable's cache (in ratio)
42 42 extern const QString CACHE_TOLERANCE_PROPERTY;
43 43
44 44 /// Range with which the timecontroller is initialized
45 45 extern const QString INITIAL_RANGE_PROPERTY;
46 46
47 47 /// Max range that an operation can reach
48 48 extern const QString MAX_RANGE_PROPERTY;
49 49
50 50 /// Set of metadata that can be associated to a variable
51 51 extern const QString METADATA_POOL_PROPERTY;
52 52
53 53 /// Provider used to retrieve data
54 54 extern const QString PROVIDER_PROPERTY;
55 55
56 56 /// Min/max times left for an operation to execute
57 57 extern const QString OPERATION_DELAY_BOUNDS_PROPERTY;
58 58
59 59 /// Validators used to validate an operation
60 60 extern const QString VALIDATORS_PROPERTY;
61 61
62 62 /// Min/max number of operations to execute before calling validation of the current test's state
63 63 extern const QString VALIDATION_FREQUENCY_BOUNDS_PROPERTY;
64 64
65 65 // /////// //
66 66 // Structs //
67 67 // /////// //
68 68
69 69 class Variable;
70 struct VariableState {
71 std::shared_ptr<Variable> m_Variable{nullptr};
72 DateTimeRange m_Range{INVALID_RANGE};
70 struct VariableState
71 {
72 std::shared_ptr<Variable> m_Variable { nullptr };
73 DateTimeRange m_Range { INVALID_RANGE };
73 74 };
74 75
75 76 using VariableId = int;
76 77 using VariablesPool = std::map<VariableId, VariableState>;
77 78
78 79 /**
79 80 * Defines a synchronization group for a fuzzing state. A group reports the variables synchronized
80 81 * with each other, and the current range of the group (i.e. range of the last synchronized variable
81 82 * that has been moved)
82 83 */
83 struct SyncGroup {
84 std::set<VariableId> m_Variables{};
85 DateTimeRange m_Range{INVALID_RANGE};
84 struct SyncGroup
85 {
86 std::set<VariableId> m_Variables {};
87 DateTimeRange m_Range { INVALID_RANGE };
86 88 };
87 89
88 90 using SyncGroupId = QUuid;
89 91 using SyncGroupsPool = std::map<SyncGroupId, SyncGroup>;
90 92
91 93 /**
92 94 * Defines a current state during a fuzzing state. It contains all the variables manipulated during
93 95 * the test, as well as the synchronization status of these variables.
94 96 */
95 struct FuzzingState {
96 const SyncGroup &syncGroup(SyncGroupId id) const;
97 SyncGroup &syncGroup(SyncGroupId id);
97 struct FuzzingState
98 {
99 const SyncGroup& syncGroup(SyncGroupId id) const;
100 SyncGroup& syncGroup(SyncGroupId id);
98 101
99 const VariableState &variableState(VariableId id) const;
100 VariableState &variableState(VariableId id);
102 const VariableState& variableState(VariableId id) const;
103 VariableState& variableState(VariableId id);
101 104
102 105 /// @return the identifier of the synchronization group in which the variable passed in
103 106 /// parameter is located. If the variable is not in any group, returns an invalid identifier
104 107 SyncGroupId syncGroupId(VariableId variableId) const;
105 108
106 109 /// @return the set of synchronization group identifiers
107 110 std::vector<SyncGroupId> syncGroupsIds() const;
108 111
109 112 /// Updates fuzzing state according to a variable synchronization
110 113 /// @param variableId the variable that is synchronized
111 114 /// @param syncGroupId the synchronization group
112 115 void synchronizeVariable(VariableId variableId, SyncGroupId syncGroupId);
113 116
114 117 /// Updates fuzzing state according to a variable desynchronization
115 118 /// @param variableId the variable that is desynchronized
116 119 /// @param syncGroupId the synchronization group from which to remove the variable
117 120 void desynchronizeVariable(VariableId variableId, SyncGroupId syncGroupId);
118 121
119 122 /// Updates the range of a variable and all variables to which it is synchronized
120 123 /// @param the variable for which to affect the range
121 124 /// @param the range to affect
122 void updateRanges(VariableId variableId, const DateTimeRange &newRange);
125 void updateRanges(VariableId variableId, const DateTimeRange& newRange);
123 126
124 127 VariablesPool m_VariablesPool;
125 128 SyncGroupsPool m_SyncGroupsPool;
126 129 };
127 130
128 131 #endif // SCIQLOP_FUZZINGDEFS_H
@@ -1,31 +1,32
1 1 #ifndef SCIQLOP_COSINUSPROVIDER_H
2 2 #define SCIQLOP_COSINUSPROVIDER_H
3 3
4 4 #include "MockPluginGlobal.h"
5 5
6 6 #include <Data/IDataProvider.h>
7 7
8 8 #include <QLoggingCategory>
9 9 #include <QUuid>
10 10
11 11 #include <QHash>
12 12
13 13 /**
14 14 * @brief The CosinusProvider class is an example of how a data provider can generate data
15 15 */
16 class SCIQLOP_MOCKPLUGIN_EXPORT CosinusProvider : public IDataProvider {
16 class SCIQLOP_MOCKPLUGIN_EXPORT CosinusProvider : public IDataProvider
17 {
17 18 public:
18 19 std::shared_ptr<IDataProvider> clone() const override;
19 20
20 virtual IDataSeries* getData(const DataProviderParameters &parameters) override;
21 virtual TimeSeries::ITimeSerie* getData(const DataProviderParameters& parameters) override;
21 22
22 23 private:
23 std::shared_ptr<IDataSeries>
24 retrieveData(QUuid acqIdentifier, const DateTimeRange &dataRangeRequested, const QVariantHash &data);
24 std::shared_ptr<IDataSeries> retrieveData(
25 QUuid acqIdentifier, const DateTimeRange& dataRangeRequested, const QVariantHash& data);
25 26
26 IDataSeries* _generate(const DateTimeRange &range, const QVariantHash &metaData);
27 TimeSeries::ITimeSerie* _generate(const DateTimeRange& range, const QVariantHash& metaData);
27 28
28 29 QHash<QUuid, bool> m_VariableToEnableProvider;
29 30 };
30 31
31 32 #endif // SCIQLOP_COSINUSPROVIDER_H
@@ -1,204 +1,87
1 1 #include "CosinusProvider.h"
2 2 #include "MockDefs.h"
3 3
4 4 #include <Data/DataProviderParameters.h>
5 #include <Data/ScalarSeries.h>
6 #include <Data/SpectrogramSeries.h>
7 #include <Data/VectorSeries.h>
5 #include <Data/ScalarTimeSerie.h>
6 #include <Data/SpectrogramTimeSerie.h>
7 #include <Data/VectorTimeSerie.h>
8 8
9 9 #include <cmath>
10 10 #include <set>
11 11
12 12 #include <QFuture>
13 13 #include <QThread>
14 14 #include <QtConcurrent/QtConcurrent>
15 15
16 16
17 namespace {
17 namespace
18 {
18 19
19 20 /// Number of bands generated for a spectrogram
20 21 const auto SPECTROGRAM_NUMBER_BANDS = 30;
21 22
22 23 /// Bands for which to generate NaN values for a spectrogram
23 const auto SPECTROGRAM_NAN_BANDS = std::set<int>{1, 3, 10, 20};
24 const auto SPECTROGRAM_NAN_BANDS = std::set<int> { 1, 3, 10, 20 };
24 25
25 26 /// Bands for which to generate zeros for a spectrogram
26 const auto SPECTROGRAM_ZERO_BANDS = std::set<int>{2, 15, 19, 29};
27
28 /// Abstract cosinus type
29 struct ICosinusType {
30 virtual ~ICosinusType() = default;
31 /// @return the number of components generated for the type
32 virtual std::size_t componentCount() const = 0;
33 /// @return the data series created for the type
34 virtual IDataSeries* createDataSeries(std::vector<double> xAxisData,
35 std::vector<double> valuesData) const = 0;
36 /// Generates values (one value per component)
37 /// @param x the x-axis data used to generate values
38 /// @param values the vector in which to insert the generated values
39 /// @param dataIndex the index of insertion of the generated values
40 ///
41 virtual void generateValues(double x, std::vector<double> &values, int dataIndex) const = 0;
42 };
43
44 struct ScalarCosinus : public ICosinusType {
45 std::size_t componentCount() const override { return 1; }
46
47 IDataSeries* createDataSeries(std::vector<double> xAxisData,
48 std::vector<double> valuesData) const override
49 {
50 return new ScalarSeries(std::move(xAxisData), std::move(valuesData),
51 Unit{QStringLiteral("t"), true}, Unit{});
52 }
53
54 void generateValues(double x, std::vector<double> &values, int dataIndex) const override
55 {
56 values[dataIndex] = std::cos(x);
57 }
58 };
59
60 struct SpectrogramCosinus : public ICosinusType {
61 /// Ctor with y-axis
62 explicit SpectrogramCosinus(std::vector<double> yAxisData, Unit yAxisUnit, Unit valuesUnit)
63 : m_YAxisData{std::move(yAxisData)},
64 m_YAxisUnit{std::move(yAxisUnit)},
65 m_ValuesUnit{std::move(valuesUnit)}
66 {
67 }
68
69 std::size_t componentCount() const override { return m_YAxisData.size(); }
70
71 IDataSeries* createDataSeries(std::vector<double> xAxisData,
72 std::vector<double> valuesData) const override
73 {
74 return new SpectrogramSeries(
75 std::move(xAxisData), m_YAxisData, std::move(valuesData),
76 Unit{QStringLiteral("t"), true}, m_YAxisUnit, m_ValuesUnit);
77 }
78
79 void generateValues(double x, std::vector<double> &values, int dataIndex) const override
80 {
81 auto componentCount = this->componentCount();
82 for (int i = 0; i < componentCount; ++i) {
83 auto y = m_YAxisData[i];
84
85 double value;
86
87 // if (SPECTROGRAM_ZERO_BANDS.find(y) != SPECTROGRAM_ZERO_BANDS.end()) {
88 // value = 0.;
89 // }
90 // else if (SPECTROGRAM_NAN_BANDS.find(y) != SPECTROGRAM_NAN_BANDS.end()) {
91 // value = std::numeric_limits<double>::quiet_NaN();
92 // }
93 // else
94 {
95 // Generates value for non NaN/zero bands
96 //auto r = 3 * std::sqrt(x * x + y * y) + 1e-2;
97 //value = 2 * x * (std::cos(r + 2) / r - std::sin(r + 2) / r);
98 value = x + 10*y;
99 }
100
101 values[componentCount * dataIndex + i] = value;
102 }
103 }
104
105 std::vector<double> m_YAxisData;
106 Unit m_YAxisUnit;
107 Unit m_ValuesUnit;
108 };
109
110 struct VectorCosinus : public ICosinusType {
111 std::size_t componentCount() const override { return 3; }
27 const auto SPECTROGRAM_ZERO_BANDS = std::set<int> { 2, 15, 19, 29 };
112 28
113 IDataSeries* createDataSeries(std::vector<double> xAxisData,
114 std::vector<double> valuesData) const override
115 {
116 return new VectorSeries(std::move(xAxisData), std::move(valuesData),
117 Unit{QStringLiteral("t"), true}, Unit{});
118 }
119
120 void generateValues(double x, std::vector<double> &values, int dataIndex) const override
121 {
122 // Generates value for each component: cos(x), cos(x)/2, cos(x)/3
123 auto xValue = std::cos(x);
124 auto componentCount = this->componentCount();
125 for (auto i = 0; i < componentCount; ++i) {
126 values[componentCount * dataIndex + i] = xValue / (i + 1);
127 }
128 }
129 };
130
131 /// Converts string to cosinus type
132 /// @return the cosinus type if the string could be converted, nullptr otherwise
133 std::unique_ptr<ICosinusType> cosinusType(const QString &type) noexcept
134 {
135 if (type.compare(QStringLiteral("scalar"), Qt::CaseInsensitive) == 0) {
136 return std::make_unique<ScalarCosinus>();
137 }
138 else if (type.compare(QStringLiteral("spectrogram"), Qt::CaseInsensitive) == 0) {
139 // Generates default y-axis data for spectrogram [0., 1., 2., ...]
140 std::vector<double> yAxisData(SPECTROGRAM_NUMBER_BANDS);
141 std::iota(yAxisData.begin(), yAxisData.end(), 1.);
142 for (auto & v:yAxisData)
143 {
144 v = std::pow(2,v);
145 }
146 return std::make_unique<SpectrogramCosinus>(std::move(yAxisData), Unit{"eV"},
147 Unit{"eV/(cm^2-s-sr-eV)"});
148 }
149 else if (type.compare(QStringLiteral("vector"), Qt::CaseInsensitive) == 0) {
150 return std::make_unique<VectorCosinus>();
151 }
152 else {
153 return nullptr;
154 }
155 }
156 29
157 30 } // namespace
158 31
159 32 std::shared_ptr<IDataProvider> CosinusProvider::clone() const
160 33 {
161 34 // No copy is made in clone
162 35 return std::make_shared<CosinusProvider>();
163 36 }
164 37
165 IDataSeries *CosinusProvider::_generate(const DateTimeRange &range, const QVariantHash &metaData)
38 TimeSeries::ITimeSerie* CosinusProvider::_generate(
39 const DateTimeRange& range, const QVariantHash& metaData)
166 40 {
167 auto dataIndex = 0;
168
169 41 // Retrieves cosinus type
170 42 auto typeVariant = metaData.value(COSINUS_TYPE_KEY, COSINUS_TYPE_DEFAULT_VALUE);
171 auto type = cosinusType(typeVariant.toString());
172 43 auto freqVariant = metaData.value(COSINUS_FREQUENCY_KEY, COSINUS_FREQUENCY_DEFAULT_VALUE);
44 const auto fs = 200.;
173 45 double freq = freqVariant.toDouble();
174 46 double start = std::ceil(range.m_TStart * freq);
175 47 double end = std::floor(range.m_TEnd * freq);
176 if (end < start) {
48 if (end < start)
49 {
177 50 std::swap(start, end);
178 51 }
179 52 std::size_t dataCount = static_cast<std::size_t>(end - start + 1);
180 std::size_t componentCount = type->componentCount();
181
182 auto xAxisData = std::vector<double>{};
183 xAxisData.resize(dataCount);
184
185 auto valuesData = std::vector<double>{};
186 valuesData.resize(dataCount * componentCount);
187
188 int progress = 0;
189 auto progressEnd = dataCount;
190 for (auto time = start; time <= end; ++time, ++dataIndex)
53 if (typeVariant.toString() == QStringLiteral("scalar"))
191 54 {
192 const auto x = time / freq;
193 xAxisData[dataIndex] = x;
194 // Generates values (depending on the type)
195 type->generateValues(x, valuesData, dataIndex);
55 auto ts = new ScalarTimeSerie(dataCount);
56 std::generate(
57 std::begin(*ts), std::end(*ts), [range, freq, fs, dt = 1. / freq, i = 0.]() mutable {
58 auto t = range.m_TStart + i * dt;
59 i++;
60 return std::pair<double, double> { t, std::cos(2 * 3.14 * freq / fs * t) };
61 });
62 return ts;
196 63 }
197 return type->createDataSeries(std::move(xAxisData), std::move(valuesData));
64 if (typeVariant.toString() == QStringLiteral("vector"))
65 {
66 auto ts = new VectorTimeSerie(dataCount);
67 std::generate(
68 std::begin(*ts), std::end(*ts), [range, freq, fs, dt = 1. / freq, i = 0.]() mutable {
69 auto t = range.m_TStart + i * dt;
70 i++;
71 return std::pair<double, VectorTimeSerie::raw_value_type> { t,
72 { std::cos(2 * 3.14 * freq / fs * t), std::sin(2 * 3.14 * freq / fs * t),
73 std::cos(2 * 3.14 * freq / fs * t) * std::sin(2 * 3.14 * freq / fs * t) } };
74 });
75 return ts;
76 }
77 if (typeVariant.toString() == QStringLiteral("spectrogram"))
78 {
79 return nullptr;
80 }
81 return nullptr;
198 82 }
199 83
200 IDataSeries* CosinusProvider::getData(const DataProviderParameters &parameters)
84 TimeSeries::ITimeSerie* CosinusProvider::getData(const DataProviderParameters& parameters)
201 85 {
202 86 return _generate(parameters.m_Range, parameters.m_Data);
203 87 }
204
@@ -1,85 +1,86
1 1 /*------------------------------------------------------------------------------
2 2 -- This file is a part of the SciQLOP Software
3 3 -- Copyright (C) 2018, Plasma Physics Laboratory - CNRS
4 4 --
5 5 -- This program is free software; you can redistribute it and/or modify
6 6 -- it under the terms of the GNU General Public License as published by
7 7 -- the Free Software Foundation; either version 2 of the License, or
8 8 -- (at your option) any later version.
9 9 --
10 10 -- This program is distributed in the hope that it will be useful,
11 11 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 13 -- GNU General Public License for more details.
14 14 --
15 15 -- You should have received a copy of the GNU General Public License
16 16 -- along with this program; if not, write to the Free Software
17 17 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 18 -------------------------------------------------------------------------------*/
19 19 /*-- Author : Alexis Jeandet
20 20 -- Mail : alexis.jeandet@member.fsf.org
21 21 ----------------------------------------------------------------------------*/
22 #include <string>
23 #include <sstream>
24 22 #include <memory>
23 #include <sstream>
24 #include <string>
25 25
26 #include <pybind11/pybind11.h>
27 #include <pybind11/operators.h>
26 #include <pybind11/chrono.h>
28 27 #include <pybind11/embed.h>
29 28 #include <pybind11/numpy.h>
30 #include <pybind11/chrono.h>
29 #include <pybind11/operators.h>
30 #include <pybind11/pybind11.h>
31 31
32 #include <Common/DateUtils.h>
33 #include <Data/DataSeriesType.h>
34 #include <Data/DateTimeRange.h>
32 35 #include <SqpApplication.h>
33 #include <Variable/VariableController2.h>
34 36 #include <Time/TimeController.h>
35 #include <Data/DateTimeRange.h>
36 #include <Data/DataSeriesType.h>
37 #include <Common/DateUtils.h>
38 #include <Variable/Variable.h>
39 #include <Data/ScalarSeries.h>
40 #include <Data/VectorSeries.h>
37 #include <Variable/VariableController2.h>
41 38
42 #include <MockPlugin.h>
43 39 #include <CosinusProvider.h>
40 #include <MockPlugin.h>
44 41
45 42 #include <QFile>
46 43
47 #include <pywrappers_common.h>
48 44 #include <CoreWrappers.h>
49
45 #include <pywrappers_common.h>
50 46
51 47
52 48 using namespace std::chrono;
53 49 namespace py = pybind11;
54 50
55 51
56
57 PYBIND11_MODULE(pytestmockplugin, m){
52 PYBIND11_MODULE(pytestmockplugin, m)
53 {
58 54
59 55 int argc = 0;
60 char ** argv=nullptr;
56 char** argv = nullptr;
61 57 SqpApplication::setOrganizationName("LPP");
62 58 SqpApplication::setOrganizationDomain("lpp.fr");
63 59 SqpApplication::setApplicationName("SciQLop");
64 60 static SqpApplication app(argc, argv);
65 61
66 62 auto qtmod = py::module::import("sciqlopqt");
67 63 auto sciqlopmod = py::module::import("pysciqlopcore");
68 64
69 65 m.doc() = "";
70 66
71 py::class_<VariableController2>(m, "VariableController2").def_static("createVariable",[](const QString &name,
72 std::shared_ptr<IDataProvider> provider, const DateTimeRange& range){
73 return sqpApp->variableController().createVariable(name, {{"cosinusType", "spectrogram"}, {"cosinusFrequency", "0.1"}}, provider, range);
67 py::class_<VariableController2>(m, "VariableController2")
68 .def_static("createVariable",
69 [](const QString& name, std::shared_ptr<IDataProvider> provider,
70 const DateTimeRange& range) {
71 return sqpApp->variableController().createVariable(name,
72 { { "cosinusType", "spectrogram" }, { "cosinusFrequency", "0.1" } }, provider,
73 range);
74 });
75
76 py::class_<TimeController>(m, "TimeController").def_static("setTime", [](DateTimeRange range) {
77 sqpApp->timeController().setDateTimeRange(range);
74 78 });
75 79
76 py::class_<TimeController>(m,"TimeController")
77 .def_static("setTime", [](DateTimeRange range){sqpApp->timeController().setDateTimeRange(range);});
78
79 80 auto mock_provider = std::make_shared<CosinusProvider>();
80 m.def("mock_provider",[mock_provider](){return mock_provider;}, py::return_value_policy::copy);
81
82 py::class_<CosinusProvider, std::shared_ptr<CosinusProvider>, IDataProvider>(m, "CosinusProvider");
81 m.def("mock_provider", [mock_provider]() { return mock_provider; },
82 py::return_value_policy::copy);
83 83
84 py::class_<CosinusProvider, std::shared_ptr<CosinusProvider>, IDataProvider>(
85 m, "CosinusProvider");
84 86 }
85
General Comments 0
You need to be logged in to leave comments. Login now