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