3
3
#include < vector>
4
4
#include < map>
5
5
#include < numeric>
6
+ #include < algorithm>
6
7
#include < stdexcept>
7
8
#include < iostream>
8
9
23
24
#define PyString_FromString PyUnicode_FromString
24
25
#endif
25
26
27
+ #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
28
+ #include < numpy/arrayobject.h>
26
29
27
30
namespace matplotlibcpp {
28
31
@@ -72,6 +75,8 @@ namespace matplotlibcpp {
72
75
Py_SetProgramName (name);
73
76
Py_Initialize ();
74
77
78
+ import_array (); // initialize numpy C-API
79
+
75
80
PyObject* pyplotname = PyString_FromString (" matplotlib.pyplot" );
76
81
PyObject* pylabname = PyString_FromString (" pylab" );
77
82
if (!pyplotname || !pylabname) { throw std::runtime_error (" couldnt create string" ); }
@@ -177,25 +182,52 @@ namespace matplotlibcpp {
177
182
178
183
return res;
179
184
}
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
+ }
180
217
181
218
template <typename Numeric>
182
219
bool plot (const std::vector<Numeric> &x, const std::vector<Numeric> &y, const std::map<std::string, std::string>& keywords)
183
220
{
184
221
assert (x.size () == y.size ());
185
222
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);
194
226
195
227
// construct positional args
196
228
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 );
199
231
200
232
// construct keyword args
201
233
PyObject* kwargs = PyDict_New ();
@@ -219,22 +251,16 @@ namespace matplotlibcpp {
219
251
assert (x.size () == y1 .size ());
220
252
assert (x.size () == y2.size ());
221
253
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);
232
258
233
259
// construct positional args
234
260
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 );
238
264
239
265
// construct keyword args
240
266
PyObject* kwargs = PyDict_New ();
@@ -255,20 +281,18 @@ namespace matplotlibcpp {
255
281
template < typename Numeric>
256
282
bool hist (const std::vector<Numeric>& y, long bins=10 ,std::string color=" b" , double alpha=1.0 )
257
283
{
258
- PyObject* ylist = PyList_New (y.size ());
259
-
284
+
285
+ PyObject* yarray = get_array (y);
286
+
260
287
PyObject* kwargs = PyDict_New ();
261
288
PyDict_SetItemString (kwargs, " bins" , PyLong_FromLong (bins));
262
289
PyDict_SetItemString (kwargs, " color" , PyString_FromString (color.c_str ()));
263
290
PyDict_SetItemString (kwargs, " alpha" , PyFloat_FromDouble (alpha));
264
291
265
- for (size_t i = 0 ; i < y.size (); ++i) {
266
- PyList_SetItem (ylist, i, PyFloat_FromDouble (y.at (i)));
267
- }
268
292
269
293
PyObject* plot_args = PyTuple_New (1 );
270
294
271
- PyTuple_SetItem (plot_args, 0 , ylist );
295
+ PyTuple_SetItem (plot_args, 0 , yarray );
272
296
273
297
274
298
PyObject* res = PyObject_Call (detail::_interpreter::get ().s_python_function_hist , plot_args, kwargs);
@@ -284,19 +308,17 @@ namespace matplotlibcpp {
284
308
template < typename Numeric>
285
309
bool named_hist (std::string label,const std::vector<Numeric>& y, long bins=10 , std::string color=" b" , double alpha=1.0 )
286
310
{
287
- PyObject* ylist = PyList_New (y.size ());
311
+ PyObject* yarray = get_array (y);
312
+
288
313
PyObject* kwargs = PyDict_New ();
289
314
PyDict_SetItemString (kwargs, " label" , PyString_FromString (label.c_str ()));
290
315
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 ()));
292
317
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
+
297
319
298
320
PyObject* plot_args = PyTuple_New (1 );
299
- PyTuple_SetItem (plot_args, 0 , ylist );
321
+ PyTuple_SetItem (plot_args, 0 , yarray );
300
322
301
323
PyObject* res = PyObject_Call (detail::_interpreter::get ().s_python_function_hist , plot_args, kwargs);
302
324
@@ -312,18 +334,14 @@ namespace matplotlibcpp {
312
334
{
313
335
assert (x.size () == y.size ());
314
336
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);
318
339
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 ());
323
341
324
342
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 );
327
345
PyTuple_SetItem (plot_args, 2 , pystring);
328
346
329
347
PyObject* res = PyObject_CallObject (detail::_interpreter::get ().s_python_function_plot , plot_args);
@@ -339,26 +357,19 @@ namespace matplotlibcpp {
339
357
{
340
358
assert (x.size () == y.size ());
341
359
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);
346
363
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 ();
349
365
350
- PyDict_SetItemString (kwargs, " yerr" , yerrlist );
366
+ PyDict_SetItemString (kwargs, " yerr" , yerrarray );
351
367
352
368
PyObject *pystring = PyString_FromString (s.c_str ());
353
369
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
-
359
370
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 );
362
373
363
374
PyObject *res = PyObject_Call (detail::_interpreter::get ().s_python_function_errorbar , plot_args, kwargs);
364
375
@@ -379,16 +390,13 @@ namespace matplotlibcpp {
379
390
PyObject* kwargs = PyDict_New ();
380
391
PyDict_SetItemString (kwargs, " label" , PyString_FromString (name.c_str ()));
381
392
382
- PyObject* ylist = PyList_New (y.size ());
383
- PyObject* pystring = PyString_FromString (format.c_str ());
393
+ PyObject* yarray = get_array (y);
384
394
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 ());
388
396
389
397
PyObject* plot_args = PyTuple_New (2 );
390
398
391
- PyTuple_SetItem (plot_args, 0 , ylist );
399
+ PyTuple_SetItem (plot_args, 0 , yarray );
392
400
PyTuple_SetItem (plot_args, 1 , pystring);
393
401
394
402
PyObject* res = PyObject_Call (detail::_interpreter::get ().s_python_function_plot , plot_args, kwargs);
@@ -406,18 +414,14 @@ namespace matplotlibcpp {
406
414
PyObject* kwargs = PyDict_New ();
407
415
PyDict_SetItemString (kwargs, " label" , PyString_FromString (name.c_str ()));
408
416
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);
412
419
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 ());
417
421
418
422
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 );
421
425
PyTuple_SetItem (plot_args, 2 , pystring);
422
426
423
427
PyObject* res = PyObject_Call (detail::_interpreter::get ().s_python_function_plot , plot_args, kwargs);
0 commit comments