Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ac61b3f

Browse files
ChristosTBenno Evers
authored and
Benno Evers
committed
replace python lists with numpy arrays and avoid copy of input data
1 parent 0bfb012 commit ac61b3f

File tree

1 file changed

+78
-74
lines changed

1 file changed

+78
-74
lines changed

matplotlibcpp.h

+78-74
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <vector>
44
#include <map>
55
#include <numeric>
6+
#include <algorithm>
67
#include <stdexcept>
78
#include <iostream>
89

@@ -23,6 +24,8 @@
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

2730
namespace 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

Comments
 (0)