33#include < vector>
44#include < map>
55#include < numeric>
6+ #include < algorithm>
67#include < stdexcept>
78#include < iostream>
89
2324#define PyString_FromString PyUnicode_FromString
2425#endif
2526
27+ #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
28+ #include < numpy/arrayobject.h>
2629
2730namespace matplotlibcpp {
2831
@@ -72,6 +75,8 @@ namespace matplotlibcpp {
7275 Py_SetProgramName (name);
7376 Py_Initialize ();
7477
78+ import_array (); // initialize numpy C-API
79+
7580 PyObject* pyplotname = PyString_FromString (" matplotlib.pyplot" );
7681 PyObject* pylabname = PyString_FromString (" pylab" );
7782 if (!pyplotname || !pylabname) { throw std::runtime_error (" couldnt create string" ); }
@@ -177,25 +182,52 @@ namespace matplotlibcpp {
177182
178183 return res;
179184 }
185+ // Type selector for numpy array conversion
186+ template <typename T> struct select_npy_type { const static NPY_TYPES type = NPY_NOTYPE; }; // Default
187+ template <> struct select_npy_type <double > { const static NPY_TYPES type = NPY_DOUBLE; };
188+ template <> struct select_npy_type <float > { const static NPY_TYPES type = NPY_FLOAT; };
189+ template <> struct select_npy_type <bool > { const static NPY_TYPES type = NPY_BOOL; };
190+ template <> struct select_npy_type <std::int8_t > { const static NPY_TYPES type = NPY_INT8; };
191+ template <> struct select_npy_type <std::int16_t > { const static NPY_TYPES type = NPY_SHORT; };
192+ template <> struct select_npy_type <std::int32_t > { const static NPY_TYPES type = NPY_INT; };
193+ template <> struct select_npy_type <std::int64_t > { const static NPY_TYPES type = NPY_INT64; };
194+ template <> struct select_npy_type <std::uint8_t > { const static NPY_TYPES type = NPY_UINT8; };
195+ template <> struct select_npy_type <std::uint16_t > { const static NPY_TYPES type = NPY_USHORT; };
196+ template <> struct select_npy_type <std::uint32_t > { const static NPY_TYPES type = NPY_ULONG; };
197+ template <> struct select_npy_type <std::uint64_t > { const static NPY_TYPES type = NPY_UINT64; };
198+
199+ template <typename Numeric>
200+ PyObject* get_array (const std::vector<Numeric>& v)
201+ {
202+ detail::_interpreter::get (); // interpreter needs to be initialized for the numpy commands to work
203+ NPY_TYPES type = select_npy_type<Numeric>::type;
204+ if (type == NPY_NOTYPE)
205+ {
206+ std::vector<double > vd (v.size ());
207+ npy_intp vsize = v.size ();
208+ std::copy (v.begin (),v.end (),vd.begin ());
209+ PyObject* varray = PyArray_SimpleNewFromData (1 , &vsize, NPY_DOUBLE, (void *)(vd.data ()));
210+ return varray;
211+ }
212+
213+ npy_intp vsize = v.size ();
214+ PyObject* varray = PyArray_SimpleNewFromData (1 , &vsize, type, (void *)(v.data ()));
215+ return varray;
216+ }
180217
181218 template <typename Numeric>
182219 bool plot (const std::vector<Numeric> &x, const std::vector<Numeric> &y, const std::map<std::string, std::string>& keywords)
183220 {
184221 assert (x.size () == y.size ());
185222
186- // using python lists
187- PyObject* xlist = PyList_New (x.size ());
188- PyObject* ylist = PyList_New (y.size ());
189-
190- for (size_t i = 0 ; i < x.size (); ++i) {
191- PyList_SetItem (xlist, i, PyFloat_FromDouble (x.at (i)));
192- PyList_SetItem (ylist, i, PyFloat_FromDouble (y.at (i)));
193- }
223+ // using numpy arrays
224+ PyObject* xarray = get_array (x);
225+ PyObject* yarray = get_array (y);
194226
195227 // construct positional args
196228 PyObject* args = PyTuple_New (2 );
197- PyTuple_SetItem (args, 0 , xlist );
198- PyTuple_SetItem (args, 1 , ylist );
229+ PyTuple_SetItem (args, 0 , xarray );
230+ PyTuple_SetItem (args, 1 , yarray );
199231
200232 // construct keyword args
201233 PyObject* kwargs = PyDict_New ();
@@ -219,22 +251,16 @@ namespace matplotlibcpp {
219251 assert (x.size () == y1.size ());
220252 assert (x.size () == y2.size ());
221253
222- // using python lists
223- PyObject* xlist = PyList_New (x.size ());
224- PyObject* y1list = PyList_New (y1.size ());
225- PyObject* y2list = PyList_New (y2.size ());
226-
227- for (size_t i = 0 ; i < x.size (); ++i) {
228- PyList_SetItem (xlist, i, PyFloat_FromDouble (x.at (i)));
229- PyList_SetItem (y1list, i, PyFloat_FromDouble (y1.at (i)));
230- PyList_SetItem (y2list, i, PyFloat_FromDouble (y2.at (i)));
231- }
254+ // using numpy arrays
255+ PyObject* xarray = get_array (x);
256+ PyObject* y1array = get_array (y1);
257+ PyObject* y2array = get_array (y2);
232258
233259 // construct positional args
234260 PyObject* args = PyTuple_New (3 );
235- PyTuple_SetItem (args, 0 , xlist );
236- PyTuple_SetItem (args, 1 , y1list );
237- PyTuple_SetItem (args, 2 , y2list );
261+ PyTuple_SetItem (args, 0 , xarray );
262+ PyTuple_SetItem (args, 1 , y1array );
263+ PyTuple_SetItem (args, 2 , y2array );
238264
239265 // construct keyword args
240266 PyObject* kwargs = PyDict_New ();
@@ -255,20 +281,18 @@ namespace matplotlibcpp {
255281 template < typename Numeric>
256282 bool hist (const std::vector<Numeric>& y, long bins=10 ,std::string color=" b" , double alpha=1.0 )
257283 {
258- PyObject* ylist = PyList_New (y.size ());
259-
284+
285+ PyObject* yarray = get_array (y);
286+
260287 PyObject* kwargs = PyDict_New ();
261288 PyDict_SetItemString (kwargs, " bins" , PyLong_FromLong (bins));
262289 PyDict_SetItemString (kwargs, " color" , PyString_FromString (color.c_str ()));
263290 PyDict_SetItemString (kwargs, " alpha" , PyFloat_FromDouble (alpha));
264291
265- for (size_t i = 0 ; i < y.size (); ++i) {
266- PyList_SetItem (ylist, i, PyFloat_FromDouble (y.at (i)));
267- }
268292
269293 PyObject* plot_args = PyTuple_New (1 );
270294
271- PyTuple_SetItem (plot_args, 0 , ylist );
295+ PyTuple_SetItem (plot_args, 0 , yarray );
272296
273297
274298 PyObject* res = PyObject_Call (detail::_interpreter::get ().s_python_function_hist , plot_args, kwargs);
@@ -284,19 +308,17 @@ namespace matplotlibcpp {
284308 template < typename Numeric>
285309 bool named_hist (std::string label,const std::vector<Numeric>& y, long bins=10 , std::string color=" b" , double alpha=1.0 )
286310 {
287- PyObject* ylist = PyList_New (y.size ());
311+ PyObject* yarray = get_array (y);
312+
288313 PyObject* kwargs = PyDict_New ();
289314 PyDict_SetItemString (kwargs, " label" , PyString_FromString (label.c_str ()));
290315 PyDict_SetItemString (kwargs, " bins" , PyLong_FromLong (bins));
291- PyDict_SetItemString (kwargs, " color" , PyString_FromString (color.c_str ()));
316+ PyDict_SetItemString (kwargs, " color" , PyString_FromString (color.c_str ()));
292317 PyDict_SetItemString (kwargs, " alpha" , PyFloat_FromDouble (alpha));
293-
294- for (size_t i = 0 ; i < y.size (); ++i) {
295- PyList_SetItem (ylist, i, PyFloat_FromDouble (y.at (i)));
296- }
318+
297319
298320 PyObject* plot_args = PyTuple_New (1 );
299- PyTuple_SetItem (plot_args, 0 , ylist );
321+ PyTuple_SetItem (plot_args, 0 , yarray );
300322
301323 PyObject* res = PyObject_Call (detail::_interpreter::get ().s_python_function_hist , plot_args, kwargs);
302324
@@ -312,18 +334,14 @@ namespace matplotlibcpp {
312334 {
313335 assert (x.size () == y.size ());
314336
315- PyObject* xlist = PyList_New (x.size ());
316- PyObject* ylist = PyList_New (y.size ());
317- PyObject* pystring = PyString_FromString (s.c_str ());
337+ PyObject* xarray = get_array (x);
338+ PyObject* yarray = get_array (y);
318339
319- for (size_t i = 0 ; i < x.size (); ++i) {
320- PyList_SetItem (xlist, i, PyFloat_FromDouble (x.at (i)));
321- PyList_SetItem (ylist, i, PyFloat_FromDouble (y.at (i)));
322- }
340+ PyObject* pystring = PyString_FromString (s.c_str ());
323341
324342 PyObject* plot_args = PyTuple_New (3 );
325- PyTuple_SetItem (plot_args, 0 , xlist );
326- PyTuple_SetItem (plot_args, 1 , ylist );
343+ PyTuple_SetItem (plot_args, 0 , xarray );
344+ PyTuple_SetItem (plot_args, 1 , yarray );
327345 PyTuple_SetItem (plot_args, 2 , pystring);
328346
329347 PyObject* res = PyObject_CallObject (detail::_interpreter::get ().s_python_function_plot , plot_args);
@@ -339,26 +357,19 @@ namespace matplotlibcpp {
339357 {
340358 assert (x.size () == y.size ());
341359
342- PyObject *kwargs = PyDict_New ();
343- PyObject *xlist = PyList_New (x.size ());
344- PyObject *ylist = PyList_New (y.size ());
345- PyObject *yerrlist = PyList_New (yerr.size ());
360+ PyObject* xarray = get_array (x);
361+ PyObject* yarray = get_array (y);
362+ PyObject* yerrarray = get_array (yerr);
346363
347- for (size_t i = 0 ; i < yerr.size (); ++i)
348- PyList_SetItem (yerrlist, i, PyFloat_FromDouble (yerr.at (i)));
364+ PyObject *kwargs = PyDict_New ();
349365
350- PyDict_SetItemString (kwargs, " yerr" , yerrlist );
366+ PyDict_SetItemString (kwargs, " yerr" , yerrarray );
351367
352368 PyObject *pystring = PyString_FromString (s.c_str ());
353369
354- for (size_t i = 0 ; i < x.size (); ++i) {
355- PyList_SetItem (xlist, i, PyFloat_FromDouble (x.at (i)));
356- PyList_SetItem (ylist, i, PyFloat_FromDouble (y.at (i)));
357- }
358-
359370 PyObject *plot_args = PyTuple_New (2 );
360- PyTuple_SetItem (plot_args, 0 , xlist );
361- PyTuple_SetItem (plot_args, 1 , ylist );
371+ PyTuple_SetItem (plot_args, 0 , xarray );
372+ PyTuple_SetItem (plot_args, 1 , yarray );
362373
363374 PyObject *res = PyObject_Call (detail::_interpreter::get ().s_python_function_errorbar , plot_args, kwargs);
364375
@@ -379,16 +390,13 @@ namespace matplotlibcpp {
379390 PyObject* kwargs = PyDict_New ();
380391 PyDict_SetItemString (kwargs, " label" , PyString_FromString (name.c_str ()));
381392
382- PyObject* ylist = PyList_New (y.size ());
383- PyObject* pystring = PyString_FromString (format.c_str ());
393+ PyObject* yarray = get_array (y);
384394
385- for (size_t i = 0 ; i < y.size (); ++i) {
386- PyList_SetItem (ylist, i, PyFloat_FromDouble (y.at (i)));
387- }
395+ PyObject* pystring = PyString_FromString (format.c_str ());
388396
389397 PyObject* plot_args = PyTuple_New (2 );
390398
391- PyTuple_SetItem (plot_args, 0 , ylist );
399+ PyTuple_SetItem (plot_args, 0 , yarray );
392400 PyTuple_SetItem (plot_args, 1 , pystring);
393401
394402 PyObject* res = PyObject_Call (detail::_interpreter::get ().s_python_function_plot , plot_args, kwargs);
@@ -406,18 +414,14 @@ namespace matplotlibcpp {
406414 PyObject* kwargs = PyDict_New ();
407415 PyDict_SetItemString (kwargs, " label" , PyString_FromString (name.c_str ()));
408416
409- PyObject* xlist = PyList_New (x.size ());
410- PyObject* ylist = PyList_New (y.size ());
411- PyObject* pystring = PyString_FromString (format.c_str ());
417+ PyObject* xarray = get_array (x);
418+ PyObject* yarray = get_array (y);
412419
413- for (size_t i = 0 ; i < x.size (); ++i) {
414- PyList_SetItem (xlist, i, PyFloat_FromDouble (x.at (i)));
415- PyList_SetItem (ylist, i, PyFloat_FromDouble (y.at (i)));
416- }
420+ PyObject* pystring = PyString_FromString (format.c_str ());
417421
418422 PyObject* plot_args = PyTuple_New (3 );
419- PyTuple_SetItem (plot_args, 0 , xlist );
420- PyTuple_SetItem (plot_args, 1 , ylist );
423+ PyTuple_SetItem (plot_args, 0 , xarray );
424+ PyTuple_SetItem (plot_args, 1 , yarray );
421425 PyTuple_SetItem (plot_args, 2 , pystring);
422426
423427 PyObject* res = PyObject_Call (detail::_interpreter::get ().s_python_function_plot , plot_args, kwargs);
0 commit comments