IgANet
IGAnets - Isogeometric Analysis Networks
Loading...
Searching...
No Matches
matplotlibcpp.h
Go to the documentation of this file.
1#pragma once
2
3// Python headers must be included before any system headers, since
4// they define _POSIX_C_SOURCE
5#include <Python.h>
6
7#include <algorithm>
8#include <array>
9#include <cstdint> // <cstdint> requires c++11 support
10#include <functional>
11#include <iostream>
12#include <map>
13#include <numeric>
14#include <stdexcept>
15#include <string> // std::stod
16#include <vector>
17
18#ifndef WITHOUT_NUMPY
19#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
20#include <numpy/arrayobject.h>
21
22#ifdef WITH_OPENCV
23#include <opencv2/opencv.hpp>
24#endif // WITH_OPENCV
25
26/*
27 * A bunch of constants were removed in OpenCV 4 in favour of enum classes, so
28 * define the ones we need here.
29 */
30#if CV_MAJOR_VERSION > 3
31#define CV_BGR2RGB cv::COLOR_BGR2RGB
32#define CV_BGRA2RGBA cv::COLOR_BGRA2RGBA
33#endif
34#endif // WITHOUT_NUMPY
35
36#if PY_MAJOR_VERSION >= 3
37#define PyString_FromString PyUnicode_FromString
38#define PyInt_FromLong PyLong_FromLong
39#define PyString_FromString PyUnicode_FromString
40#endif
41
42namespace matplotlibcpp {
43namespace detail {
44
45static std::string s_backend;
46
105
106 /* For now, _interpreter is implemented as a singleton since its currently not
107 possible to have multiple independent embedded python interpreters without
108 patching the python source code or starting a separate process for each.
109 [1] Furthermore, many python objects expect that they are destructed in the
110 same thread as they were constructed. [2] So for advanced usage, a `kill()`
111 function is provided so that library users can manually ensure that the
112 interpreter is constructed and destroyed within the same thread.
113
114 1:
115 http://bytes.com/topic/python/answers/793370-multiple-independent-python-interpreters-c-c-program
116 2: https://github.com/lava/matplotlib-cpp/pull/202#issue-436220256
117 */
118
119 static _interpreter &get() { return interkeeper(false); }
120
121 static _interpreter &kill() { return interkeeper(true); }
122
123 // Stores the actual singleton object referenced by `get()` and `kill()`.
124 static _interpreter &interkeeper(bool should_kill) {
125 static _interpreter ctx;
126 if (should_kill)
127 ctx.~_interpreter();
128 return ctx;
129 }
130
131 PyObject *safe_import(PyObject *module, std::string fname) {
132 PyObject *fn = PyObject_GetAttrString(module, fname.c_str());
133
134 if (!fn)
135 throw std::runtime_error(
136 std::string("Couldn't find required function: ") + fname);
137
138 if (!PyFunction_Check(fn))
139 throw std::runtime_error(
140 fname + std::string(" is unexpectedly not a PyFunction."));
141
142 return fn;
143 }
144
145private:
146#ifndef WITHOUT_NUMPY
147#if PY_MAJOR_VERSION >= 3
148
149 void *import_numpy() {
150 import_array(); // initialize C-API
151 return NULL;
152 }
153
154#else
155
157 import_array(); // initialize C-API
158 }
159
160#endif
161#endif
162
164
165 // optional but recommended
166#if PY_MAJOR_VERSION >= 3
167 wchar_t name[] = L"plotting";
168#else
169 char name[] = "plotting";
170#endif
171 Py_SetProgramName(name);
172 Py_Initialize();
173
174 wchar_t const *dummy_args[] = {
175 L"Python",
176 NULL}; // const is needed because literals must not be modified
177 wchar_t const **argv = dummy_args;
178 int argc = sizeof(dummy_args) / sizeof(dummy_args[0]) - 1;
179
180#if PY_MAJOR_VERSION >= 3
181 PySys_SetArgv(argc, const_cast<wchar_t **>(argv));
182#else
183 PySys_SetArgv(argc, (char **)(argv));
184#endif
185
186#ifndef WITHOUT_NUMPY
187 import_numpy(); // initialize numpy C-API
188#endif
189
190 PyObject *matplotlibname = PyString_FromString("matplotlib");
191 PyObject *pyplotname = PyString_FromString("matplotlib.pyplot");
192 PyObject *cmname = PyString_FromString("matplotlib.cm");
193 PyObject *pylabname = PyString_FromString("pylab");
194 if (!pyplotname || !pylabname || !matplotlibname || !cmname) {
195 throw std::runtime_error("couldnt create string");
196 }
197
198 PyObject *matplotlib = PyImport_Import(matplotlibname);
199
200 Py_DECREF(matplotlibname);
201 if (!matplotlib) {
202 PyErr_Print();
203 throw std::runtime_error("Error loading module matplotlib!");
204 }
205
206 // matplotlib.use() must be called *before* pylab, matplotlib.pyplot,
207 // or matplotlib.backends is imported for the first time
208 if (!s_backend.empty()) {
209 PyObject_CallMethod(matplotlib, const_cast<char *>("use"),
210 const_cast<char *>("s"), s_backend.c_str());
211 }
212
213 PyObject *pymod = PyImport_Import(pyplotname);
214 Py_DECREF(pyplotname);
215 if (!pymod) {
216 throw std::runtime_error("Error loading module matplotlib.pyplot!");
217 }
218
219 s_python_colormap = PyImport_Import(cmname);
220 Py_DECREF(cmname);
221 if (!s_python_colormap) {
222 throw std::runtime_error("Error loading module matplotlib.cm!");
223 }
224
225 PyObject *pylabmod = PyImport_Import(pylabname);
226 Py_DECREF(pylabname);
227 if (!pylabmod) {
228 throw std::runtime_error("Error loading module pylab!");
229 }
230
231 s_python_function_arrow = safe_import(pymod, "arrow");
232 s_python_function_show = safe_import(pymod, "show");
233 s_python_function_close = safe_import(pymod, "close");
234 s_python_function_draw = safe_import(pymod, "draw");
235 s_python_function_pause = safe_import(pymod, "pause");
236 s_python_function_figure = safe_import(pymod, "figure");
237 s_python_function_fignum_exists = safe_import(pymod, "fignum_exists");
238 s_python_function_plot = safe_import(pymod, "plot");
239 s_python_function_quiver = safe_import(pymod, "quiver");
240 s_python_function_contour = safe_import(pymod, "contour");
241 s_python_function_semilogx = safe_import(pymod, "semilogx");
242 s_python_function_semilogy = safe_import(pymod, "semilogy");
243 s_python_function_loglog = safe_import(pymod, "loglog");
244 s_python_function_fill = safe_import(pymod, "fill");
245 s_python_function_fill_between = safe_import(pymod, "fill_between");
246 s_python_function_hist = safe_import(pymod, "hist");
247 s_python_function_scatter = safe_import(pymod, "scatter");
248 s_python_function_boxplot = safe_import(pymod, "boxplot");
249 s_python_function_subplot = safe_import(pymod, "subplot");
250 s_python_function_subplot2grid = safe_import(pymod, "subplot2grid");
251 s_python_function_legend = safe_import(pymod, "legend");
252 s_python_function_xlim = safe_import(pymod, "xlim");
253 s_python_function_ylim = safe_import(pymod, "ylim");
254 s_python_function_title = safe_import(pymod, "title");
255 s_python_function_axis = safe_import(pymod, "axis");
256 s_python_function_axhline = safe_import(pymod, "axhline");
257 s_python_function_axvline = safe_import(pymod, "axvline");
258 s_python_function_axvspan = safe_import(pymod, "axvspan");
259 s_python_function_xlabel = safe_import(pymod, "xlabel");
260 s_python_function_ylabel = safe_import(pymod, "ylabel");
261 s_python_function_gca = safe_import(pymod, "gca");
262 s_python_function_xticks = safe_import(pymod, "xticks");
263 s_python_function_yticks = safe_import(pymod, "yticks");
264 s_python_function_margins = safe_import(pymod, "margins");
265 s_python_function_tick_params = safe_import(pymod, "tick_params");
266 s_python_function_grid = safe_import(pymod, "grid");
267 s_python_function_ion = safe_import(pymod, "ion");
268 s_python_function_ginput = safe_import(pymod, "ginput");
269 s_python_function_save = safe_import(pylabmod, "savefig");
270 s_python_function_annotate = safe_import(pymod, "annotate");
271 s_python_function_cla = safe_import(pymod, "cla");
272 s_python_function_clf = safe_import(pymod, "clf");
273 s_python_function_errorbar = safe_import(pymod, "errorbar");
274 s_python_function_tight_layout = safe_import(pymod, "tight_layout");
275 s_python_function_stem = safe_import(pymod, "stem");
276 s_python_function_xkcd = safe_import(pymod, "xkcd");
277 s_python_function_text = safe_import(pymod, "text");
278 s_python_function_suptitle = safe_import(pymod, "suptitle");
279 s_python_function_bar = safe_import(pymod, "bar");
280 s_python_function_barh = safe_import(pymod, "barh");
281 s_python_function_colorbar = PyObject_GetAttrString(pymod, "colorbar");
282 s_python_function_subplots_adjust = safe_import(pymod, "subplots_adjust");
283 s_python_function_rcparams = PyObject_GetAttrString(pymod, "rcParams");
284 s_python_function_spy = PyObject_GetAttrString(pymod, "spy");
285#ifndef WITHOUT_NUMPY
286 s_python_function_imshow = safe_import(pymod, "imshow");
287#endif
288 s_python_empty_tuple = PyTuple_New(0);
289 }
290
291 ~_interpreter() { Py_Finalize(); }
292};
293
294} // end namespace detail
295
306inline void backend(const std::string &name) { detail::s_backend = name; }
307
308inline bool annotate(std::string annotation, double x, double y) {
310
311 PyObject *xy = PyTuple_New(2);
312 PyObject *str = PyString_FromString(annotation.c_str());
313
314 PyTuple_SetItem(xy, 0, PyFloat_FromDouble(x));
315 PyTuple_SetItem(xy, 1, PyFloat_FromDouble(y));
316
317 PyObject *kwargs = PyDict_New();
318 PyDict_SetItemString(kwargs, "xy", xy);
319
320 PyObject *args = PyTuple_New(1);
321 PyTuple_SetItem(args, 0, str);
322
323 PyObject *res = PyObject_Call(
324 detail::_interpreter::get().s_python_function_annotate, args, kwargs);
325
326 Py_DECREF(args);
327 Py_DECREF(kwargs);
328
329 if (res)
330 Py_DECREF(res);
331
332 return res;
333}
334
335namespace detail {
336
337#ifndef WITHOUT_NUMPY
338// Type selector for numpy array conversion
339template <typename T> struct select_npy_type {
340 const static NPY_TYPES type = NPY_NOTYPE;
341}; // Default
342template <> struct select_npy_type<double> {
343 const static NPY_TYPES type = NPY_DOUBLE;
344};
345template <> struct select_npy_type<float> {
346 const static NPY_TYPES type = NPY_FLOAT;
347};
348template <> struct select_npy_type<bool> {
349 const static NPY_TYPES type = NPY_BOOL;
350};
351template <> struct select_npy_type<int8_t> {
352 const static NPY_TYPES type = NPY_INT8;
353};
354template <> struct select_npy_type<int16_t> {
355 const static NPY_TYPES type = NPY_SHORT;
356};
357template <> struct select_npy_type<int32_t> {
358 const static NPY_TYPES type = NPY_INT;
359};
360template <> struct select_npy_type<int64_t> {
361 const static NPY_TYPES type = NPY_INT64;
362};
363template <> struct select_npy_type<uint8_t> {
364 const static NPY_TYPES type = NPY_UINT8;
365};
366template <> struct select_npy_type<uint16_t> {
367 const static NPY_TYPES type = NPY_USHORT;
368};
369template <> struct select_npy_type<uint32_t> {
370 const static NPY_TYPES type = NPY_ULONG;
371};
372template <> struct select_npy_type<uint64_t> {
373 const static NPY_TYPES type = NPY_UINT64;
374};
375
376// Sanity checks; comment them out or change the numpy type below if you're
377// compiling on a platform where they don't apply
378static_assert(sizeof(long long) == 8);
379template <> struct select_npy_type<long long> {
380 const static NPY_TYPES type = NPY_INT64;
381};
382static_assert(sizeof(unsigned long long) == 8);
383template <> struct select_npy_type<unsigned long long> {
384 const static NPY_TYPES type = NPY_UINT64;
385};
386
387template <typename Numeric> PyObject *get_array(const std::vector<Numeric> &v) {
388 npy_intp vsize = v.size();
389 NPY_TYPES type = select_npy_type<Numeric>::type;
390 if (type == NPY_NOTYPE) {
391 size_t memsize = v.size() * sizeof(double);
392 double *dp = static_cast<double *>(::malloc(memsize));
393 for (size_t i = 0; i < v.size(); ++i)
394 dp[i] = v[i];
395 PyObject *varray = PyArray_SimpleNewFromData(1, &vsize, NPY_DOUBLE, dp);
396 PyArray_UpdateFlags(reinterpret_cast<PyArrayObject *>(varray),
397 NPY_ARRAY_OWNDATA);
398 return varray;
399 }
400
401 PyObject *varray =
402 PyArray_SimpleNewFromData(1, &vsize, type, (void *)(v.data()));
403 return varray;
404}
405
406template <typename Numeric>
407PyObject *get_2darray(const std::vector<::std::vector<Numeric>> &v) {
408 if (v.size() < 1)
409 throw std::runtime_error("get_2d_array v too small");
410
411 npy_intp vsize[2] = {static_cast<npy_intp>(v.size()),
412 static_cast<npy_intp>(v[0].size())};
413
414 PyArrayObject *varray =
415 (PyArrayObject *)PyArray_SimpleNew(2, vsize, NPY_DOUBLE);
416
417 double *vd_begin = static_cast<double *>(PyArray_DATA(varray));
418
419 for (const ::std::vector<Numeric> &v_row : v) {
420 if (v_row.size() != static_cast<size_t>(vsize[1]))
421 throw std::runtime_error("Missmatched array size");
422 std::copy(v_row.begin(), v_row.end(), vd_begin);
423 vd_begin += vsize[1];
424 }
425
426 return reinterpret_cast<PyObject *>(varray);
427}
428
429#else // fallback if we don't have numpy: copy every element of the given vector
430
431template <typename Numeric> PyObject *get_array(const std::vector<Numeric> &v) {
432 PyObject *list = PyList_New(v.size());
433 for (size_t i = 0; i < v.size(); ++i) {
434 PyList_SetItem(list, i, PyFloat_FromDouble(v.at(i)));
435 }
436 return list;
437}
438
439#endif // WITHOUT_NUMPY
440
441// sometimes, for labels and such, we need string arrays
442inline PyObject *get_array(const std::vector<std::string> &strings) {
443 PyObject *list = PyList_New(strings.size());
444 for (std::size_t i = 0; i < strings.size(); ++i) {
445 PyList_SetItem(list, i, PyString_FromString(strings[i].c_str()));
446 }
447 return list;
448}
449
450// not all matplotlib need 2d arrays, some prefer lists of lists
451template <typename Numeric>
452PyObject *get_listlist(const std::vector<std::vector<Numeric>> &ll) {
453 PyObject *listlist = PyList_New(ll.size());
454 for (std::size_t i = 0; i < ll.size(); ++i) {
455 PyList_SetItem(listlist, i, get_array(ll[i]));
456 }
457 return listlist;
458}
459
460} // namespace detail
461
465template <typename Numeric>
466bool plot(const std::vector<Numeric> &x, const std::vector<Numeric> &y,
467 const std::map<std::string, std::string> &keywords) {
468 assert(x.size() == y.size());
469
471
472 // using numpy arrays
473 PyObject *xarray = detail::get_array(x);
474 PyObject *yarray = detail::get_array(y);
475
476 // construct positional args
477 PyObject *args = PyTuple_New(2);
478 PyTuple_SetItem(args, 0, xarray);
479 PyTuple_SetItem(args, 1, yarray);
480
481 // construct keyword args
482 PyObject *kwargs = PyDict_New();
483 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
484 it != keywords.end(); ++it) {
485 PyDict_SetItemString(kwargs, it->first.c_str(),
486 PyString_FromString(it->second.c_str()));
487 }
488
489 PyObject *res = PyObject_Call(
490 detail::_interpreter::get().s_python_function_plot, args, kwargs);
491
492 Py_DECREF(args);
493 Py_DECREF(kwargs);
494 if (res)
495 Py_DECREF(res);
496
497 return res;
498}
499
500// TODO - it should be possible to make this work by implementing
501// a non-numpy alternative for `detail::get_2darray()`.
502#ifndef WITHOUT_NUMPY
503template <typename Numeric>
504void plot_surface(const std::vector<::std::vector<Numeric>> &x,
505 const std::vector<::std::vector<Numeric>> &y,
506 const std::vector<::std::vector<Numeric>> &z,
507 const std::map<std::string, std::string> &keywords =
508 std::map<std::string, std::string>(),
509 const long fig_number = 0) {
511
512 // We lazily load the modules here the first time this function is called
513 // because I'm not sure that we can assume "matplotlib installed" implies
514 // "mpl_toolkits installed" on all platforms, and we don't want to require
515 // it for people who don't need 3d plots.
516 static PyObject *mpl_toolkitsmod = nullptr, *axis3dmod = nullptr;
517 if (!mpl_toolkitsmod) {
519
520 PyObject *mpl_toolkits = PyString_FromString("mpl_toolkits");
521 PyObject *axis3d = PyString_FromString("mpl_toolkits.mplot3d");
522 if (!mpl_toolkits || !axis3d) {
523 throw std::runtime_error("couldnt create string");
524 }
525
526 mpl_toolkitsmod = PyImport_Import(mpl_toolkits);
527 Py_DECREF(mpl_toolkits);
528 if (!mpl_toolkitsmod) {
529 throw std::runtime_error("Error loading module mpl_toolkits!");
530 }
531
532 axis3dmod = PyImport_Import(axis3d);
533 Py_DECREF(axis3d);
534 if (!axis3dmod) {
535 throw std::runtime_error("Error loading module mpl_toolkits.mplot3d!");
536 }
537 }
538
539 assert(x.size() == y.size());
540 assert(y.size() == z.size());
541
542 // using numpy arrays
543 PyObject *xarray = detail::get_2darray(x);
544 PyObject *yarray = detail::get_2darray(y);
545 PyObject *zarray = detail::get_2darray(z);
546
547 // construct positional args
548 PyObject *args = PyTuple_New(3);
549 PyTuple_SetItem(args, 0, xarray);
550 PyTuple_SetItem(args, 1, yarray);
551 PyTuple_SetItem(args, 2, zarray);
552
553 // Build up the kw args.
554 PyObject *kwargs = PyDict_New();
555 PyDict_SetItemString(kwargs, "rstride", PyInt_FromLong(1));
556 PyDict_SetItemString(kwargs, "cstride", PyInt_FromLong(1));
557
558 PyObject *python_colormap_coolwarm = PyObject_GetAttrString(
559 detail::_interpreter::get().s_python_colormap, "coolwarm");
560
561 PyDict_SetItemString(kwargs, "cmap", python_colormap_coolwarm);
562
563 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
564 it != keywords.end(); ++it) {
565 if (it->first == "linewidth" || it->first == "alpha") {
566 PyDict_SetItemString(kwargs, it->first.c_str(),
567 PyFloat_FromDouble(std::stod(it->second)));
568 } else {
569 PyDict_SetItemString(kwargs, it->first.c_str(),
570 PyString_FromString(it->second.c_str()));
571 }
572 }
573
574 PyObject *fig_args = PyTuple_New(1);
575 PyObject *fig = nullptr;
576 PyTuple_SetItem(fig_args, 0, PyLong_FromLong(fig_number));
577 PyObject *fig_exists = PyObject_CallObject(
578 detail::_interpreter::get().s_python_function_fignum_exists, fig_args);
579 if (!PyObject_IsTrue(fig_exists)) {
580 fig = PyObject_CallObject(
581 detail::_interpreter::get().s_python_function_figure,
582 detail::_interpreter::get().s_python_empty_tuple);
583 } else {
584 fig = PyObject_CallObject(
585 detail::_interpreter::get().s_python_function_figure, fig_args);
586 }
587 Py_DECREF(fig_exists);
588 if (!fig)
589 throw std::runtime_error("Call to figure() failed.");
590
591 PyObject *gca_kwargs = PyDict_New();
592 PyDict_SetItemString(gca_kwargs, "projection", PyString_FromString("3d"));
593
594 PyObject *gca = PyObject_GetAttrString(fig, "gca");
595 if (!gca)
596 throw std::runtime_error("No gca");
597 Py_INCREF(gca);
598 PyObject *axis = PyObject_Call(
599 gca, detail::_interpreter::get().s_python_empty_tuple, gca_kwargs);
600
601 if (!axis)
602 throw std::runtime_error("No axis");
603 Py_INCREF(axis);
604
605 Py_DECREF(gca);
606 Py_DECREF(gca_kwargs);
607
608 PyObject *plot_surface = PyObject_GetAttrString(axis, "plot_surface");
609 if (!plot_surface)
610 throw std::runtime_error("No surface");
611 Py_INCREF(plot_surface);
612 PyObject *res = PyObject_Call(plot_surface, args, kwargs);
613 if (!res)
614 throw std::runtime_error("failed surface");
615 Py_DECREF(plot_surface);
616
617 Py_DECREF(axis);
618 Py_DECREF(args);
619 Py_DECREF(kwargs);
620 if (res)
621 Py_DECREF(res);
622}
623
624template <typename Numeric>
625void contour(const std::vector<::std::vector<Numeric>> &x,
626 const std::vector<::std::vector<Numeric>> &y,
627 const std::vector<::std::vector<Numeric>> &z,
628 const std::map<std::string, std::string> &keywords = {}) {
630
631 // using numpy arrays
632 PyObject *xarray = detail::get_2darray(x);
633 PyObject *yarray = detail::get_2darray(y);
634 PyObject *zarray = detail::get_2darray(z);
635
636 // construct positional args
637 PyObject *args = PyTuple_New(3);
638 PyTuple_SetItem(args, 0, xarray);
639 PyTuple_SetItem(args, 1, yarray);
640 PyTuple_SetItem(args, 2, zarray);
641
642 // Build up the kw args.
643 PyObject *kwargs = PyDict_New();
644
645 PyObject *python_colormap_coolwarm = PyObject_GetAttrString(
646 detail::_interpreter::get().s_python_colormap, "coolwarm");
647
648 PyDict_SetItemString(kwargs, "cmap", python_colormap_coolwarm);
649
650 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
651 it != keywords.end(); ++it) {
652 PyDict_SetItemString(kwargs, it->first.c_str(),
653 PyString_FromString(it->second.c_str()));
654 }
655
656 PyObject *res = PyObject_Call(
657 detail::_interpreter::get().s_python_function_contour, args, kwargs);
658 if (!res)
659 throw std::runtime_error("failed contour");
660
661 Py_DECREF(args);
662 Py_DECREF(kwargs);
663 if (res)
664 Py_DECREF(res);
665}
666
667template <typename Numeric>
668void spy(const std::vector<::std::vector<Numeric>> &x,
669 const double markersize = -1, // -1 for default matplotlib size
670 const std::map<std::string, std::string> &keywords = {}) {
672
673 PyObject *xarray = detail::get_2darray(x);
674
675 PyObject *kwargs = PyDict_New();
676 if (markersize != -1) {
677 PyDict_SetItemString(kwargs, "markersize", PyFloat_FromDouble(markersize));
678 }
679 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
680 it != keywords.end(); ++it) {
681 PyDict_SetItemString(kwargs, it->first.c_str(),
682 PyString_FromString(it->second.c_str()));
683 }
684
685 PyObject *plot_args = PyTuple_New(1);
686 PyTuple_SetItem(plot_args, 0, xarray);
687
688 PyObject *res = PyObject_Call(
689 detail::_interpreter::get().s_python_function_spy, plot_args, kwargs);
690
691 Py_DECREF(plot_args);
692 Py_DECREF(kwargs);
693 if (res)
694 Py_DECREF(res);
695}
696#endif // WITHOUT_NUMPY
697
698template <typename Numeric>
699void plot3(const std::vector<Numeric> &x, const std::vector<Numeric> &y,
700 const std::vector<Numeric> &z,
701 const std::map<std::string, std::string> &keywords =
702 std::map<std::string, std::string>(),
703 const long fig_number = 0) {
705
706 // Same as with plot_surface: We lazily load the modules here the first time
707 // this function is called because I'm not sure that we can assume "matplotlib
708 // installed" implies "mpl_toolkits installed" on all platforms, and we don't
709 // want to require it for people who don't need 3d plots.
710 static PyObject *mpl_toolkitsmod = nullptr, *axis3dmod = nullptr;
711 if (!mpl_toolkitsmod) {
713
714 PyObject *mpl_toolkits = PyString_FromString("mpl_toolkits");
715 PyObject *axis3d = PyString_FromString("mpl_toolkits.mplot3d");
716 if (!mpl_toolkits || !axis3d) {
717 throw std::runtime_error("couldnt create string");
718 }
719
720 mpl_toolkitsmod = PyImport_Import(mpl_toolkits);
721 Py_DECREF(mpl_toolkits);
722 if (!mpl_toolkitsmod) {
723 throw std::runtime_error("Error loading module mpl_toolkits!");
724 }
725
726 axis3dmod = PyImport_Import(axis3d);
727 Py_DECREF(axis3d);
728 if (!axis3dmod) {
729 throw std::runtime_error("Error loading module mpl_toolkits.mplot3d!");
730 }
731 }
732
733 assert(x.size() == y.size());
734 assert(y.size() == z.size());
735
736 PyObject *xarray = detail::get_array(x);
737 PyObject *yarray = detail::get_array(y);
738 PyObject *zarray = detail::get_array(z);
739
740 // construct positional args
741 PyObject *args = PyTuple_New(3);
742 PyTuple_SetItem(args, 0, xarray);
743 PyTuple_SetItem(args, 1, yarray);
744 PyTuple_SetItem(args, 2, zarray);
745
746 // Build up the kw args.
747 PyObject *kwargs = PyDict_New();
748
749 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
750 it != keywords.end(); ++it) {
751 PyDict_SetItemString(kwargs, it->first.c_str(),
752 PyString_FromString(it->second.c_str()));
753 }
754
755 PyObject *fig_args = PyTuple_New(1);
756 PyObject *fig = nullptr;
757 PyTuple_SetItem(fig_args, 0, PyLong_FromLong(fig_number));
758 PyObject *fig_exists = PyObject_CallObject(
759 detail::_interpreter::get().s_python_function_fignum_exists, fig_args);
760 if (!PyObject_IsTrue(fig_exists)) {
761 fig = PyObject_CallObject(
762 detail::_interpreter::get().s_python_function_figure,
763 detail::_interpreter::get().s_python_empty_tuple);
764 } else {
765 fig = PyObject_CallObject(
766 detail::_interpreter::get().s_python_function_figure, fig_args);
767 }
768 if (!fig)
769 throw std::runtime_error("Call to figure() failed.");
770
771 PyObject *gca_kwargs = PyDict_New();
772 PyDict_SetItemString(gca_kwargs, "projection", PyString_FromString("3d"));
773
774 PyObject *gca = PyObject_GetAttrString(fig, "gca");
775 if (!gca)
776 throw std::runtime_error("No gca");
777 Py_INCREF(gca);
778 PyObject *axis = PyObject_Call(
779 gca, detail::_interpreter::get().s_python_empty_tuple, gca_kwargs);
780
781 if (!axis)
782 throw std::runtime_error("No axis");
783 Py_INCREF(axis);
784
785 Py_DECREF(gca);
786 Py_DECREF(gca_kwargs);
787
788 PyObject *plot3 = PyObject_GetAttrString(axis, "plot");
789 if (!plot3)
790 throw std::runtime_error("No 3D line plot");
791 Py_INCREF(plot3);
792 PyObject *res = PyObject_Call(plot3, args, kwargs);
793 if (!res)
794 throw std::runtime_error("Failed 3D line plot");
795 Py_DECREF(plot3);
796
797 Py_DECREF(axis);
798 Py_DECREF(args);
799 Py_DECREF(kwargs);
800 if (res)
801 Py_DECREF(res);
802}
803
804template <typename Numeric>
805bool stem(const std::vector<Numeric> &x, const std::vector<Numeric> &y,
806 const std::map<std::string, std::string> &keywords) {
807 assert(x.size() == y.size());
808
810
811 // using numpy arrays
812 PyObject *xarray = detail::get_array(x);
813 PyObject *yarray = detail::get_array(y);
814
815 // construct positional args
816 PyObject *args = PyTuple_New(2);
817 PyTuple_SetItem(args, 0, xarray);
818 PyTuple_SetItem(args, 1, yarray);
819
820 // construct keyword args
821 PyObject *kwargs = PyDict_New();
822 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
823 it != keywords.end(); ++it) {
824 PyDict_SetItemString(kwargs, it->first.c_str(),
825 PyString_FromString(it->second.c_str()));
826 }
827
828 PyObject *res = PyObject_Call(
829 detail::_interpreter::get().s_python_function_stem, args, kwargs);
830
831 Py_DECREF(args);
832 Py_DECREF(kwargs);
833 if (res)
834 Py_DECREF(res);
835
836 return res;
837}
838
839template <typename Numeric>
840bool fill(const std::vector<Numeric> &x, const std::vector<Numeric> &y,
841 const std::map<std::string, std::string> &keywords) {
842 assert(x.size() == y.size());
843
845
846 // using numpy arrays
847 PyObject *xarray = detail::get_array(x);
848 PyObject *yarray = detail::get_array(y);
849
850 // construct positional args
851 PyObject *args = PyTuple_New(2);
852 PyTuple_SetItem(args, 0, xarray);
853 PyTuple_SetItem(args, 1, yarray);
854
855 // construct keyword args
856 PyObject *kwargs = PyDict_New();
857 for (auto it = keywords.begin(); it != keywords.end(); ++it) {
858 PyDict_SetItemString(kwargs, it->first.c_str(),
859 PyUnicode_FromString(it->second.c_str()));
860 }
861
862 PyObject *res = PyObject_Call(
863 detail::_interpreter::get().s_python_function_fill, args, kwargs);
864
865 Py_DECREF(args);
866 Py_DECREF(kwargs);
867
868 if (res)
869 Py_DECREF(res);
870
871 return res;
872}
873
874template <typename Numeric>
875bool fill_between(const std::vector<Numeric> &x, const std::vector<Numeric> &y1,
876 const std::vector<Numeric> &y2,
877 const std::map<std::string, std::string> &keywords) {
878 assert(x.size() == y1.size());
879 assert(x.size() == y2.size());
880
882
883 // using numpy arrays
884 PyObject *xarray = detail::get_array(x);
885 PyObject *y1array = detail::get_array(y1);
886 PyObject *y2array = detail::get_array(y2);
887
888 // construct positional args
889 PyObject *args = PyTuple_New(3);
890 PyTuple_SetItem(args, 0, xarray);
891 PyTuple_SetItem(args, 1, y1array);
892 PyTuple_SetItem(args, 2, y2array);
893
894 // construct keyword args
895 PyObject *kwargs = PyDict_New();
896 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
897 it != keywords.end(); ++it) {
898 PyDict_SetItemString(kwargs, it->first.c_str(),
899 PyUnicode_FromString(it->second.c_str()));
900 }
901
902 PyObject *res = PyObject_Call(
903 detail::_interpreter::get().s_python_function_fill_between, args, kwargs);
904
905 Py_DECREF(args);
906 Py_DECREF(kwargs);
907 if (res)
908 Py_DECREF(res);
909
910 return res;
911}
912
913template <typename Numeric>
914bool arrow(Numeric x, Numeric y, Numeric end_x, Numeric end_y,
915 const std::string &fc = "r", const std::string ec = "k",
916 Numeric head_length = 0.25, Numeric head_width = 0.1625) {
917 PyObject *obj_x = PyFloat_FromDouble(x);
918 PyObject *obj_y = PyFloat_FromDouble(y);
919 PyObject *obj_end_x = PyFloat_FromDouble(end_x);
920 PyObject *obj_end_y = PyFloat_FromDouble(end_y);
921
922 PyObject *kwargs = PyDict_New();
923 PyDict_SetItemString(kwargs, "fc", PyString_FromString(fc.c_str()));
924 PyDict_SetItemString(kwargs, "ec", PyString_FromString(ec.c_str()));
925 PyDict_SetItemString(kwargs, "head_width", PyFloat_FromDouble(head_width));
926 PyDict_SetItemString(kwargs, "head_length", PyFloat_FromDouble(head_length));
927
928 PyObject *plot_args = PyTuple_New(4);
929 PyTuple_SetItem(plot_args, 0, obj_x);
930 PyTuple_SetItem(plot_args, 1, obj_y);
931 PyTuple_SetItem(plot_args, 2, obj_end_x);
932 PyTuple_SetItem(plot_args, 3, obj_end_y);
933
934 PyObject *res = PyObject_Call(
935 detail::_interpreter::get().s_python_function_arrow, plot_args, kwargs);
936
937 Py_DECREF(plot_args);
938 Py_DECREF(kwargs);
939 if (res)
940 Py_DECREF(res);
941
942 return res;
943}
944
945template <typename Numeric>
946bool hist(const std::vector<Numeric> &y, long bins = 10,
947 std::string color = "b", double alpha = 1.0,
948 bool cumulative = false) {
950
951 PyObject *yarray = detail::get_array(y);
952
953 PyObject *kwargs = PyDict_New();
954 PyDict_SetItemString(kwargs, "bins", PyLong_FromLong(bins));
955 PyDict_SetItemString(kwargs, "color", PyString_FromString(color.c_str()));
956 PyDict_SetItemString(kwargs, "alpha", PyFloat_FromDouble(alpha));
957 PyDict_SetItemString(kwargs, "cumulative", cumulative ? Py_True : Py_False);
958
959 PyObject *plot_args = PyTuple_New(1);
960
961 PyTuple_SetItem(plot_args, 0, yarray);
962
963 PyObject *res = PyObject_Call(
964 detail::_interpreter::get().s_python_function_hist, plot_args, kwargs);
965
966 Py_DECREF(plot_args);
967 Py_DECREF(kwargs);
968 if (res)
969 Py_DECREF(res);
970
971 return res;
972}
973
974#ifndef WITHOUT_NUMPY
975namespace detail {
976
977inline void imshow(void *ptr, const NPY_TYPES type, const int rows,
978 const int columns, const int colors,
979 const std::map<std::string, std::string> &keywords,
980 PyObject **out) {
981 assert(type == NPY_UINT8 || type == NPY_FLOAT);
982 assert(colors == 1 || colors == 3 || colors == 4);
983
985
986 // construct args
987 npy_intp dims[3] = {rows, columns, colors};
988 PyObject *args = PyTuple_New(1);
989 PyTuple_SetItem(
990 args, 0, PyArray_SimpleNewFromData(colors == 1 ? 2 : 3, dims, type, ptr));
991
992 // construct keyword args
993 PyObject *kwargs = PyDict_New();
994 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
995 it != keywords.end(); ++it) {
996 PyDict_SetItemString(kwargs, it->first.c_str(),
997 PyUnicode_FromString(it->second.c_str()));
998 }
999
1000 PyObject *res = PyObject_Call(
1001 detail::_interpreter::get().s_python_function_imshow, args, kwargs);
1002 Py_DECREF(args);
1003 Py_DECREF(kwargs);
1004 if (!res)
1005 throw std::runtime_error("Call to imshow() failed");
1006 if (out)
1007 *out = res;
1008 else
1009 Py_DECREF(res);
1010}
1011
1012} // namespace detail
1013
1014inline void imshow(const unsigned char *ptr, const int rows, const int columns,
1015 const int colors,
1016 const std::map<std::string, std::string> &keywords = {},
1017 PyObject **out = nullptr) {
1018 detail::imshow((void *)ptr, NPY_UINT8, rows, columns, colors, keywords, out);
1019}
1020
1021inline void imshow(const float *ptr, const int rows, const int columns,
1022 const int colors,
1023 const std::map<std::string, std::string> &keywords = {},
1024 PyObject **out = nullptr) {
1025 detail::imshow((void *)ptr, NPY_FLOAT, rows, columns, colors, keywords, out);
1026}
1027
1028#ifdef WITH_OPENCV
1029void imshow(const cv::Mat &image,
1030 const std::map<std::string, std::string> &keywords = {}) {
1031 // Convert underlying type of matrix, if needed
1032 cv::Mat image2;
1033 NPY_TYPES npy_type = NPY_UINT8;
1034 switch (image.type() & CV_MAT_DEPTH_MASK) {
1035 case CV_8U:
1036 image2 = image;
1037 break;
1038 case CV_32F:
1039 image2 = image;
1040 npy_type = NPY_FLOAT;
1041 break;
1042 default:
1043 image.convertTo(image2, CV_MAKETYPE(CV_8U, image.channels()));
1044 }
1045
1046 // If color image, convert from BGR to RGB
1047 switch (image2.channels()) {
1048 case 3:
1049 cv::cvtColor(image2, image2, CV_BGR2RGB);
1050 break;
1051 case 4:
1052 cv::cvtColor(image2, image2, CV_BGRA2RGBA);
1053 }
1054
1055 detail::imshow(image2.data, npy_type, image2.rows, image2.cols,
1056 image2.channels(), keywords);
1057}
1058#endif // WITH_OPENCV
1059#endif // WITHOUT_NUMPY
1060
1061template <typename NumericX, typename NumericY>
1062bool scatter(const std::vector<NumericX> &x, const std::vector<NumericY> &y,
1063 const double s = 1.0, // The marker size in points**2
1064 const std::map<std::string, std::string> &keywords = {}) {
1066
1067 assert(x.size() == y.size());
1068
1069 PyObject *xarray = detail::get_array(x);
1070 PyObject *yarray = detail::get_array(y);
1071
1072 PyObject *kwargs = PyDict_New();
1073 PyDict_SetItemString(kwargs, "s", PyLong_FromLong(s));
1074 for (const auto &it : keywords) {
1075 PyDict_SetItemString(kwargs, it.first.c_str(),
1076 PyString_FromString(it.second.c_str()));
1077 }
1078
1079 PyObject *plot_args = PyTuple_New(2);
1080 PyTuple_SetItem(plot_args, 0, xarray);
1081 PyTuple_SetItem(plot_args, 1, yarray);
1082
1083 PyObject *res = PyObject_Call(
1084 detail::_interpreter::get().s_python_function_scatter, plot_args, kwargs);
1085
1086 Py_DECREF(plot_args);
1087 Py_DECREF(kwargs);
1088 if (res)
1089 Py_DECREF(res);
1090
1091 return res;
1092}
1093
1094template <typename NumericX, typename NumericY, typename NumericColors>
1095bool scatter_colored(const std::vector<NumericX> &x,
1096 const std::vector<NumericY> &y,
1097 const std::vector<NumericColors> &colors,
1098 const double s = 1.0, // The marker size in points**2
1099 const std::map<std::string, std::string> &keywords = {}) {
1101
1102 assert(x.size() == y.size());
1103
1104 PyObject *xarray = detail::get_array(x);
1105 PyObject *yarray = detail::get_array(y);
1106 PyObject *colors_array = detail::get_array(colors);
1107
1108 PyObject *kwargs = PyDict_New();
1109 PyDict_SetItemString(kwargs, "s", PyLong_FromLong(s));
1110 PyDict_SetItemString(kwargs, "c", colors_array);
1111
1112 for (const auto &it : keywords) {
1113 PyDict_SetItemString(kwargs, it.first.c_str(),
1114 PyString_FromString(it.second.c_str()));
1115 }
1116
1117 PyObject *plot_args = PyTuple_New(2);
1118 PyTuple_SetItem(plot_args, 0, xarray);
1119 PyTuple_SetItem(plot_args, 1, yarray);
1120
1121 PyObject *res = PyObject_Call(
1122 detail::_interpreter::get().s_python_function_scatter, plot_args, kwargs);
1123
1124 Py_DECREF(plot_args);
1125 Py_DECREF(kwargs);
1126 if (res)
1127 Py_DECREF(res);
1128
1129 return res;
1130}
1131
1132template <typename NumericX, typename NumericY, typename NumericZ>
1133bool scatter(const std::vector<NumericX> &x, const std::vector<NumericY> &y,
1134 const std::vector<NumericZ> &z,
1135 const double s = 1.0, // The marker size in points**2
1136 const std::map<std::string, std::string> &keywords = {},
1137 const long fig_number = 0) {
1139
1140 // Same as with plot_surface: We lazily load the modules here the first time
1141 // this function is called because I'm not sure that we can assume "matplotlib
1142 // installed" implies "mpl_toolkits installed" on all platforms, and we don't
1143 // want to require it for people who don't need 3d plots.
1144 static PyObject *mpl_toolkitsmod = nullptr, *axis3dmod = nullptr;
1145 if (!mpl_toolkitsmod) {
1147
1148 PyObject *mpl_toolkits = PyString_FromString("mpl_toolkits");
1149 PyObject *axis3d = PyString_FromString("mpl_toolkits.mplot3d");
1150 if (!mpl_toolkits || !axis3d) {
1151 throw std::runtime_error("couldnt create string");
1152 }
1153
1154 mpl_toolkitsmod = PyImport_Import(mpl_toolkits);
1155 Py_DECREF(mpl_toolkits);
1156 if (!mpl_toolkitsmod) {
1157 throw std::runtime_error("Error loading module mpl_toolkits!");
1158 }
1159
1160 axis3dmod = PyImport_Import(axis3d);
1161 Py_DECREF(axis3d);
1162 if (!axis3dmod) {
1163 throw std::runtime_error("Error loading module mpl_toolkits.mplot3d!");
1164 }
1165 }
1166
1167 assert(x.size() == y.size());
1168 assert(y.size() == z.size());
1169
1170 PyObject *xarray = detail::get_array(x);
1171 PyObject *yarray = detail::get_array(y);
1172 PyObject *zarray = detail::get_array(z);
1173
1174 // construct positional args
1175 PyObject *args = PyTuple_New(3);
1176 PyTuple_SetItem(args, 0, xarray);
1177 PyTuple_SetItem(args, 1, yarray);
1178 PyTuple_SetItem(args, 2, zarray);
1179
1180 // Build up the kw args.
1181 PyObject *kwargs = PyDict_New();
1182
1183 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
1184 it != keywords.end(); ++it) {
1185 PyDict_SetItemString(kwargs, it->first.c_str(),
1186 PyString_FromString(it->second.c_str()));
1187 }
1188 PyObject *fig_args = PyTuple_New(1);
1189 PyObject *fig = nullptr;
1190 PyTuple_SetItem(fig_args, 0, PyLong_FromLong(fig_number));
1191 PyObject *fig_exists = PyObject_CallObject(
1192 detail::_interpreter::get().s_python_function_fignum_exists, fig_args);
1193 if (!PyObject_IsTrue(fig_exists)) {
1194 fig = PyObject_CallObject(
1195 detail::_interpreter::get().s_python_function_figure,
1196 detail::_interpreter::get().s_python_empty_tuple);
1197 } else {
1198 fig = PyObject_CallObject(
1199 detail::_interpreter::get().s_python_function_figure, fig_args);
1200 }
1201 Py_DECREF(fig_exists);
1202 if (!fig)
1203 throw std::runtime_error("Call to figure() failed.");
1204
1205 PyObject *gca_kwargs = PyDict_New();
1206 PyDict_SetItemString(gca_kwargs, "projection", PyString_FromString("3d"));
1207
1208 PyObject *gca = PyObject_GetAttrString(fig, "gca");
1209 if (!gca)
1210 throw std::runtime_error("No gca");
1211 Py_INCREF(gca);
1212 PyObject *axis = PyObject_Call(
1213 gca, detail::_interpreter::get().s_python_empty_tuple, gca_kwargs);
1214
1215 if (!axis)
1216 throw std::runtime_error("No axis");
1217 Py_INCREF(axis);
1218
1219 Py_DECREF(gca);
1220 Py_DECREF(gca_kwargs);
1221
1222 PyObject *plot3 = PyObject_GetAttrString(axis, "scatter");
1223 if (!plot3)
1224 throw std::runtime_error("No 3D line plot");
1225 Py_INCREF(plot3);
1226 PyObject *res = PyObject_Call(plot3, args, kwargs);
1227 if (!res)
1228 throw std::runtime_error("Failed 3D line plot");
1229 Py_DECREF(plot3);
1230
1231 Py_DECREF(axis);
1232 Py_DECREF(args);
1233 Py_DECREF(kwargs);
1234 Py_DECREF(fig);
1235 if (res)
1236 Py_DECREF(res);
1237 return res;
1238}
1239
1240template <typename Numeric>
1241bool boxplot(const std::vector<std::vector<Numeric>> &data,
1242 const std::vector<std::string> &labels = {},
1243 const std::map<std::string, std::string> &keywords = {}) {
1245
1246 PyObject *listlist = detail::get_listlist(data);
1247 PyObject *args = PyTuple_New(1);
1248 PyTuple_SetItem(args, 0, listlist);
1249
1250 PyObject *kwargs = PyDict_New();
1251
1252 // kwargs needs the labels, if there are (the correct number of) labels
1253 if (!labels.empty() && labels.size() == data.size()) {
1254 PyDict_SetItemString(kwargs, "labels", detail::get_array(labels));
1255 }
1256
1257 // take care of the remaining keywords
1258 for (const auto &it : keywords) {
1259 PyDict_SetItemString(kwargs, it.first.c_str(),
1260 PyString_FromString(it.second.c_str()));
1261 }
1262
1263 PyObject *res = PyObject_Call(
1264 detail::_interpreter::get().s_python_function_boxplot, args, kwargs);
1265
1266 Py_DECREF(args);
1267 Py_DECREF(kwargs);
1268
1269 if (res)
1270 Py_DECREF(res);
1271
1272 return res;
1273}
1274
1275template <typename Numeric>
1276bool boxplot(const std::vector<Numeric> &data,
1277 const std::map<std::string, std::string> &keywords = {}) {
1279
1280 PyObject *vector = detail::get_array(data);
1281 PyObject *args = PyTuple_New(1);
1282 PyTuple_SetItem(args, 0, vector);
1283
1284 PyObject *kwargs = PyDict_New();
1285 for (const auto &it : keywords) {
1286 PyDict_SetItemString(kwargs, it.first.c_str(),
1287 PyString_FromString(it.second.c_str()));
1288 }
1289
1290 PyObject *res = PyObject_Call(
1291 detail::_interpreter::get().s_python_function_boxplot, args, kwargs);
1292
1293 Py_DECREF(args);
1294 Py_DECREF(kwargs);
1295
1296 if (res)
1297 Py_DECREF(res);
1298
1299 return res;
1300}
1301
1302template <typename Numeric>
1303bool bar(const std::vector<Numeric> &x, const std::vector<Numeric> &y,
1304 std::string ec = "black", std::string ls = "-", double lw = 1.0,
1305 const std::map<std::string, std::string> &keywords = {}) {
1307
1308 PyObject *xarray = detail::get_array(x);
1309 PyObject *yarray = detail::get_array(y);
1310
1311 PyObject *kwargs = PyDict_New();
1312
1313 PyDict_SetItemString(kwargs, "ec", PyString_FromString(ec.c_str()));
1314 PyDict_SetItemString(kwargs, "ls", PyString_FromString(ls.c_str()));
1315 PyDict_SetItemString(kwargs, "lw", PyFloat_FromDouble(lw));
1316
1317 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
1318 it != keywords.end(); ++it) {
1319 PyDict_SetItemString(kwargs, it->first.c_str(),
1320 PyUnicode_FromString(it->second.c_str()));
1321 }
1322
1323 PyObject *plot_args = PyTuple_New(2);
1324 PyTuple_SetItem(plot_args, 0, xarray);
1325 PyTuple_SetItem(plot_args, 1, yarray);
1326
1327 PyObject *res = PyObject_Call(
1328 detail::_interpreter::get().s_python_function_bar, plot_args, kwargs);
1329
1330 Py_DECREF(plot_args);
1331 Py_DECREF(kwargs);
1332 if (res)
1333 Py_DECREF(res);
1334
1335 return res;
1336}
1337
1338template <typename Numeric>
1339bool bar(const std::vector<Numeric> &y, std::string ec = "black",
1340 std::string ls = "-", double lw = 1.0,
1341 const std::map<std::string, std::string> &keywords = {}) {
1342 using T = typename std::remove_reference<decltype(y)>::type::value_type;
1343
1345
1346 std::vector<T> x;
1347 for (std::size_t i = 0; i < y.size(); i++) {
1348 x.push_back(i);
1349 }
1350
1351 return bar(x, y, ec, ls, lw, keywords);
1352}
1353
1354template <typename Numeric>
1355bool barh(const std::vector<Numeric> &x, const std::vector<Numeric> &y,
1356 std::string ec = "black", std::string ls = "-", double lw = 1.0,
1357 const std::map<std::string, std::string> &keywords = {}) {
1358 PyObject *xarray = detail::get_array(x);
1359 PyObject *yarray = detail::get_array(y);
1360
1361 PyObject *kwargs = PyDict_New();
1362
1363 PyDict_SetItemString(kwargs, "ec", PyString_FromString(ec.c_str()));
1364 PyDict_SetItemString(kwargs, "ls", PyString_FromString(ls.c_str()));
1365 PyDict_SetItemString(kwargs, "lw", PyFloat_FromDouble(lw));
1366
1367 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
1368 it != keywords.end(); ++it) {
1369 PyDict_SetItemString(kwargs, it->first.c_str(),
1370 PyUnicode_FromString(it->second.c_str()));
1371 }
1372
1373 PyObject *plot_args = PyTuple_New(2);
1374 PyTuple_SetItem(plot_args, 0, xarray);
1375 PyTuple_SetItem(plot_args, 1, yarray);
1376
1377 PyObject *res = PyObject_Call(
1378 detail::_interpreter::get().s_python_function_barh, plot_args, kwargs);
1379
1380 Py_DECREF(plot_args);
1381 Py_DECREF(kwargs);
1382 if (res)
1383 Py_DECREF(res);
1384
1385 return res;
1386}
1387
1388inline bool
1389subplots_adjust(const std::map<std::string, double> &keywords = {}) {
1391
1392 PyObject *kwargs = PyDict_New();
1393 for (std::map<std::string, double>::const_iterator it = keywords.begin();
1394 it != keywords.end(); ++it) {
1395 PyDict_SetItemString(kwargs, it->first.c_str(),
1396 PyFloat_FromDouble(it->second));
1397 }
1398
1399 PyObject *plot_args = PyTuple_New(0);
1400
1401 PyObject *res = PyObject_Call(
1402 detail::_interpreter::get().s_python_function_subplots_adjust, plot_args,
1403 kwargs);
1404
1405 Py_DECREF(plot_args);
1406 Py_DECREF(kwargs);
1407 if (res)
1408 Py_DECREF(res);
1409
1410 return res;
1411}
1412
1413template <typename Numeric>
1414bool named_hist(std::string label, const std::vector<Numeric> &y,
1415 long bins = 10, std::string color = "b", double alpha = 1.0) {
1417
1418 PyObject *yarray = detail::get_array(y);
1419
1420 PyObject *kwargs = PyDict_New();
1421 PyDict_SetItemString(kwargs, "label", PyString_FromString(label.c_str()));
1422 PyDict_SetItemString(kwargs, "bins", PyLong_FromLong(bins));
1423 PyDict_SetItemString(kwargs, "color", PyString_FromString(color.c_str()));
1424 PyDict_SetItemString(kwargs, "alpha", PyFloat_FromDouble(alpha));
1425
1426 PyObject *plot_args = PyTuple_New(1);
1427 PyTuple_SetItem(plot_args, 0, yarray);
1428
1429 PyObject *res = PyObject_Call(
1430 detail::_interpreter::get().s_python_function_hist, plot_args, kwargs);
1431
1432 Py_DECREF(plot_args);
1433 Py_DECREF(kwargs);
1434 if (res)
1435 Py_DECREF(res);
1436
1437 return res;
1438}
1439
1440template <typename NumericX, typename NumericY>
1441bool plot(const std::vector<NumericX> &x, const std::vector<NumericY> &y,
1442 const std::string &s = "") {
1443 assert(x.size() == y.size());
1444
1446
1447 PyObject *xarray = detail::get_array(x);
1448 PyObject *yarray = detail::get_array(y);
1449
1450 PyObject *pystring = PyString_FromString(s.c_str());
1451
1452 PyObject *plot_args = PyTuple_New(3);
1453 PyTuple_SetItem(plot_args, 0, xarray);
1454 PyTuple_SetItem(plot_args, 1, yarray);
1455 PyTuple_SetItem(plot_args, 2, pystring);
1456
1457 PyObject *res = PyObject_CallObject(
1458 detail::_interpreter::get().s_python_function_plot, plot_args);
1459
1460 Py_DECREF(plot_args);
1461 if (res)
1462 Py_DECREF(res);
1463
1464 return res;
1465}
1466
1467template <typename NumericX, typename NumericY, typename NumericZ>
1468bool contour(const std::vector<NumericX> &x, const std::vector<NumericY> &y,
1469 const std::vector<NumericZ> &z,
1470 const std::map<std::string, std::string> &keywords = {}) {
1471 assert(x.size() == y.size() && x.size() == z.size());
1472
1473 PyObject *xarray = detail::get_array(x);
1474 PyObject *yarray = detail::get_array(y);
1475 PyObject *zarray = detail::get_array(z);
1476
1477 PyObject *plot_args = PyTuple_New(3);
1478 PyTuple_SetItem(plot_args, 0, xarray);
1479 PyTuple_SetItem(plot_args, 1, yarray);
1480 PyTuple_SetItem(plot_args, 2, zarray);
1481
1482 // construct keyword args
1483 PyObject *kwargs = PyDict_New();
1484 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
1485 it != keywords.end(); ++it) {
1486 PyDict_SetItemString(kwargs, it->first.c_str(),
1487 PyUnicode_FromString(it->second.c_str()));
1488 }
1489
1490 PyObject *res = PyObject_Call(
1491 detail::_interpreter::get().s_python_function_contour, plot_args, kwargs);
1492
1493 Py_DECREF(kwargs);
1494 Py_DECREF(plot_args);
1495 if (res)
1496 Py_DECREF(res);
1497
1498 return res;
1499}
1500
1501template <typename NumericX, typename NumericY, typename NumericU,
1502 typename NumericW>
1503bool quiver(const std::vector<NumericX> &x, const std::vector<NumericY> &y,
1504 const std::vector<NumericU> &u, const std::vector<NumericW> &w,
1505 const std::map<std::string, std::string> &keywords = {}) {
1506 assert(x.size() == y.size() && x.size() == u.size() && u.size() == w.size());
1507
1509
1510 PyObject *xarray = detail::get_array(x);
1511 PyObject *yarray = detail::get_array(y);
1512 PyObject *uarray = detail::get_array(u);
1513 PyObject *warray = detail::get_array(w);
1514
1515 PyObject *plot_args = PyTuple_New(4);
1516 PyTuple_SetItem(plot_args, 0, xarray);
1517 PyTuple_SetItem(plot_args, 1, yarray);
1518 PyTuple_SetItem(plot_args, 2, uarray);
1519 PyTuple_SetItem(plot_args, 3, warray);
1520
1521 // construct keyword args
1522 PyObject *kwargs = PyDict_New();
1523 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
1524 it != keywords.end(); ++it) {
1525 PyDict_SetItemString(kwargs, it->first.c_str(),
1526 PyUnicode_FromString(it->second.c_str()));
1527 }
1528
1529 PyObject *res = PyObject_Call(
1530 detail::_interpreter::get().s_python_function_quiver, plot_args, kwargs);
1531
1532 Py_DECREF(kwargs);
1533 Py_DECREF(plot_args);
1534 if (res)
1535 Py_DECREF(res);
1536
1537 return res;
1538}
1539
1540template <typename NumericX, typename NumericY, typename NumericZ,
1541 typename NumericU, typename NumericW, typename NumericV>
1542bool quiver(const std::vector<NumericX> &x, const std::vector<NumericY> &y,
1543 const std::vector<NumericZ> &z, const std::vector<NumericU> &u,
1544 const std::vector<NumericW> &w, const std::vector<NumericV> &v,
1545 const std::map<std::string, std::string> &keywords = {}) {
1546 // set up 3d axes stuff
1547 static PyObject *mpl_toolkitsmod = nullptr, *axis3dmod = nullptr;
1548 if (!mpl_toolkitsmod) {
1550
1551 PyObject *mpl_toolkits = PyString_FromString("mpl_toolkits");
1552 PyObject *axis3d = PyString_FromString("mpl_toolkits.mplot3d");
1553 if (!mpl_toolkits || !axis3d) {
1554 throw std::runtime_error("couldnt create string");
1555 }
1556
1557 mpl_toolkitsmod = PyImport_Import(mpl_toolkits);
1558 Py_DECREF(mpl_toolkits);
1559 if (!mpl_toolkitsmod) {
1560 throw std::runtime_error("Error loading module mpl_toolkits!");
1561 }
1562
1563 axis3dmod = PyImport_Import(axis3d);
1564 Py_DECREF(axis3d);
1565 if (!axis3dmod) {
1566 throw std::runtime_error("Error loading module mpl_toolkits.mplot3d!");
1567 }
1568 }
1569
1570 // assert sizes match up
1571 assert(x.size() == y.size() && x.size() == u.size() && u.size() == w.size() &&
1572 x.size() == z.size() && x.size() == v.size() && u.size() == v.size());
1573
1574 // set up parameters
1576
1577 PyObject *xarray = detail::get_array(x);
1578 PyObject *yarray = detail::get_array(y);
1579 PyObject *zarray = detail::get_array(z);
1580 PyObject *uarray = detail::get_array(u);
1581 PyObject *warray = detail::get_array(w);
1582 PyObject *varray = detail::get_array(v);
1583
1584 PyObject *plot_args = PyTuple_New(6);
1585 PyTuple_SetItem(plot_args, 0, xarray);
1586 PyTuple_SetItem(plot_args, 1, yarray);
1587 PyTuple_SetItem(plot_args, 2, zarray);
1588 PyTuple_SetItem(plot_args, 3, uarray);
1589 PyTuple_SetItem(plot_args, 4, warray);
1590 PyTuple_SetItem(plot_args, 5, varray);
1591
1592 // construct keyword args
1593 PyObject *kwargs = PyDict_New();
1594 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
1595 it != keywords.end(); ++it) {
1596 PyDict_SetItemString(kwargs, it->first.c_str(),
1597 PyUnicode_FromString(it->second.c_str()));
1598 }
1599
1600 // get figure gca to enable 3d projection
1601 PyObject *fig =
1602 PyObject_CallObject(detail::_interpreter::get().s_python_function_figure,
1603 detail::_interpreter::get().s_python_empty_tuple);
1604 if (!fig)
1605 throw std::runtime_error("Call to figure() failed.");
1606
1607 PyObject *gca_kwargs = PyDict_New();
1608 PyDict_SetItemString(gca_kwargs, "projection", PyString_FromString("3d"));
1609
1610 PyObject *gca = PyObject_GetAttrString(fig, "gca");
1611 if (!gca)
1612 throw std::runtime_error("No gca");
1613 Py_INCREF(gca);
1614 PyObject *axis = PyObject_Call(
1615 gca, detail::_interpreter::get().s_python_empty_tuple, gca_kwargs);
1616
1617 if (!axis)
1618 throw std::runtime_error("No axis");
1619 Py_INCREF(axis);
1620 Py_DECREF(gca);
1621 Py_DECREF(gca_kwargs);
1622
1623 // plot our boys bravely, plot them strongly, plot them with a wink and clap
1624 PyObject *plot3 = PyObject_GetAttrString(axis, "quiver");
1625 if (!plot3)
1626 throw std::runtime_error("No 3D line plot");
1627 Py_INCREF(plot3);
1628 PyObject *res = PyObject_Call(plot3, plot_args, kwargs);
1629 if (!res)
1630 throw std::runtime_error("Failed 3D plot");
1631 Py_DECREF(plot3);
1632 Py_DECREF(axis);
1633 Py_DECREF(kwargs);
1634 Py_DECREF(plot_args);
1635 if (res)
1636 Py_DECREF(res);
1637
1638 return res;
1639}
1640
1641template <typename NumericX, typename NumericY>
1642bool stem(const std::vector<NumericX> &x, const std::vector<NumericY> &y,
1643 const std::string &s = "") {
1644 assert(x.size() == y.size());
1645
1647
1648 PyObject *xarray = detail::get_array(x);
1649 PyObject *yarray = detail::get_array(y);
1650
1651 PyObject *pystring = PyString_FromString(s.c_str());
1652
1653 PyObject *plot_args = PyTuple_New(3);
1654 PyTuple_SetItem(plot_args, 0, xarray);
1655 PyTuple_SetItem(plot_args, 1, yarray);
1656 PyTuple_SetItem(plot_args, 2, pystring);
1657
1658 PyObject *res = PyObject_CallObject(
1659 detail::_interpreter::get().s_python_function_stem, plot_args);
1660
1661 Py_DECREF(plot_args);
1662 if (res)
1663 Py_DECREF(res);
1664
1665 return res;
1666}
1667
1668template <typename NumericX, typename NumericY>
1669bool semilogx(const std::vector<NumericX> &x, const std::vector<NumericY> &y,
1670 const std::string &s = "") {
1671 assert(x.size() == y.size());
1672
1674
1675 PyObject *xarray = detail::get_array(x);
1676 PyObject *yarray = detail::get_array(y);
1677
1678 PyObject *pystring = PyString_FromString(s.c_str());
1679
1680 PyObject *plot_args = PyTuple_New(3);
1681 PyTuple_SetItem(plot_args, 0, xarray);
1682 PyTuple_SetItem(plot_args, 1, yarray);
1683 PyTuple_SetItem(plot_args, 2, pystring);
1684
1685 PyObject *res = PyObject_CallObject(
1686 detail::_interpreter::get().s_python_function_semilogx, plot_args);
1687
1688 Py_DECREF(plot_args);
1689 if (res)
1690 Py_DECREF(res);
1691
1692 return res;
1693}
1694
1695template <typename NumericX, typename NumericY>
1696bool semilogy(const std::vector<NumericX> &x, const std::vector<NumericY> &y,
1697 const std::string &s = "") {
1698 assert(x.size() == y.size());
1699
1701
1702 PyObject *xarray = detail::get_array(x);
1703 PyObject *yarray = detail::get_array(y);
1704
1705 PyObject *pystring = PyString_FromString(s.c_str());
1706
1707 PyObject *plot_args = PyTuple_New(3);
1708 PyTuple_SetItem(plot_args, 0, xarray);
1709 PyTuple_SetItem(plot_args, 1, yarray);
1710 PyTuple_SetItem(plot_args, 2, pystring);
1711
1712 PyObject *res = PyObject_CallObject(
1713 detail::_interpreter::get().s_python_function_semilogy, plot_args);
1714
1715 Py_DECREF(plot_args);
1716 if (res)
1717 Py_DECREF(res);
1718
1719 return res;
1720}
1721
1722template <typename NumericX, typename NumericY>
1723bool loglog(const std::vector<NumericX> &x, const std::vector<NumericY> &y,
1724 const std::string &s = "") {
1725 assert(x.size() == y.size());
1726
1728
1729 PyObject *xarray = detail::get_array(x);
1730 PyObject *yarray = detail::get_array(y);
1731
1732 PyObject *pystring = PyString_FromString(s.c_str());
1733
1734 PyObject *plot_args = PyTuple_New(3);
1735 PyTuple_SetItem(plot_args, 0, xarray);
1736 PyTuple_SetItem(plot_args, 1, yarray);
1737 PyTuple_SetItem(plot_args, 2, pystring);
1738
1739 PyObject *res = PyObject_CallObject(
1740 detail::_interpreter::get().s_python_function_loglog, plot_args);
1741
1742 Py_DECREF(plot_args);
1743 if (res)
1744 Py_DECREF(res);
1745
1746 return res;
1747}
1748
1749template <typename NumericX, typename NumericY>
1750bool errorbar(const std::vector<NumericX> &x, const std::vector<NumericY> &y,
1751 const std::vector<NumericX> &yerr,
1752 const std::map<std::string, std::string> &keywords = {}) {
1753 assert(x.size() == y.size());
1754
1756
1757 PyObject *xarray = detail::get_array(x);
1758 PyObject *yarray = detail::get_array(y);
1759 PyObject *yerrarray = detail::get_array(yerr);
1760
1761 // construct keyword args
1762 PyObject *kwargs = PyDict_New();
1763 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
1764 it != keywords.end(); ++it) {
1765 PyDict_SetItemString(kwargs, it->first.c_str(),
1766 PyString_FromString(it->second.c_str()));
1767 }
1768
1769 PyDict_SetItemString(kwargs, "yerr", yerrarray);
1770
1771 PyObject *plot_args = PyTuple_New(2);
1772 PyTuple_SetItem(plot_args, 0, xarray);
1773 PyTuple_SetItem(plot_args, 1, yarray);
1774
1775 PyObject *res =
1776 PyObject_Call(detail::_interpreter::get().s_python_function_errorbar,
1777 plot_args, kwargs);
1778
1779 Py_DECREF(kwargs);
1780 Py_DECREF(plot_args);
1781
1782 if (res)
1783 Py_DECREF(res);
1784 else
1785 throw std::runtime_error("Call to errorbar() failed.");
1786
1787 return res;
1788}
1789
1790template <typename Numeric>
1791bool named_plot(const std::string &name, const std::vector<Numeric> &y,
1792 const std::string &format = "") {
1794
1795 PyObject *kwargs = PyDict_New();
1796 PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str()));
1797
1798 PyObject *yarray = detail::get_array(y);
1799
1800 PyObject *pystring = PyString_FromString(format.c_str());
1801
1802 PyObject *plot_args = PyTuple_New(2);
1803
1804 PyTuple_SetItem(plot_args, 0, yarray);
1805 PyTuple_SetItem(plot_args, 1, pystring);
1806
1807 PyObject *res = PyObject_Call(
1808 detail::_interpreter::get().s_python_function_plot, plot_args, kwargs);
1809
1810 Py_DECREF(kwargs);
1811 Py_DECREF(plot_args);
1812 if (res)
1813 Py_DECREF(res);
1814
1815 return res;
1816}
1817
1818template <typename NumericX, typename NumericY>
1819bool named_plot(const std::string &name, const std::vector<NumericX> &x,
1820 const std::vector<NumericY> &y,
1821 const std::string &format = "") {
1823
1824 PyObject *kwargs = PyDict_New();
1825 PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str()));
1826
1827 PyObject *xarray = detail::get_array(x);
1828 PyObject *yarray = detail::get_array(y);
1829
1830 PyObject *pystring = PyString_FromString(format.c_str());
1831
1832 PyObject *plot_args = PyTuple_New(3);
1833 PyTuple_SetItem(plot_args, 0, xarray);
1834 PyTuple_SetItem(plot_args, 1, yarray);
1835 PyTuple_SetItem(plot_args, 2, pystring);
1836
1837 PyObject *res = PyObject_Call(
1838 detail::_interpreter::get().s_python_function_plot, plot_args, kwargs);
1839
1840 Py_DECREF(kwargs);
1841 Py_DECREF(plot_args);
1842 if (res)
1843 Py_DECREF(res);
1844
1845 return res;
1846}
1847
1848template <typename NumericX, typename NumericY>
1849bool named_semilogx(const std::string &name, const std::vector<NumericX> &x,
1850 const std::vector<NumericY> &y,
1851 const std::string &format = "") {
1853
1854 PyObject *kwargs = PyDict_New();
1855 PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str()));
1856
1857 PyObject *xarray = detail::get_array(x);
1858 PyObject *yarray = detail::get_array(y);
1859
1860 PyObject *pystring = PyString_FromString(format.c_str());
1861
1862 PyObject *plot_args = PyTuple_New(3);
1863 PyTuple_SetItem(plot_args, 0, xarray);
1864 PyTuple_SetItem(plot_args, 1, yarray);
1865 PyTuple_SetItem(plot_args, 2, pystring);
1866
1867 PyObject *res =
1868 PyObject_Call(detail::_interpreter::get().s_python_function_semilogx,
1869 plot_args, kwargs);
1870
1871 Py_DECREF(kwargs);
1872 Py_DECREF(plot_args);
1873 if (res)
1874 Py_DECREF(res);
1875
1876 return res;
1877}
1878
1879template <typename NumericX, typename NumericY>
1880bool named_semilogy(const std::string &name, const std::vector<NumericX> &x,
1881 const std::vector<NumericY> &y,
1882 const std::string &format = "") {
1884
1885 PyObject *kwargs = PyDict_New();
1886 PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str()));
1887
1888 PyObject *xarray = detail::get_array(x);
1889 PyObject *yarray = detail::get_array(y);
1890
1891 PyObject *pystring = PyString_FromString(format.c_str());
1892
1893 PyObject *plot_args = PyTuple_New(3);
1894 PyTuple_SetItem(plot_args, 0, xarray);
1895 PyTuple_SetItem(plot_args, 1, yarray);
1896 PyTuple_SetItem(plot_args, 2, pystring);
1897
1898 PyObject *res =
1899 PyObject_Call(detail::_interpreter::get().s_python_function_semilogy,
1900 plot_args, kwargs);
1901
1902 Py_DECREF(kwargs);
1903 Py_DECREF(plot_args);
1904 if (res)
1905 Py_DECREF(res);
1906
1907 return res;
1908}
1909
1910template <typename NumericX, typename NumericY>
1911bool named_loglog(const std::string &name, const std::vector<NumericX> &x,
1912 const std::vector<NumericY> &y,
1913 const std::string &format = "") {
1915
1916 PyObject *kwargs = PyDict_New();
1917 PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str()));
1918
1919 PyObject *xarray = detail::get_array(x);
1920 PyObject *yarray = detail::get_array(y);
1921
1922 PyObject *pystring = PyString_FromString(format.c_str());
1923
1924 PyObject *plot_args = PyTuple_New(3);
1925 PyTuple_SetItem(plot_args, 0, xarray);
1926 PyTuple_SetItem(plot_args, 1, yarray);
1927 PyTuple_SetItem(plot_args, 2, pystring);
1928 PyObject *res = PyObject_Call(
1929 detail::_interpreter::get().s_python_function_loglog, plot_args, kwargs);
1930
1931 Py_DECREF(kwargs);
1932 Py_DECREF(plot_args);
1933 if (res)
1934 Py_DECREF(res);
1935
1936 return res;
1937}
1938
1939template <typename Numeric>
1940bool plot(const std::vector<Numeric> &y, const std::string &format = "") {
1941 std::vector<Numeric> x(y.size());
1942 for (size_t i = 0; i < x.size(); ++i)
1943 x.at(i) = i;
1944 return plot(x, y, format);
1945}
1946
1947template <typename Numeric>
1948bool plot(const std::vector<Numeric> &y,
1949 const std::map<std::string, std::string> &keywords) {
1950 std::vector<Numeric> x(y.size());
1951 for (size_t i = 0; i < x.size(); ++i)
1952 x.at(i) = i;
1953 return plot(x, y, keywords);
1954}
1955
1956template <typename Numeric>
1957bool stem(const std::vector<Numeric> &y, const std::string &format = "") {
1958 std::vector<Numeric> x(y.size());
1959 for (size_t i = 0; i < x.size(); ++i)
1960 x.at(i) = i;
1961 return stem(x, y, format);
1962}
1963
1964template <typename Numeric>
1965void text(Numeric x, Numeric y, const std::string &s = "") {
1967
1968 PyObject *args = PyTuple_New(3);
1969 PyTuple_SetItem(args, 0, PyFloat_FromDouble(x));
1970 PyTuple_SetItem(args, 1, PyFloat_FromDouble(y));
1971 PyTuple_SetItem(args, 2, PyString_FromString(s.c_str()));
1972
1973 PyObject *res = PyObject_CallObject(
1974 detail::_interpreter::get().s_python_function_text, args);
1975 if (!res)
1976 throw std::runtime_error("Call to text() failed.");
1977
1978 Py_DECREF(args);
1979 Py_DECREF(res);
1980}
1981
1982inline void colorbar(PyObject *mappable = NULL,
1983 const std::map<std::string, float> &keywords = {}) {
1984 if (mappable == NULL)
1985 throw std::runtime_error("Must call colorbar with PyObject* returned from "
1986 "an image, contour, surface, etc.");
1987
1989
1990 PyObject *args = PyTuple_New(1);
1991 PyTuple_SetItem(args, 0, mappable);
1992
1993 PyObject *kwargs = PyDict_New();
1994 for (std::map<std::string, float>::const_iterator it = keywords.begin();
1995 it != keywords.end(); ++it) {
1996 PyDict_SetItemString(kwargs, it->first.c_str(),
1997 PyFloat_FromDouble(it->second));
1998 }
1999
2000 PyObject *res = PyObject_Call(
2001 detail::_interpreter::get().s_python_function_colorbar, args, kwargs);
2002 if (!res)
2003 throw std::runtime_error("Call to colorbar() failed.");
2004
2005 Py_DECREF(args);
2006 Py_DECREF(kwargs);
2007 Py_DECREF(res);
2008}
2009
2010inline long figure(long number = -1) {
2012
2013 PyObject *res;
2014 if (number == -1)
2015 res = PyObject_CallObject(
2016 detail::_interpreter::get().s_python_function_figure,
2017 detail::_interpreter::get().s_python_empty_tuple);
2018 else {
2019 assert(number > 0);
2020
2021 // Make sure interpreter is initialised
2023
2024 PyObject *args = PyTuple_New(1);
2025 PyTuple_SetItem(args, 0, PyLong_FromLong(number));
2026 res = PyObject_CallObject(
2027 detail::_interpreter::get().s_python_function_figure, args);
2028 Py_DECREF(args);
2029 }
2030
2031 if (!res)
2032 throw std::runtime_error("Call to figure() failed.");
2033
2034 PyObject *num = PyObject_GetAttrString(res, "number");
2035 if (!num)
2036 throw std::runtime_error("Could not get number attribute of figure object");
2037 const long figureNumber = PyLong_AsLong(num);
2038
2039 Py_DECREF(num);
2040 Py_DECREF(res);
2041
2042 return figureNumber;
2043}
2044
2045inline bool fignum_exists(long number) {
2047
2048 PyObject *args = PyTuple_New(1);
2049 PyTuple_SetItem(args, 0, PyLong_FromLong(number));
2050 PyObject *res = PyObject_CallObject(
2051 detail::_interpreter::get().s_python_function_fignum_exists, args);
2052 if (!res)
2053 throw std::runtime_error("Call to fignum_exists() failed.");
2054
2055 bool ret = PyObject_IsTrue(res);
2056 Py_DECREF(res);
2057 Py_DECREF(args);
2058
2059 return ret;
2060}
2061
2062inline void figure_size(size_t w, size_t h) {
2064
2065 const size_t dpi = 100;
2066 PyObject *size = PyTuple_New(2);
2067 PyTuple_SetItem(size, 0, PyFloat_FromDouble((double)w / dpi));
2068 PyTuple_SetItem(size, 1, PyFloat_FromDouble((double)h / dpi));
2069
2070 PyObject *kwargs = PyDict_New();
2071 PyDict_SetItemString(kwargs, "figsize", size);
2072 PyDict_SetItemString(kwargs, "dpi", PyLong_FromSize_t(dpi));
2073
2074 PyObject *res =
2075 PyObject_Call(detail::_interpreter::get().s_python_function_figure,
2076 detail::_interpreter::get().s_python_empty_tuple, kwargs);
2077
2078 Py_DECREF(kwargs);
2079
2080 if (!res)
2081 throw std::runtime_error("Call to figure_size() failed.");
2082 Py_DECREF(res);
2083}
2084
2085inline void legend() {
2087
2088 PyObject *res =
2089 PyObject_CallObject(detail::_interpreter::get().s_python_function_legend,
2090 detail::_interpreter::get().s_python_empty_tuple);
2091 if (!res)
2092 throw std::runtime_error("Call to legend() failed.");
2093
2094 Py_DECREF(res);
2095}
2096
2097inline void legend(const std::map<std::string, std::string> &keywords) {
2099
2100 // construct keyword args
2101 PyObject *kwargs = PyDict_New();
2102 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
2103 it != keywords.end(); ++it) {
2104 PyDict_SetItemString(kwargs, it->first.c_str(),
2105 PyString_FromString(it->second.c_str()));
2106 }
2107
2108 PyObject *res =
2109 PyObject_Call(detail::_interpreter::get().s_python_function_legend,
2110 detail::_interpreter::get().s_python_empty_tuple, kwargs);
2111 if (!res)
2112 throw std::runtime_error("Call to legend() failed.");
2113
2114 Py_DECREF(kwargs);
2115 Py_DECREF(res);
2116}
2117
2118template <typename Numeric> inline void set_aspect(Numeric ratio) {
2120
2121 PyObject *args = PyTuple_New(1);
2122 PyTuple_SetItem(args, 0, PyFloat_FromDouble(ratio));
2123 PyObject *kwargs = PyDict_New();
2124
2125 PyObject *ax =
2126 PyObject_CallObject(detail::_interpreter::get().s_python_function_gca,
2127 detail::_interpreter::get().s_python_empty_tuple);
2128 if (!ax)
2129 throw std::runtime_error("Call to gca() failed.");
2130 Py_INCREF(ax);
2131
2132 PyObject *set_aspect = PyObject_GetAttrString(ax, "set_aspect");
2133 if (!set_aspect)
2134 throw std::runtime_error("Attribute set_aspect not found.");
2135 Py_INCREF(set_aspect);
2136
2137 PyObject *res = PyObject_Call(set_aspect, args, kwargs);
2138 if (!res)
2139 throw std::runtime_error("Call to set_aspect() failed.");
2140 Py_DECREF(set_aspect);
2141
2142 Py_DECREF(ax);
2143 Py_DECREF(args);
2144 Py_DECREF(kwargs);
2145}
2146
2147inline void set_aspect_equal() {
2148 // expect ratio == "equal". Leaving error handling to matplotlib.
2150
2151 PyObject *args = PyTuple_New(1);
2152 PyTuple_SetItem(args, 0, PyString_FromString("equal"));
2153 PyObject *kwargs = PyDict_New();
2154
2155 PyObject *ax =
2156 PyObject_CallObject(detail::_interpreter::get().s_python_function_gca,
2157 detail::_interpreter::get().s_python_empty_tuple);
2158 if (!ax)
2159 throw std::runtime_error("Call to gca() failed.");
2160 Py_INCREF(ax);
2161
2162 PyObject *set_aspect = PyObject_GetAttrString(ax, "set_aspect");
2163 if (!set_aspect)
2164 throw std::runtime_error("Attribute set_aspect not found.");
2165 Py_INCREF(set_aspect);
2166
2167 PyObject *res = PyObject_Call(set_aspect, args, kwargs);
2168 if (!res)
2169 throw std::runtime_error("Call to set_aspect() failed.");
2170 Py_DECREF(set_aspect);
2171
2172 Py_DECREF(ax);
2173 Py_DECREF(args);
2174 Py_DECREF(kwargs);
2175}
2176
2177template <typename Numeric> void ylim(Numeric left, Numeric right) {
2179
2180 PyObject *list = PyList_New(2);
2181 PyList_SetItem(list, 0, PyFloat_FromDouble(left));
2182 PyList_SetItem(list, 1, PyFloat_FromDouble(right));
2183
2184 PyObject *args = PyTuple_New(1);
2185 PyTuple_SetItem(args, 0, list);
2186
2187 PyObject *res = PyObject_CallObject(
2188 detail::_interpreter::get().s_python_function_ylim, args);
2189 if (!res)
2190 throw std::runtime_error("Call to ylim() failed.");
2191
2192 Py_DECREF(args);
2193 Py_DECREF(res);
2194}
2195
2196template <typename Numeric> void xlim(Numeric left, Numeric right) {
2198
2199 PyObject *list = PyList_New(2);
2200 PyList_SetItem(list, 0, PyFloat_FromDouble(left));
2201 PyList_SetItem(list, 1, PyFloat_FromDouble(right));
2202
2203 PyObject *args = PyTuple_New(1);
2204 PyTuple_SetItem(args, 0, list);
2205
2206 PyObject *res = PyObject_CallObject(
2207 detail::_interpreter::get().s_python_function_xlim, args);
2208 if (!res)
2209 throw std::runtime_error("Call to xlim() failed.");
2210
2211 Py_DECREF(args);
2212 Py_DECREF(res);
2213}
2214
2215inline std::array<double, 2> xlim() {
2216 PyObject *args = PyTuple_New(0);
2217 PyObject *res = PyObject_CallObject(
2218 detail::_interpreter::get().s_python_function_xlim, args);
2219
2220 if (!res)
2221 throw std::runtime_error("Call to xlim() failed.");
2222
2223 Py_DECREF(res);
2224
2225 PyObject *left = PyTuple_GetItem(res, 0);
2226 PyObject *right = PyTuple_GetItem(res, 1);
2227 return {PyFloat_AsDouble(left), PyFloat_AsDouble(right)};
2228}
2229
2230inline std::array<double, 2> ylim() {
2231 PyObject *args = PyTuple_New(0);
2232 PyObject *res = PyObject_CallObject(
2233 detail::_interpreter::get().s_python_function_ylim, args);
2234
2235 if (!res)
2236 throw std::runtime_error("Call to ylim() failed.");
2237
2238 Py_DECREF(res);
2239
2240 PyObject *left = PyTuple_GetItem(res, 0);
2241 PyObject *right = PyTuple_GetItem(res, 1);
2242 return {PyFloat_AsDouble(left), PyFloat_AsDouble(right)};
2243}
2244
2245template <typename Numeric>
2246inline void xticks(const std::vector<Numeric> &ticks,
2247 const std::vector<std::string> &labels = {},
2248 const std::map<std::string, std::string> &keywords = {}) {
2249 assert(labels.size() == 0 || ticks.size() == labels.size());
2250
2252
2253 // using numpy array
2254 PyObject *ticksarray = detail::get_array(ticks);
2255
2256 PyObject *args;
2257 if (labels.size() == 0) {
2258 // construct positional args
2259 args = PyTuple_New(1);
2260 PyTuple_SetItem(args, 0, ticksarray);
2261 } else {
2262 // make tuple of tick labels
2263 PyObject *labelstuple = PyTuple_New(labels.size());
2264 for (size_t i = 0; i < labels.size(); i++)
2265 PyTuple_SetItem(labelstuple, i, PyUnicode_FromString(labels[i].c_str()));
2266
2267 // construct positional args
2268 args = PyTuple_New(2);
2269 PyTuple_SetItem(args, 0, ticksarray);
2270 PyTuple_SetItem(args, 1, labelstuple);
2271 }
2272
2273 // construct keyword args
2274 PyObject *kwargs = PyDict_New();
2275 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
2276 it != keywords.end(); ++it) {
2277 PyDict_SetItemString(kwargs, it->first.c_str(),
2278 PyString_FromString(it->second.c_str()));
2279 }
2280
2281 PyObject *res = PyObject_Call(
2282 detail::_interpreter::get().s_python_function_xticks, args, kwargs);
2283
2284 Py_DECREF(args);
2285 Py_DECREF(kwargs);
2286 if (!res)
2287 throw std::runtime_error("Call to xticks() failed");
2288
2289 Py_DECREF(res);
2290}
2291
2292template <typename Numeric>
2293inline void xticks(const std::vector<Numeric> &ticks,
2294 const std::map<std::string, std::string> &keywords) {
2295 xticks(ticks, {}, keywords);
2296}
2297
2298template <typename Numeric>
2299inline void yticks(const std::vector<Numeric> &ticks,
2300 const std::vector<std::string> &labels = {},
2301 const std::map<std::string, std::string> &keywords = {}) {
2302 assert(labels.size() == 0 || ticks.size() == labels.size());
2303
2305
2306 // using numpy array
2307 PyObject *ticksarray = detail::get_array(ticks);
2308
2309 PyObject *args;
2310 if (labels.size() == 0) {
2311 // construct positional args
2312 args = PyTuple_New(1);
2313 PyTuple_SetItem(args, 0, ticksarray);
2314 } else {
2315 // make tuple of tick labels
2316 PyObject *labelstuple = PyTuple_New(labels.size());
2317 for (size_t i = 0; i < labels.size(); i++)
2318 PyTuple_SetItem(labelstuple, i, PyUnicode_FromString(labels[i].c_str()));
2319
2320 // construct positional args
2321 args = PyTuple_New(2);
2322 PyTuple_SetItem(args, 0, ticksarray);
2323 PyTuple_SetItem(args, 1, labelstuple);
2324 }
2325
2326 // construct keyword args
2327 PyObject *kwargs = PyDict_New();
2328 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
2329 it != keywords.end(); ++it) {
2330 PyDict_SetItemString(kwargs, it->first.c_str(),
2331 PyString_FromString(it->second.c_str()));
2332 }
2333
2334 PyObject *res = PyObject_Call(
2335 detail::_interpreter::get().s_python_function_yticks, args, kwargs);
2336
2337 Py_DECREF(args);
2338 Py_DECREF(kwargs);
2339 if (!res)
2340 throw std::runtime_error("Call to yticks() failed");
2341
2342 Py_DECREF(res);
2343}
2344
2345template <typename Numeric>
2346inline void yticks(const std::vector<Numeric> &ticks,
2347 const std::map<std::string, std::string> &keywords) {
2348 yticks(ticks, {}, keywords);
2349}
2350
2351template <typename Numeric> inline void margins(Numeric margin) {
2352 // construct positional args
2353 PyObject *args = PyTuple_New(1);
2354 PyTuple_SetItem(args, 0, PyFloat_FromDouble(margin));
2355
2356 PyObject *res = PyObject_CallObject(
2357 detail::_interpreter::get().s_python_function_margins, args);
2358 if (!res)
2359 throw std::runtime_error("Call to margins() failed.");
2360
2361 Py_DECREF(args);
2362 Py_DECREF(res);
2363}
2364
2365template <typename Numeric>
2366inline void margins(Numeric margin_x, Numeric margin_y) {
2367 // construct positional args
2368 PyObject *args = PyTuple_New(2);
2369 PyTuple_SetItem(args, 0, PyFloat_FromDouble(margin_x));
2370 PyTuple_SetItem(args, 1, PyFloat_FromDouble(margin_y));
2371
2372 PyObject *res = PyObject_CallObject(
2373 detail::_interpreter::get().s_python_function_margins, args);
2374 if (!res)
2375 throw std::runtime_error("Call to margins() failed.");
2376
2377 Py_DECREF(args);
2378 Py_DECREF(res);
2379}
2380
2381inline void tick_params(const std::map<std::string, std::string> &keywords,
2382 const std::string axis = "both") {
2384
2385 // construct positional args
2386 PyObject *args;
2387 args = PyTuple_New(1);
2388 PyTuple_SetItem(args, 0, PyString_FromString(axis.c_str()));
2389
2390 // construct keyword args
2391 PyObject *kwargs = PyDict_New();
2392 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
2393 it != keywords.end(); ++it) {
2394 PyDict_SetItemString(kwargs, it->first.c_str(),
2395 PyString_FromString(it->second.c_str()));
2396 }
2397
2398 PyObject *res = PyObject_Call(
2399 detail::_interpreter::get().s_python_function_tick_params, args, kwargs);
2400
2401 Py_DECREF(args);
2402 Py_DECREF(kwargs);
2403 if (!res)
2404 throw std::runtime_error("Call to tick_params() failed");
2405
2406 Py_DECREF(res);
2407}
2408
2409inline void subplot(long nrows, long ncols, long plot_number) {
2411
2412 // construct positional args
2413 PyObject *args = PyTuple_New(3);
2414 PyTuple_SetItem(args, 0, PyFloat_FromDouble(nrows));
2415 PyTuple_SetItem(args, 1, PyFloat_FromDouble(ncols));
2416 PyTuple_SetItem(args, 2, PyFloat_FromDouble(plot_number));
2417
2418 PyObject *res = PyObject_CallObject(
2419 detail::_interpreter::get().s_python_function_subplot, args);
2420 if (!res)
2421 throw std::runtime_error("Call to subplot() failed.");
2422
2423 Py_DECREF(args);
2424 Py_DECREF(res);
2425}
2426
2427inline void subplot2grid(long nrows, long ncols, long rowid = 0, long colid = 0,
2428 long rowspan = 1, long colspan = 1) {
2430
2431 PyObject *shape = PyTuple_New(2);
2432 PyTuple_SetItem(shape, 0, PyLong_FromLong(nrows));
2433 PyTuple_SetItem(shape, 1, PyLong_FromLong(ncols));
2434
2435 PyObject *loc = PyTuple_New(2);
2436 PyTuple_SetItem(loc, 0, PyLong_FromLong(rowid));
2437 PyTuple_SetItem(loc, 1, PyLong_FromLong(colid));
2438
2439 PyObject *args = PyTuple_New(4);
2440 PyTuple_SetItem(args, 0, shape);
2441 PyTuple_SetItem(args, 1, loc);
2442 PyTuple_SetItem(args, 2, PyLong_FromLong(rowspan));
2443 PyTuple_SetItem(args, 3, PyLong_FromLong(colspan));
2444
2445 PyObject *res = PyObject_CallObject(
2446 detail::_interpreter::get().s_python_function_subplot2grid, args);
2447 if (!res)
2448 throw std::runtime_error("Call to subplot2grid() failed.");
2449
2450 Py_DECREF(shape);
2451 Py_DECREF(loc);
2452 Py_DECREF(args);
2453 Py_DECREF(res);
2454}
2455
2456inline void title(const std::string &titlestr,
2457 const std::map<std::string, std::string> &keywords = {}) {
2459
2460 PyObject *pytitlestr = PyString_FromString(titlestr.c_str());
2461 PyObject *args = PyTuple_New(1);
2462 PyTuple_SetItem(args, 0, pytitlestr);
2463
2464 PyObject *kwargs = PyDict_New();
2465 for (auto it = keywords.begin(); it != keywords.end(); ++it) {
2466 PyDict_SetItemString(kwargs, it->first.c_str(),
2467 PyUnicode_FromString(it->second.c_str()));
2468 }
2469
2470 PyObject *res = PyObject_Call(
2471 detail::_interpreter::get().s_python_function_title, args, kwargs);
2472 if (!res)
2473 throw std::runtime_error("Call to title() failed.");
2474
2475 Py_DECREF(args);
2476 Py_DECREF(kwargs);
2477 Py_DECREF(res);
2478}
2479
2480inline void suptitle(const std::string &suptitlestr,
2481 const std::map<std::string, std::string> &keywords = {}) {
2483
2484 PyObject *pysuptitlestr = PyString_FromString(suptitlestr.c_str());
2485 PyObject *args = PyTuple_New(1);
2486 PyTuple_SetItem(args, 0, pysuptitlestr);
2487
2488 PyObject *kwargs = PyDict_New();
2489 for (auto it = keywords.begin(); it != keywords.end(); ++it) {
2490 PyDict_SetItemString(kwargs, it->first.c_str(),
2491 PyUnicode_FromString(it->second.c_str()));
2492 }
2493
2494 PyObject *res = PyObject_Call(
2495 detail::_interpreter::get().s_python_function_suptitle, args, kwargs);
2496 if (!res)
2497 throw std::runtime_error("Call to suptitle() failed.");
2498
2499 Py_DECREF(args);
2500 Py_DECREF(kwargs);
2501 Py_DECREF(res);
2502}
2503
2504inline void axis(const std::string &axisstr) {
2506
2507 PyObject *str = PyString_FromString(axisstr.c_str());
2508 PyObject *args = PyTuple_New(1);
2509 PyTuple_SetItem(args, 0, str);
2510
2511 PyObject *res = PyObject_CallObject(
2512 detail::_interpreter::get().s_python_function_axis, args);
2513 if (!res)
2514 throw std::runtime_error("Call to title() failed.");
2515
2516 Py_DECREF(args);
2517 Py_DECREF(res);
2518}
2519
2520inline void axhline(double y, double xmin = 0., double xmax = 1.,
2521 const std::map<std::string, std::string> &keywords =
2522 std::map<std::string, std::string>()) {
2524
2525 // construct positional args
2526 PyObject *args = PyTuple_New(3);
2527 PyTuple_SetItem(args, 0, PyFloat_FromDouble(y));
2528 PyTuple_SetItem(args, 1, PyFloat_FromDouble(xmin));
2529 PyTuple_SetItem(args, 2, PyFloat_FromDouble(xmax));
2530
2531 // construct keyword args
2532 PyObject *kwargs = PyDict_New();
2533 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
2534 it != keywords.end(); ++it) {
2535 PyDict_SetItemString(kwargs, it->first.c_str(),
2536 PyString_FromString(it->second.c_str()));
2537 }
2538
2539 PyObject *res = PyObject_Call(
2540 detail::_interpreter::get().s_python_function_axhline, args, kwargs);
2541
2542 Py_DECREF(args);
2543 Py_DECREF(kwargs);
2544
2545 if (res)
2546 Py_DECREF(res);
2547}
2548
2549inline void axvline(double x, double ymin = 0., double ymax = 1.,
2550 const std::map<std::string, std::string> &keywords =
2551 std::map<std::string, std::string>()) {
2553
2554 // construct positional args
2555 PyObject *args = PyTuple_New(3);
2556 PyTuple_SetItem(args, 0, PyFloat_FromDouble(x));
2557 PyTuple_SetItem(args, 1, PyFloat_FromDouble(ymin));
2558 PyTuple_SetItem(args, 2, PyFloat_FromDouble(ymax));
2559
2560 // construct keyword args
2561 PyObject *kwargs = PyDict_New();
2562 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
2563 it != keywords.end(); ++it) {
2564 PyDict_SetItemString(kwargs, it->first.c_str(),
2565 PyString_FromString(it->second.c_str()));
2566 }
2567
2568 PyObject *res = PyObject_Call(
2569 detail::_interpreter::get().s_python_function_axvline, args, kwargs);
2570
2571 Py_DECREF(args);
2572 Py_DECREF(kwargs);
2573
2574 if (res)
2575 Py_DECREF(res);
2576}
2577
2578inline void axvspan(double xmin, double xmax, double ymin = 0.,
2579 double ymax = 1.,
2580 const std::map<std::string, std::string> &keywords =
2581 std::map<std::string, std::string>()) {
2582 // construct positional args
2583 PyObject *args = PyTuple_New(4);
2584 PyTuple_SetItem(args, 0, PyFloat_FromDouble(xmin));
2585 PyTuple_SetItem(args, 1, PyFloat_FromDouble(xmax));
2586 PyTuple_SetItem(args, 2, PyFloat_FromDouble(ymin));
2587 PyTuple_SetItem(args, 3, PyFloat_FromDouble(ymax));
2588
2589 // construct keyword args
2590 PyObject *kwargs = PyDict_New();
2591 for (auto it = keywords.begin(); it != keywords.end(); ++it) {
2592 if (it->first == "linewidth" || it->first == "alpha") {
2593 PyDict_SetItemString(kwargs, it->first.c_str(),
2594 PyFloat_FromDouble(std::stod(it->second)));
2595 } else {
2596 PyDict_SetItemString(kwargs, it->first.c_str(),
2597 PyString_FromString(it->second.c_str()));
2598 }
2599 }
2600
2601 PyObject *res = PyObject_Call(
2602 detail::_interpreter::get().s_python_function_axvspan, args, kwargs);
2603 Py_DECREF(args);
2604 Py_DECREF(kwargs);
2605
2606 if (res)
2607 Py_DECREF(res);
2608}
2609
2610inline void xlabel(const std::string &str,
2611 const std::map<std::string, std::string> &keywords = {}) {
2613
2614 PyObject *pystr = PyString_FromString(str.c_str());
2615 PyObject *args = PyTuple_New(1);
2616 PyTuple_SetItem(args, 0, pystr);
2617
2618 PyObject *kwargs = PyDict_New();
2619 for (auto it = keywords.begin(); it != keywords.end(); ++it) {
2620 PyDict_SetItemString(kwargs, it->first.c_str(),
2621 PyUnicode_FromString(it->second.c_str()));
2622 }
2623
2624 PyObject *res = PyObject_Call(
2625 detail::_interpreter::get().s_python_function_xlabel, args, kwargs);
2626 if (!res)
2627 throw std::runtime_error("Call to xlabel() failed.");
2628
2629 Py_DECREF(args);
2630 Py_DECREF(kwargs);
2631 Py_DECREF(res);
2632}
2633
2634inline void ylabel(const std::string &str,
2635 const std::map<std::string, std::string> &keywords = {}) {
2637
2638 PyObject *pystr = PyString_FromString(str.c_str());
2639 PyObject *args = PyTuple_New(1);
2640 PyTuple_SetItem(args, 0, pystr);
2641
2642 PyObject *kwargs = PyDict_New();
2643 for (auto it = keywords.begin(); it != keywords.end(); ++it) {
2644 PyDict_SetItemString(kwargs, it->first.c_str(),
2645 PyUnicode_FromString(it->second.c_str()));
2646 }
2647
2648 PyObject *res = PyObject_Call(
2649 detail::_interpreter::get().s_python_function_ylabel, args, kwargs);
2650 if (!res)
2651 throw std::runtime_error("Call to ylabel() failed.");
2652
2653 Py_DECREF(args);
2654 Py_DECREF(kwargs);
2655 Py_DECREF(res);
2656}
2657
2658inline void
2659set_zlabel(const std::string &str,
2660 const std::map<std::string, std::string> &keywords = {}) {
2662
2663 // Same as with plot_surface: We lazily load the modules here the first time
2664 // this function is called because I'm not sure that we can assume "matplotlib
2665 // installed" implies "mpl_toolkits installed" on all platforms, and we don't
2666 // want to require it for people who don't need 3d plots.
2667 static PyObject *mpl_toolkitsmod = nullptr, *axis3dmod = nullptr;
2668 if (!mpl_toolkitsmod) {
2669 PyObject *mpl_toolkits = PyString_FromString("mpl_toolkits");
2670 PyObject *axis3d = PyString_FromString("mpl_toolkits.mplot3d");
2671 if (!mpl_toolkits || !axis3d) {
2672 throw std::runtime_error("couldnt create string");
2673 }
2674
2675 mpl_toolkitsmod = PyImport_Import(mpl_toolkits);
2676 Py_DECREF(mpl_toolkits);
2677 if (!mpl_toolkitsmod) {
2678 throw std::runtime_error("Error loading module mpl_toolkits!");
2679 }
2680
2681 axis3dmod = PyImport_Import(axis3d);
2682 Py_DECREF(axis3d);
2683 if (!axis3dmod) {
2684 throw std::runtime_error("Error loading module mpl_toolkits.mplot3d!");
2685 }
2686 }
2687
2688 PyObject *pystr = PyString_FromString(str.c_str());
2689 PyObject *args = PyTuple_New(1);
2690 PyTuple_SetItem(args, 0, pystr);
2691
2692 PyObject *kwargs = PyDict_New();
2693 for (auto it = keywords.begin(); it != keywords.end(); ++it) {
2694 PyDict_SetItemString(kwargs, it->first.c_str(),
2695 PyUnicode_FromString(it->second.c_str()));
2696 }
2697
2698 PyObject *ax =
2699 PyObject_CallObject(detail::_interpreter::get().s_python_function_gca,
2700 detail::_interpreter::get().s_python_empty_tuple);
2701 if (!ax)
2702 throw std::runtime_error("Call to gca() failed.");
2703 Py_INCREF(ax);
2704
2705 PyObject *zlabel = PyObject_GetAttrString(ax, "set_zlabel");
2706 if (!zlabel)
2707 throw std::runtime_error("Attribute set_zlabel not found.");
2708 Py_INCREF(zlabel);
2709
2710 PyObject *res = PyObject_Call(zlabel, args, kwargs);
2711 if (!res)
2712 throw std::runtime_error("Call to set_zlabel() failed.");
2713 Py_DECREF(zlabel);
2714
2715 Py_DECREF(ax);
2716 Py_DECREF(args);
2717 Py_DECREF(kwargs);
2718 if (res)
2719 Py_DECREF(res);
2720}
2721
2722inline void grid(bool flag) {
2724
2725 PyObject *pyflag = flag ? Py_True : Py_False;
2726 Py_INCREF(pyflag);
2727
2728 PyObject *args = PyTuple_New(1);
2729 PyTuple_SetItem(args, 0, pyflag);
2730
2731 PyObject *res = PyObject_CallObject(
2732 detail::_interpreter::get().s_python_function_grid, args);
2733 if (!res)
2734 throw std::runtime_error("Call to grid() failed.");
2735
2736 Py_DECREF(args);
2737 Py_DECREF(res);
2738}
2739
2740inline void show(const bool block = true) {
2742
2743 PyObject *res;
2744 if (block) {
2745 res =
2746 PyObject_CallObject(detail::_interpreter::get().s_python_function_show,
2747 detail::_interpreter::get().s_python_empty_tuple);
2748 } else {
2749 PyObject *kwargs = PyDict_New();
2750 PyDict_SetItemString(kwargs, "block", Py_False);
2751 res =
2752 PyObject_Call(detail::_interpreter::get().s_python_function_show,
2753 detail::_interpreter::get().s_python_empty_tuple, kwargs);
2754 Py_DECREF(kwargs);
2755 }
2756
2757 if (!res)
2758 throw std::runtime_error("Call to show() failed.");
2759
2760 Py_DECREF(res);
2761}
2762
2763inline void close() {
2765
2766 PyObject *res =
2767 PyObject_CallObject(detail::_interpreter::get().s_python_function_close,
2768 detail::_interpreter::get().s_python_empty_tuple);
2769
2770 if (!res)
2771 throw std::runtime_error("Call to close() failed.");
2772
2773 Py_DECREF(res);
2774}
2775
2776inline void xkcd() {
2778
2779 PyObject *res;
2780 PyObject *kwargs = PyDict_New();
2781
2782 res = PyObject_Call(detail::_interpreter::get().s_python_function_xkcd,
2783 detail::_interpreter::get().s_python_empty_tuple, kwargs);
2784
2785 Py_DECREF(kwargs);
2786
2787 if (!res)
2788 throw std::runtime_error("Call to show() failed.");
2789
2790 Py_DECREF(res);
2791}
2792
2793inline void draw() {
2795
2796 PyObject *res =
2797 PyObject_CallObject(detail::_interpreter::get().s_python_function_draw,
2798 detail::_interpreter::get().s_python_empty_tuple);
2799
2800 if (!res)
2801 throw std::runtime_error("Call to draw() failed.");
2802
2803 Py_DECREF(res);
2804}
2805
2806template <typename Numeric> inline void pause(Numeric interval) {
2808
2809 PyObject *args = PyTuple_New(1);
2810 PyTuple_SetItem(args, 0, PyFloat_FromDouble(interval));
2811
2812 PyObject *res = PyObject_CallObject(
2813 detail::_interpreter::get().s_python_function_pause, args);
2814 if (!res)
2815 throw std::runtime_error("Call to pause() failed.");
2816
2817 Py_DECREF(args);
2818 Py_DECREF(res);
2819}
2820
2821inline void save(const std::string &filename, const int dpi = 0) {
2823
2824 PyObject *pyfilename = PyString_FromString(filename.c_str());
2825
2826 PyObject *args = PyTuple_New(1);
2827 PyTuple_SetItem(args, 0, pyfilename);
2828
2829 PyObject *kwargs = PyDict_New();
2830
2831 if (dpi > 0) {
2832 PyDict_SetItemString(kwargs, "dpi", PyLong_FromLong(dpi));
2833 }
2834
2835 PyObject *res = PyObject_Call(
2836 detail::_interpreter::get().s_python_function_save, args, kwargs);
2837 if (!res)
2838 throw std::runtime_error("Call to save() failed.");
2839
2840 Py_DECREF(args);
2841 Py_DECREF(kwargs);
2842 Py_DECREF(res);
2843}
2844
2845inline void rcparams(const std::map<std::string, std::string> &keywords = {}) {
2847 PyObject *args = PyTuple_New(0);
2848 PyObject *kwargs = PyDict_New();
2849 for (auto it = keywords.begin(); it != keywords.end(); ++it) {
2850 if ("text.usetex" == it->first)
2851 PyDict_SetItemString(kwargs, it->first.c_str(),
2852 PyLong_FromLong(std::stoi(it->second.c_str())));
2853 else
2854 PyDict_SetItemString(kwargs, it->first.c_str(),
2855 PyString_FromString(it->second.c_str()));
2856 }
2857
2858 PyObject *update = PyObject_GetAttrString(
2859 detail::_interpreter::get().s_python_function_rcparams, "update");
2860 PyObject *res = PyObject_Call(update, args, kwargs);
2861 if (!res)
2862 throw std::runtime_error("Call to rcParams.update() failed.");
2863 Py_DECREF(args);
2864 Py_DECREF(kwargs);
2865 Py_DECREF(update);
2866 Py_DECREF(res);
2867}
2868
2869inline void clf() {
2871
2872 PyObject *res =
2873 PyObject_CallObject(detail::_interpreter::get().s_python_function_clf,
2874 detail::_interpreter::get().s_python_empty_tuple);
2875
2876 if (!res)
2877 throw std::runtime_error("Call to clf() failed.");
2878
2879 Py_DECREF(res);
2880}
2881
2882inline void cla() {
2884
2885 PyObject *res =
2886 PyObject_CallObject(detail::_interpreter::get().s_python_function_cla,
2887 detail::_interpreter::get().s_python_empty_tuple);
2888
2889 if (!res)
2890 throw std::runtime_error("Call to cla() failed.");
2891
2892 Py_DECREF(res);
2893}
2894
2895inline void ion() {
2897
2898 PyObject *res =
2899 PyObject_CallObject(detail::_interpreter::get().s_python_function_ion,
2900 detail::_interpreter::get().s_python_empty_tuple);
2901
2902 if (!res)
2903 throw std::runtime_error("Call to ion() failed.");
2904
2905 Py_DECREF(res);
2906}
2907
2908inline std::vector<std::array<double, 2>>
2909ginput(const int numClicks = 1,
2910 const std::map<std::string, std::string> &keywords = {}) {
2912
2913 PyObject *args = PyTuple_New(1);
2914 PyTuple_SetItem(args, 0, PyLong_FromLong(numClicks));
2915
2916 // construct keyword args
2917 PyObject *kwargs = PyDict_New();
2918 for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
2919 it != keywords.end(); ++it) {
2920 PyDict_SetItemString(kwargs, it->first.c_str(),
2921 PyUnicode_FromString(it->second.c_str()));
2922 }
2923
2924 PyObject *res = PyObject_Call(
2925 detail::_interpreter::get().s_python_function_ginput, args, kwargs);
2926
2927 Py_DECREF(kwargs);
2928 Py_DECREF(args);
2929 if (!res)
2930 throw std::runtime_error("Call to ginput() failed.");
2931
2932 const size_t len = PyList_Size(res);
2933 std::vector<std::array<double, 2>> out;
2934 out.reserve(len);
2935 for (size_t i = 0; i < len; i++) {
2936 PyObject *current = PyList_GetItem(res, i);
2937 std::array<double, 2> position;
2938 position[0] = PyFloat_AsDouble(PyTuple_GetItem(current, 0));
2939 position[1] = PyFloat_AsDouble(PyTuple_GetItem(current, 1));
2940 out.push_back(position);
2941 }
2942 Py_DECREF(res);
2943
2944 return out;
2945}
2946
2947// Actually, is there any reason not to call this automatically for every plot?
2948inline void tight_layout() {
2950
2951 PyObject *res = PyObject_CallObject(
2952 detail::_interpreter::get().s_python_function_tight_layout,
2953 detail::_interpreter::get().s_python_empty_tuple);
2954
2955 if (!res)
2956 throw std::runtime_error("Call to tight_layout() failed.");
2957
2958 Py_DECREF(res);
2959}
2960
2961// Support for variadic plot() and initializer lists:
2962
2963namespace detail {
2964
2965template <typename T>
2966using is_function = typename std::is_function<
2967 std::remove_pointer<std::remove_reference<T>>>::type;
2968
2969template <bool obj, typename T> struct is_callable_impl;
2970
2971template <typename T> struct is_callable_impl<false, T> {
2973}; // a non-object is callable iff it is a function
2974
2975template <typename T> struct is_callable_impl<true, T> {
2976 struct Fallback {
2978 };
2979 struct Derived : T, Fallback {};
2980
2981 template <typename U, U> struct Check;
2982
2983 template <typename U>
2984 static std::true_type
2985 test(...); // use a variadic function to make sure (1) it accepts everything
2986 // and (2) its always the worst match
2987
2988 template <typename U>
2989 static std::false_type test(Check<void (Fallback::*)(), &U::operator()> *);
2990
2991public:
2992 typedef decltype(test<Derived>(nullptr)) type;
2993 typedef decltype(&Fallback::operator()) dtype;
2994 static constexpr bool value = type::value;
2995}; // an object is callable iff it defines operator()
2996
2997template <typename T> struct is_callable {
2998 // dispatch to is_callable_impl<true, T> or is_callable_impl<false, T>
2999 // depending on whether T is of class type or not
3001};
3002
3003template <typename IsYDataCallable> struct plot_impl {};
3004
3005template <> struct plot_impl<std::false_type> {
3006 template <typename IterableX, typename IterableY>
3007 bool operator()(const IterableX &x, const IterableY &y,
3008 const std::string &format) {
3010
3011 // 2-phase lookup for distance, begin, end
3012 using std::begin;
3013 using std::distance;
3014 using std::end;
3015
3016 auto xs = distance(begin(x), end(x));
3017 auto ys = distance(begin(y), end(y));
3018 assert(xs == ys && "x and y data must have the same number of elements!");
3019
3020 PyObject *xlist = PyList_New(xs);
3021 PyObject *ylist = PyList_New(ys);
3022 PyObject *pystring = PyString_FromString(format.c_str());
3023
3024 auto itx = begin(x), ity = begin(y);
3025 for (size_t i = 0; i < xs; ++i) {
3026 PyList_SetItem(xlist, i, PyFloat_FromDouble(*itx++));
3027 PyList_SetItem(ylist, i, PyFloat_FromDouble(*ity++));
3028 }
3029
3030 PyObject *plot_args = PyTuple_New(3);
3031 PyTuple_SetItem(plot_args, 0, xlist);
3032 PyTuple_SetItem(plot_args, 1, ylist);
3033 PyTuple_SetItem(plot_args, 2, pystring);
3034
3035 PyObject *res = PyObject_CallObject(
3036 detail::_interpreter::get().s_python_function_plot, plot_args);
3037
3038 Py_DECREF(plot_args);
3039 if (res)
3040 Py_DECREF(res);
3041
3042 return res;
3043 }
3044};
3045
3046template <> struct plot_impl<std::true_type> {
3047 template <typename Iterable, typename Callable>
3048 bool operator()(const Iterable &ticks, const Callable &f,
3049 const std::string &format) {
3050 if (begin(ticks) == end(ticks))
3051 return true;
3052
3053 // We could use additional meta-programming to deduce the correct element
3054 // type of y, but all values have to be convertible to double anyways
3055 std::vector<double> y;
3056 for (auto x : ticks)
3057 y.push_back(f(x));
3058 return plot_impl<std::false_type>()(ticks, y, format);
3059 }
3060};
3061
3062} // end namespace detail
3063
3064// recursion stop for the above
3065template <typename... Args> bool plot() { return true; }
3066
3067template <typename A, typename B, typename... Args>
3068bool plot(const A &a, const B &b, const std::string &format, Args... args) {
3070 format) &&
3071 plot(args...);
3072}
3073
3074/*
3075 * This group of plot() functions is needed to support initializer lists, i.e.
3076 * calling plot( {1,2,3,4} )
3077 */
3078inline bool plot(const std::vector<double> &x, const std::vector<double> &y,
3079 const std::string &format = "") {
3080 return plot<double, double>(x, y, format);
3081}
3082
3083inline bool plot(const std::vector<double> &y, const std::string &format = "") {
3084 return plot<double>(y, format);
3085}
3086
3087inline bool plot(const std::vector<double> &x, const std::vector<double> &y,
3088 const std::map<std::string, std::string> &keywords) {
3089 return plot<double>(x, y, keywords);
3090}
3091
3092/*
3093 * This class allows dynamic plots, ie changing the plotted data without
3094 * clearing and re-plotting
3095 */
3096class Plot {
3097public:
3098 // default initialization with plot label, some data and format
3099 template <typename Numeric>
3100 Plot(const std::string &name, const std::vector<Numeric> &x,
3101 const std::vector<Numeric> &y, const std::string &format = "") {
3103
3104 assert(x.size() == y.size());
3105
3106 PyObject *kwargs = PyDict_New();
3107 if (name != "")
3108 PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str()));
3109
3110 PyObject *xarray = detail::get_array(x);
3111 PyObject *yarray = detail::get_array(y);
3112
3113 PyObject *pystring = PyString_FromString(format.c_str());
3114
3115 PyObject *plot_args = PyTuple_New(3);
3116 PyTuple_SetItem(plot_args, 0, xarray);
3117 PyTuple_SetItem(plot_args, 1, yarray);
3118 PyTuple_SetItem(plot_args, 2, pystring);
3119
3120 PyObject *res = PyObject_Call(
3121 detail::_interpreter::get().s_python_function_plot, plot_args, kwargs);
3122
3123 Py_DECREF(kwargs);
3124 Py_DECREF(plot_args);
3125
3126 if (res) {
3127 line = PyList_GetItem(res, 0);
3128
3129 if (line)
3130 set_data_fct = PyObject_GetAttrString(line, "set_data");
3131 else
3132 Py_DECREF(line);
3133 Py_DECREF(res);
3134 }
3135 }
3136
3137 // shorter initialization with name or format only
3138 // basically calls line, = plot([], [])
3139 Plot(const std::string &name = "", const std::string &format = "")
3140 : Plot(name, std::vector<double>(), std::vector<double>(), format) {}
3141
3142 template <typename Numeric>
3143 bool update(const std::vector<Numeric> &x, const std::vector<Numeric> &y) {
3144 assert(x.size() == y.size());
3145 if (set_data_fct) {
3146 PyObject *xarray = detail::get_array(x);
3147 PyObject *yarray = detail::get_array(y);
3148
3149 PyObject *plot_args = PyTuple_New(2);
3150 PyTuple_SetItem(plot_args, 0, xarray);
3151 PyTuple_SetItem(plot_args, 1, yarray);
3152
3153 PyObject *res = PyObject_CallObject(set_data_fct, plot_args);
3154 if (res)
3155 Py_DECREF(res);
3156 return res;
3157 }
3158 return false;
3159 }
3160
3161 // clears the plot but keep it available
3162 bool clear() { return update(std::vector<double>(), std::vector<double>()); }
3163
3164 // definitely remove this line
3165 void remove() {
3166 if (line) {
3167 auto remove_fct = PyObject_GetAttrString(line, "remove");
3168 PyObject *args = PyTuple_New(0);
3169 PyObject *res = PyObject_CallObject(remove_fct, args);
3170 if (res)
3171 Py_DECREF(res);
3172 }
3173 decref();
3174 }
3175
3176 ~Plot() { decref(); }
3177
3178private:
3179 void decref() {
3180 if (line)
3181 Py_DECREF(line);
3182 if (set_data_fct)
3183 Py_DECREF(set_data_fct);
3184 }
3185
3186 PyObject *line = nullptr;
3187 PyObject *set_data_fct = nullptr;
3188};
3189
3190} // end namespace matplotlibcpp
Definition matplotlibcpp.h:3096
PyObject * set_data_fct
Definition matplotlibcpp.h:3187
bool clear()
Definition matplotlibcpp.h:3162
Plot(const std::string &name, const std::vector< Numeric > &x, const std::vector< Numeric > &y, const std::string &format="")
Definition matplotlibcpp.h:3100
~Plot()
Definition matplotlibcpp.h:3176
Plot(const std::string &name="", const std::string &format="")
Definition matplotlibcpp.h:3139
void decref()
Definition matplotlibcpp.h:3179
bool update(const std::vector< Numeric > &x, const std::vector< Numeric > &y)
Definition matplotlibcpp.h:3143
void remove()
Definition matplotlibcpp.h:3165
PyObject * line
Definition matplotlibcpp.h:3186
typename std::is_function< std::remove_pointer< std::remove_reference< T > > >::type is_function
Definition matplotlibcpp.h:2967
PyObject * get_listlist(const std::vector< std::vector< Numeric > > &ll)
Definition matplotlibcpp.h:452
PyObject * get_array(const std::vector< Numeric > &v)
Definition matplotlibcpp.h:387
is_function< T > type
Definition matplotlibcpp.h:2972
is_callable_impl< std::is_class< T >::value, T >::type type
Definition matplotlibcpp.h:3000
PyObject * get_2darray(const std::vector<::std::vector< Numeric > > &v)
Definition matplotlibcpp.h:407
void imshow(void *ptr, const NPY_TYPES type, const int rows, const int columns, const int colors, const std::map< std::string, std::string > &keywords, PyObject **out)
Definition matplotlibcpp.h:977
static std::string s_backend
Definition matplotlibcpp.h:45
Definition matplotlibcpp.h:2997
Definition matplotlibcpp.h:2969
Definition matplotlibcpp.h:3003
Definition matplotlibcpp.h:42
std::vector< std::array< double, 2 > > ginput(const int numClicks=1, const std::map< std::string, std::string > &keywords={})
Definition matplotlibcpp.h:2909
bool fill(const std::vector< Numeric > &x, const std::vector< Numeric > &y, const std::map< std::string, std::string > &keywords)
Definition matplotlibcpp.h:840
void contour(const std::vector<::std::vector< Numeric > > &x, const std::vector<::std::vector< Numeric > > &y, const std::vector<::std::vector< Numeric > > &z, const std::map< std::string, std::string > &keywords={})
Definition matplotlibcpp.h:625
void plot3(const std::vector< Numeric > &x, const std::vector< Numeric > &y, const std::vector< Numeric > &z, const std::map< std::string, std::string > &keywords=std::map< std::string, std::string >(), const long fig_number=0)
Definition matplotlibcpp.h:699
std::array< double, 2 > xlim()
Definition matplotlibcpp.h:2215
void tight_layout()
Definition matplotlibcpp.h:2948
bool scatter(const std::vector< NumericX > &x, const std::vector< NumericY > &y, const double s=1.0, const std::map< std::string, std::string > &keywords={})
Definition matplotlibcpp.h:1062
bool named_hist(std::string label, const std::vector< Numeric > &y, long bins=10, std::string color="b", double alpha=1.0)
Definition matplotlibcpp.h:1414
void rcparams(const std::map< std::string, std::string > &keywords={})
Definition matplotlibcpp.h:2845
void set_aspect_equal()
Definition matplotlibcpp.h:2147
long figure(long number=-1)
Definition matplotlibcpp.h:2010
bool scatter_colored(const std::vector< NumericX > &x, const std::vector< NumericY > &y, const std::vector< NumericColors > &colors, const double s=1.0, const std::map< std::string, std::string > &keywords={})
Definition matplotlibcpp.h:1095
bool errorbar(const std::vector< NumericX > &x, const std::vector< NumericY > &y, const std::vector< NumericX > &yerr, const std::map< std::string, std::string > &keywords={})
Definition matplotlibcpp.h:1750
void margins(Numeric margin)
Definition matplotlibcpp.h:2351
bool annotate(std::string annotation, double x, double y)
Definition matplotlibcpp.h:308
void imshow(const unsigned char *ptr, const int rows, const int columns, const int colors, const std::map< std::string, std::string > &keywords={}, PyObject **out=nullptr)
Definition matplotlibcpp.h:1014
bool semilogy(const std::vector< NumericX > &x, const std::vector< NumericY > &y, const std::string &s="")
Definition matplotlibcpp.h:1696
bool named_semilogy(const std::string &name, const std::vector< NumericX > &x, const std::vector< NumericY > &y, const std::string &format="")
Definition matplotlibcpp.h:1880
bool arrow(Numeric x, Numeric y, Numeric end_x, Numeric end_y, const std::string &fc="r", const std::string ec="k", Numeric head_length=0.25, Numeric head_width=0.1625)
Definition matplotlibcpp.h:914
void close()
Definition matplotlibcpp.h:2763
bool fignum_exists(long number)
Definition matplotlibcpp.h:2045
bool named_plot(const std::string &name, const std::vector< Numeric > &y, const std::string &format="")
Definition matplotlibcpp.h:1791
void tick_params(const std::map< std::string, std::string > &keywords, const std::string axis="both")
Definition matplotlibcpp.h:2381
void suptitle(const std::string &suptitlestr, const std::map< std::string, std::string > &keywords={})
Definition matplotlibcpp.h:2480
bool loglog(const std::vector< NumericX > &x, const std::vector< NumericY > &y, const std::string &s="")
Definition matplotlibcpp.h:1723
void title(const std::string &titlestr, const std::map< std::string, std::string > &keywords={})
Definition matplotlibcpp.h:2456
void axvline(double x, double ymin=0., double ymax=1., const std::map< std::string, std::string > &keywords=std::map< std::string, std::string >())
Definition matplotlibcpp.h:2549
bool bar(const std::vector< Numeric > &x, const std::vector< Numeric > &y, std::string ec="black", std::string ls="-", double lw=1.0, const std::map< std::string, std::string > &keywords={})
Definition matplotlibcpp.h:1303
void subplot(long nrows, long ncols, long plot_number)
Definition matplotlibcpp.h:2409
std::array< double, 2 > ylim()
Definition matplotlibcpp.h:2230
void backend(const std::string &name)
Definition matplotlibcpp.h:306
bool subplots_adjust(const std::map< std::string, double > &keywords={})
Definition matplotlibcpp.h:1389
bool plot()
Definition matplotlibcpp.h:3065
void legend()
Definition matplotlibcpp.h:2085
void figure_size(size_t w, size_t h)
Definition matplotlibcpp.h:2062
bool fill_between(const std::vector< Numeric > &x, const std::vector< Numeric > &y1, const std::vector< Numeric > &y2, const std::map< std::string, std::string > &keywords)
Definition matplotlibcpp.h:875
void xlabel(const std::string &str, const std::map< std::string, std::string > &keywords={})
Definition matplotlibcpp.h:2610
bool named_loglog(const std::string &name, const std::vector< NumericX > &x, const std::vector< NumericY > &y, const std::string &format="")
Definition matplotlibcpp.h:1911
void ion()
Definition matplotlibcpp.h:2895
void colorbar(PyObject *mappable=NULL, const std::map< std::string, float > &keywords={})
Definition matplotlibcpp.h:1982
bool boxplot(const std::vector< std::vector< Numeric > > &data, const std::vector< std::string > &labels={}, const std::map< std::string, std::string > &keywords={})
Definition matplotlibcpp.h:1241
void cla()
Definition matplotlibcpp.h:2882
void pause(Numeric interval)
Definition matplotlibcpp.h:2806
void axvspan(double xmin, double xmax, double ymin=0., double ymax=1., const std::map< std::string, std::string > &keywords=std::map< std::string, std::string >())
Definition matplotlibcpp.h:2578
void spy(const std::vector<::std::vector< Numeric > > &x, const double markersize=-1, const std::map< std::string, std::string > &keywords={})
Definition matplotlibcpp.h:668
void plot_surface(const std::vector<::std::vector< Numeric > > &x, const std::vector<::std::vector< Numeric > > &y, const std::vector<::std::vector< Numeric > > &z, const std::map< std::string, std::string > &keywords=std::map< std::string, std::string >(), const long fig_number=0)
Definition matplotlibcpp.h:504
void axis(const std::string &axisstr)
Definition matplotlibcpp.h:2504
void axhline(double y, double xmin=0., double xmax=1., const std::map< std::string, std::string > &keywords=std::map< std::string, std::string >())
Definition matplotlibcpp.h:2520
void yticks(const std::vector< Numeric > &ticks, const std::vector< std::string > &labels={}, const std::map< std::string, std::string > &keywords={})
Definition matplotlibcpp.h:2299
void subplot2grid(long nrows, long ncols, long rowid=0, long colid=0, long rowspan=1, long colspan=1)
Definition matplotlibcpp.h:2427
void set_zlabel(const std::string &str, const std::map< std::string, std::string > &keywords={})
Definition matplotlibcpp.h:2659
void set_aspect(Numeric ratio)
Definition matplotlibcpp.h:2118
bool barh(const std::vector< Numeric > &x, const std::vector< Numeric > &y, std::string ec="black", std::string ls="-", double lw=1.0, const std::map< std::string, std::string > &keywords={})
Definition matplotlibcpp.h:1355
void show(const bool block=true)
Definition matplotlibcpp.h:2740
void xkcd()
Definition matplotlibcpp.h:2776
void xticks(const std::vector< Numeric > &ticks, const std::vector< std::string > &labels={}, const std::map< std::string, std::string > &keywords={})
Definition matplotlibcpp.h:2246
void draw()
Definition matplotlibcpp.h:2793
void save(const std::string &filename, const int dpi=0)
Definition matplotlibcpp.h:2821
bool semilogx(const std::vector< NumericX > &x, const std::vector< NumericY > &y, const std::string &s="")
Definition matplotlibcpp.h:1669
void text(Numeric x, Numeric y, const std::string &s="")
Definition matplotlibcpp.h:1965
void ylabel(const std::string &str, const std::map< std::string, std::string > &keywords={})
Definition matplotlibcpp.h:2634
void clf()
Definition matplotlibcpp.h:2869
void grid(bool flag)
Definition matplotlibcpp.h:2722
bool named_semilogx(const std::string &name, const std::vector< NumericX > &x, const std::vector< NumericY > &y, const std::string &format="")
Definition matplotlibcpp.h:1849
bool stem(const std::vector< Numeric > &x, const std::vector< Numeric > &y, const std::map< std::string, std::string > &keywords)
Definition matplotlibcpp.h:805
bool hist(const std::vector< Numeric > &y, long bins=10, std::string color="b", double alpha=1.0, bool cumulative=false)
Definition matplotlibcpp.h:946
bool quiver(const std::vector< NumericX > &x, const std::vector< NumericY > &y, const std::vector< NumericU > &u, const std::vector< NumericW > &w, const std::map< std::string, std::string > &keywords={})
Definition matplotlibcpp.h:1503
STL namespace.
Definition matplotlibcpp.h:47
PyObject * s_python_function_axhline
Definition matplotlibcpp.h:77
PyObject * s_python_function_clf
Definition matplotlibcpp.h:89
PyObject * s_python_function_xlim
Definition matplotlibcpp.h:71
PyObject * s_python_function_errorbar
Definition matplotlibcpp.h:90
PyObject * s_python_function_axvline
Definition matplotlibcpp.h:78
PyObject * s_python_function_arrow
Definition matplotlibcpp.h:48
PyObject * s_python_function_subplot2grid
Definition matplotlibcpp.h:69
PyObject * s_python_function_barh
Definition matplotlibcpp.h:100
PyObject * s_python_function_hist
Definition matplotlibcpp.h:64
PyObject * s_python_function_suptitle
Definition matplotlibcpp.h:98
PyObject * s_python_function_boxplot
Definition matplotlibcpp.h:67
PyObject * s_python_function_xlabel
Definition matplotlibcpp.h:80
PyObject * s_python_function_spy
Definition matplotlibcpp.h:104
PyObject * s_python_function_legend
Definition matplotlibcpp.h:70
PyObject * s_python_function_margins
Definition matplotlibcpp.h:85
PyObject * s_python_function_ginput
Definition matplotlibcpp.h:73
static _interpreter & interkeeper(bool should_kill)
Definition matplotlibcpp.h:124
PyObject * s_python_function_stem
Definition matplotlibcpp.h:95
PyObject * s_python_function_grid
Definition matplotlibcpp.h:87
PyObject * s_python_function_semilogy
Definition matplotlibcpp.h:60
PyObject * s_python_function_draw
Definition matplotlibcpp.h:51
PyObject * s_python_function_fignum_exists
Definition matplotlibcpp.h:55
PyObject * s_python_function_xticks
Definition matplotlibcpp.h:83
PyObject * s_python_function_contour
Definition matplotlibcpp.h:58
PyObject * s_python_function_close
Definition matplotlibcpp.h:50
static _interpreter & get()
Definition matplotlibcpp.h:119
PyObject * s_python_function_axis
Definition matplotlibcpp.h:76
PyObject * s_python_function_plot
Definition matplotlibcpp.h:56
PyObject * s_python_function_rcparams
Definition matplotlibcpp.h:103
_interpreter()
Definition matplotlibcpp.h:163
PyObject * s_python_function_figure
Definition matplotlibcpp.h:54
PyObject * s_python_function_gca
Definition matplotlibcpp.h:82
PyObject * s_python_function_axvspan
Definition matplotlibcpp.h:79
PyObject * s_python_function_loglog
Definition matplotlibcpp.h:61
PyObject * s_python_function_tight_layout
Definition matplotlibcpp.h:92
PyObject * s_python_function_save
Definition matplotlibcpp.h:53
PyObject * s_python_function_title
Definition matplotlibcpp.h:75
PyObject * s_python_function_fill
Definition matplotlibcpp.h:62
PyObject * s_python_function_show
Definition matplotlibcpp.h:49
PyObject * s_python_function_quiver
Definition matplotlibcpp.h:57
PyObject * safe_import(PyObject *module, std::string fname)
Definition matplotlibcpp.h:131
static _interpreter & kill()
Definition matplotlibcpp.h:121
PyObject * s_python_function_ylabel
Definition matplotlibcpp.h:81
PyObject * s_python_empty_tuple
Definition matplotlibcpp.h:94
PyObject * s_python_function_cla
Definition matplotlibcpp.h:88
~_interpreter()
Definition matplotlibcpp.h:291
PyObject * s_python_function_semilogx
Definition matplotlibcpp.h:59
PyObject * s_python_function_colorbar
Definition matplotlibcpp.h:101
PyObject * s_python_function_imshow
Definition matplotlibcpp.h:65
PyObject * s_python_function_bar
Definition matplotlibcpp.h:99
PyObject * s_python_function_subplot
Definition matplotlibcpp.h:68
PyObject * s_python_function_xkcd
Definition matplotlibcpp.h:96
PyObject * s_python_function_ion
Definition matplotlibcpp.h:72
void import_numpy()
Definition matplotlibcpp.h:156
PyObject * s_python_colormap
Definition matplotlibcpp.h:93
PyObject * s_python_function_pause
Definition matplotlibcpp.h:52
PyObject * s_python_function_yticks
Definition matplotlibcpp.h:84
PyObject * s_python_function_subplots_adjust
Definition matplotlibcpp.h:102
PyObject * s_python_function_scatter
Definition matplotlibcpp.h:66
PyObject * s_python_function_annotate
Definition matplotlibcpp.h:91
PyObject * s_python_function_fill_between
Definition matplotlibcpp.h:63
PyObject * s_python_function_ylim
Definition matplotlibcpp.h:74
PyObject * s_python_function_tick_params
Definition matplotlibcpp.h:86
PyObject * s_python_function_text
Definition matplotlibcpp.h:97
decltype(test< Derived >(nullptr)) type
Definition matplotlibcpp.h:2992
decltype(&Fallback::operator()) dtype
Definition matplotlibcpp.h:2993
static std::false_type test(Check< void(Fallback::*)(), &U::operator()> *)
bool operator()(const IterableX &x, const IterableY &y, const std::string &format)
Definition matplotlibcpp.h:3007
bool operator()(const Iterable &ticks, const Callable &f, const std::string &format)
Definition matplotlibcpp.h:3048
Definition matplotlibcpp.h:339
static const NPY_TYPES type
Definition matplotlibcpp.h:340