1 // Copyright (C) 2010-2019 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Adrien BRUNETON
24 #define PY_ARRAY_UNIQUE_SYMBOL CURVEPLOT_ARRAY_API // see initializeCurvePlot()
25 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
26 #include <numpy/ndarraytypes.h>
27 #include <numpy/ndarrayobject.h>
28 #include <PyInterp_Utils.h> // GUI
30 #include "CurvePlot.hxx"
31 #include "CurvePlot_Exception.hxx"
35 PyObject * strToPyUnicode(std::string s)
37 return PyUnicode_DecodeUTF8(s.c_str(), s.size(), (char*)"strict");
40 void HandleAndPrintPyError(std::string msg)
45 throw CURVEPLOT::Exception(msg);
53 * To be called before doing anything
55 void InitializeCurvePlot()
58 // TODO: discuss where the below should really happen:
59 // doc: http://docs.scipy.org/doc/numpy/reference/c-api.array.html#importing-the-api
60 import_array(); // a macro really!
63 class ColumnVector::Internal
66 Internal() : _npArray(0) {}
69 PyArrayObject * _npArray;
72 ColumnVector::ColumnVector()
74 _impl = new Internal();
77 ColumnVector::~ColumnVector()
82 int ColumnVector::size() const
88 int ndim = PyArray_NDIM(_impl->_npArray);
90 throw Exception("ColumnVector::size() : wrong number of dimensions for internal array!!");
91 npy_intp * dims = PyArray_DIMS(_impl->_npArray);
96 ColumnVector ColumnVector::BuildFromCMemory(double * data, int size)
101 npy_intp dims[1] = {size};
105 PyObject * obj = PyArray_SimpleNewFromData(1,dims,NPY_DOUBLE, data);
106 PyArrayObject * aobj = (PyArrayObject * )obj;
108 // Make Numpy responsible of the memory of the array (the memory will be freed
109 // as soon as the array is released in NumPy)
110 PyArray_ENABLEFLAGS(aobj, NPY_ARRAY_OWNDATA);
112 ret._impl->_npArray = aobj;
117 ColumnVector ColumnVector::BuildFromStdVector(const std::vector<double> & vec)
123 double * c_mem = (double *)malloc(sizeof(double) * vec.size());
125 throw Exception("ColumnVector::BuildFromStdVector() : memory allocation error!");
126 const double * data = &vec.front();
127 std::copy(data, data+vec.size(), c_mem);
128 npy_intp dims[1] = {(intptr_t) vec.size()};
132 PyObject * obj = PyArray_SimpleNewFromData(1,dims,NPY_DOUBLE, c_mem);
133 PyArrayObject * aobj = (PyArrayObject * )obj;
135 // Make Numpy responsible of the memory of the array (the memory will be freed
136 // as soon as the array is released in NumPy)
137 PyArray_ENABLEFLAGS(aobj, NPY_ARRAY_OWNDATA);
139 ret._impl->_npArray = aobj;
144 std::string ColumnVector::toStdString() const
146 std::string ret_str = "(None)";
147 if (!_impl->_npArray)
153 PyObject_CallMethod((PyObject *)_impl->_npArray, (char *)"__str__", NULL)
155 // Now extract the returned string
156 if(!PyString_Check(ret_py))
157 throw Exception("CurvePlot::toStdString(): Unexpected returned type!");
158 ret_str = std::string(PyString_AsString(ret_py));
163 void ColumnVector::createPythonVar(std::string varName) const
165 PyObject* main_module = PyImport_AddModule((char*)"__main__");
166 PyObject* global_dict = PyModule_GetDict(main_module);
167 PyDict_SetItemString(global_dict, varName.c_str(), (PyObject *)_impl->_npArray);
170 void ColumnVector::cleanPythonVar(std::string varName) const
172 // Could be a static method really ...
174 std::string s = std::string("del ") + varName;
175 const char * cmd = s.c_str();
176 PyRun_SimpleString(cmd);
179 CurvePlot * CurvePlot::_instance = NULL;
181 class CurvePlot::Internal
184 Internal() : _controller(0) {}
185 ///! Plot2d controller from Python:
186 PyObject * _controller;
189 CurvePlot::CurvePlot(bool test_mode)
191 // TODO: do use an intermediate variable '__cont', but use directly Py***CallMethod()
192 _impl = new Internal();
197 code = std::string("import curveplot; from SalomePyQt_MockUp import SalomePyQt;") +
198 std::string("__cont=curveplot.PlotController.GetInstance(sgPyQt=SalomePyQt())");
200 code = std::string("import curveplot;")+
201 std::string("__cont=curveplot.PlotController.GetInstance()");
203 int ret = PyRun_SimpleString(const_cast<char*>(code.c_str()));
205 throw Exception("CurvePlot::CurvePlot(): Unable to load curveplot Python module!");
207 // Now get the reference to __engine and save the pointer.
208 // All the calls below returns *borrowed* references
209 PyObject* main_module = PyImport_AddModule((char*)"__main__");
210 PyObject* global_dict = PyModule_GetDict(main_module);
211 PyObject* tmp = PyDict_GetItemString(global_dict, "__cont");
213 _impl->_controller = tmp;
214 Py_INCREF(_impl->_controller);
215 PyRun_SimpleString(const_cast<char*>("del __cont"));
219 CurvePlot::~CurvePlot()
221 if(_impl->_controller != NULL)
224 Py_XDECREF(_impl->_controller);
229 CurvePlot * CurvePlot::GetInstance(bool test_mode)
232 _instance = new CurvePlot(test_mode);
236 void CurvePlot::ToggleCurveBrowser(bool with_curve_browser)
239 throw Exception("CurvePlot::ToggleCurveBrowser() must be invoked before anything else!");
242 std::string bool_s = with_curve_browser ? "True" : "False";
243 std::string cod = std::string("import curveplot; curveplot.PlotController.WITH_CURVE_BROWSER=") + bool_s;
244 PyRun_SimpleString(const_cast<char *>(cod.c_str()));
245 HandleAndPrintPyError("CurvePlot::ToggleCurveBrowser(): Unable to toggle Curve Browser!");
248 PlotID CurvePlot::AddCurve(const ColumnVector & x, const ColumnVector & y,
249 PlotID & plot_set_id,
250 std::string curve_label/*=""*/, std::string x_label/*=""*/, std::string y_label/*=""*/,
251 bool append/*=true*/)
254 PyObject * cont = GetInstance()->_impl->_controller;
256 PyObject * xx = (PyObject *)x._impl->_npArray;
257 PyObject * yy = (PyObject *)y._impl->_npArray;
260 PyObject_CallMethod(cont, (char *)"AddCurve", (char *)"OOOOOi", xx, yy,
261 strToPyUnicode(curve_label), strToPyUnicode(x_label), strToPyUnicode(y_label),
264 HandleAndPrintPyError("CurvePlot::AddCurve(): unexpected error!");
265 // Now extract curve_id and plot_set_id from the returned tuple:
266 if(!PyTuple_Check(ret))
267 throw Exception("CurvePlot::AddCurve(): Unexpected returned type!");
268 PyObject * o1 = PyTuple_GetItem(ret, 0);
269 if (!PyInt_Check(o1))
270 throw Exception("CurvePlot::AddCurve(): Unexpected returned type!");
271 PlotID curveId = PyInt_AsLong(o1);
272 PyObject * o2 = PyTuple_GetItem(ret, 1);
273 if (!PyInt_Check(o2))
274 throw Exception("CurvePlot::AddCurve(): Unexpected returned type!");
275 plot_set_id = PyInt_AsLong(o2);
279 PlotID CurvePlot::AddPlotSet(std::string title/*=""*/)
282 PyObject * cont = GetInstance()->_impl->_controller;
285 PyObject_CallMethod(cont, (char *)"AddPlotSet", (char *)"O", strToPyUnicode(title))
287 HandleAndPrintPyError("CurvePlot::AddPlotSet(): unexpected error!");
288 return PyLong_AsLong(ret);
291 PlotID CurvePlot::DeleteCurve(PlotID curve_id/*=-1*/)
294 PyObject * cont = GetInstance()->_impl->_controller;
297 PyObject_CallMethod(cont, (char *)"DeleteCurve", (char *)"i", curve_id)
299 HandleAndPrintPyError("CurvePlot::DeleteCurve(): unexpected error!");
300 return PyLong_AsLong(ret);
303 PlotID CurvePlot::DeletePlotSet(PlotID plot_set_id/*=-1*/)
306 PyObject * cont = GetInstance()->_impl->_controller;
309 PyObject_CallMethod(cont, (char *)"DeletePlotSet", (char *)"i", plot_set_id)
311 HandleAndPrintPyError("CurvePlot::DeletePlotSet(): unexpected error!");
312 return PyLong_AsLong(ret);
315 PlotID CurvePlot::ClearPlotSet(PlotID plot_set_id/*=-1*/)
318 PyObject * cont = GetInstance()->_impl->_controller;
321 PyObject_CallMethod(cont, (char *)"ClearPlotSet", (char *)"i", plot_set_id)
323 HandleAndPrintPyError("CurvePlot::ClearPlotSet(): unexpected error!");
324 return PyLong_AsLong(ret);
327 bool CurvePlot::SetXLabel(std::string x_label, PlotID plot_set_id/*=-1*/)
330 PyObject * cont = GetInstance()->_impl->_controller;
333 PyObject_CallMethod(cont, (char *)"SetXLabel", (char *)"Oi", strToPyUnicode(x_label), plot_set_id)
335 HandleAndPrintPyError("CurvePlot::SetXLabel(): unexpected error!");
336 return ((PyObject *)ret == Py_True);
339 bool CurvePlot::SetYLabel(std::string y_label, PlotID plot_set_id/*=-1*/)
342 PyObject * cont = GetInstance()->_impl->_controller;
345 PyObject_CallMethod(cont, (char *)"SetYLabel", (char *)"Oi", strToPyUnicode(y_label), plot_set_id)
347 HandleAndPrintPyError("CurvePlot::SetYLabel(): unexpected error!");
348 return ((PyObject *)ret == Py_True);
351 bool CurvePlot::SetPlotSetTitle(std::string title, PlotID plot_set_id/*=-1*/)
354 PyObject * cont = GetInstance()->_impl->_controller;
357 PyObject_CallMethod(cont, (char *)"SetPlotSetTitle", (char *)"Oi", strToPyUnicode(title), plot_set_id));
358 HandleAndPrintPyError("CurvePlot::SetPlotSetTitle(): unexpected error!");
359 return ((PyObject *)ret == Py_True);
362 PlotID CurvePlot::GetPlotSetID(PlotID curve_id)
365 PyObject * cont = GetInstance()->_impl->_controller;
368 PyObject_CallMethod(cont, (char *)"GetPlotSetID", (char *)"i", curve_id)
370 HandleAndPrintPyError("CurvePlot::GetPlotSetID(): unexpected error!");
371 return PyLong_AsLong(ret);
374 PlotID CurvePlot::GetPlotSetIDByName(std::string name)
377 PyObject * cont = GetInstance()->_impl->_controller;
380 PyObject_CallMethod(cont, (char *)"GetPlotSetIDByName", (char *)"O", strToPyUnicode(name))
382 HandleAndPrintPyError("CurvePlot::GetPlotSetIDByName(): unexpected error!");
383 return PyLong_AsLong(ret);
386 PlotID CurvePlot::GetCurrentCurveID()
389 PyObject * cont = GetInstance()->_impl->_controller;
392 PyObject_CallMethod(cont, (char *)"GetCurrentCurveID", (char *)"")
394 HandleAndPrintPyError("CurvePlot::GetCurrentCurveID(): unexpected error!");
395 return PyLong_AsLong(ret);
398 PlotID CurvePlot::GetCurrentPlotSetID()
401 PyObject * cont = GetInstance()->_impl->_controller;
404 PyObject_CallMethod(cont, (char *)"GetCurrentPlotSetID", (char *)"")
406 HandleAndPrintPyError("CurvePlot::GetCurrentPlotSetID(): unexpected error!");
407 return PyLong_AsLong(ret);
410 bool CurvePlot::IsValidPlotSetID(PlotID plot_set_id)
413 PyObject * cont = GetInstance()->_impl->_controller;
416 PyObject_CallMethod(cont, (char *)"IsValidPlotSetID", (char *)"i", plot_set_id));
417 HandleAndPrintPyError("CurvePlot::IsValidPlotSetID(): unexpected error!");
418 return ((PyObject *)ret == Py_True);
421 int CurvePlot::GetSalomeViewID(PlotID plot_set_id)
424 PyObject * cont = GetInstance()->_impl->_controller;
427 PyObject_CallMethod(cont, (char *)"GetSalomeViewID", (char *)"i", plot_set_id));
428 HandleAndPrintPyError("CurvePlot::GetSalomeViewID(): unexpected error!");
429 return PyLong_AsLong(ret);
432 void CurvePlot::OnSalomeViewTryClose(int salome_view_id)
435 PyObject * cont = GetInstance()->_impl->_controller;
438 PyObject_CallMethod(cont, (char *)"OnSalomeViewTryClose", (char *)"i", salome_view_id));
439 HandleAndPrintPyError("CurvePlot::OnSalomeViewTryClose(): unexpected error!");