Agora  1.2.0
Agora project
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 
43 namespace matplotlibcpp {
44 namespace detail {
45 
46 static std::string s_backend;
47 
48 struct _interpreter {
94  PyObject *s_python_colormap;
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()`.
128  static _interpreter& interkeeper(bool should_kill) {
129  static _interpreter ctx;
130  if (should_kill)
131  ctx.~_interpreter();
132  return ctx;
133  }
134 
135  PyObject* safe_import(PyObject* module, std::string fname) {
136  PyObject* fn = PyObject_GetAttrString(module, fname.c_str());
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 
147 private:
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 
159  void import_numpy() {
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);
175  Py_Initialize();
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 
191  PyObject* matplotlibname = PyString_FromString("matplotlib");
192  PyObject* pyplotname = PyString_FromString("matplotlib.pyplot");
193  PyObject* cmname = PyString_FromString("matplotlib.cm");
194  PyObject* pylabname = PyString_FromString("pylab");
195  if (!pyplotname || !pylabname || !matplotlibname || !cmname) {
196  throw std::runtime_error("couldnt create string");
197  }
198 
199  PyObject* matplotlib = PyImport_Import(matplotlibname);
200 
201  Py_DECREF(matplotlibname);
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 
215  PyObject* pymod = PyImport_Import(pyplotname);
216  Py_DECREF(pyplotname);
217  if (!pymod) { throw std::runtime_error("Error loading module matplotlib.pyplot!"); }
218 
219  s_python_colormap = PyImport_Import(cmname);
220  Py_DECREF(cmname);
221  if (!s_python_colormap) { throw std::runtime_error("Error loading module matplotlib.cm!"); }
222 
223  PyObject* pylabmod = PyImport_Import(pylabname);
224  Py_DECREF(pylabname);
225  if (!pylabmod) { throw std::runtime_error("Error loading module pylab!"); }
226 
227  s_python_function_arrow = safe_import(pymod, "arrow");
228  s_python_function_show = safe_import(pymod, "show");
229  s_python_function_close = safe_import(pymod, "close");
230  s_python_function_draw = safe_import(pymod, "draw");
231  s_python_function_pause = safe_import(pymod, "pause");
232  s_python_function_figure = safe_import(pymod, "figure");
233  s_python_function_fignum_exists = safe_import(pymod, "fignum_exists");
234  s_python_function_plot = safe_import(pymod, "plot");
235  s_python_function_quiver = safe_import(pymod, "quiver");
236  s_python_function_contour = safe_import(pymod, "contour");
237  s_python_function_semilogx = safe_import(pymod, "semilogx");
238  s_python_function_semilogy = safe_import(pymod, "semilogy");
239  s_python_function_loglog = safe_import(pymod, "loglog");
240  s_python_function_fill = safe_import(pymod, "fill");
241  s_python_function_fill_between = safe_import(pymod, "fill_between");
242  s_python_function_hist = safe_import(pymod,"hist");
243  s_python_function_scatter = safe_import(pymod,"scatter");
244  s_python_function_boxplot = safe_import(pymod,"boxplot");
245  s_python_function_subplot = safe_import(pymod, "subplot");
246  s_python_function_subplot2grid = safe_import(pymod, "subplot2grid");
247  s_python_function_legend = safe_import(pymod, "legend");
248  s_python_function_xlim = safe_import(pymod, "xlim");
249  s_python_function_ylim = safe_import(pymod, "ylim");
250  s_python_function_title = safe_import(pymod, "title");
251  s_python_function_axis = safe_import(pymod, "axis");
252  s_python_function_axhline = safe_import(pymod, "axhline");
253  s_python_function_axvline = safe_import(pymod, "axvline");
254  s_python_function_axvspan = safe_import(pymod, "axvspan");
255  s_python_function_xlabel = safe_import(pymod, "xlabel");
256  s_python_function_ylabel = safe_import(pymod, "ylabel");
257  s_python_function_gca = safe_import(pymod, "gca");
258  s_python_function_xticks = safe_import(pymod, "xticks");
259  s_python_function_yticks = safe_import(pymod, "yticks");
260  s_python_function_margins = safe_import(pymod, "margins");
261  s_python_function_tick_params = safe_import(pymod, "tick_params");
262  s_python_function_grid = safe_import(pymod, "grid");
263  s_python_function_ion = safe_import(pymod, "ion");
264  s_python_function_ginput = safe_import(pymod, "ginput");
265  s_python_function_save = safe_import(pylabmod, "savefig");
266  s_python_function_annotate = safe_import(pymod,"annotate");
267  s_python_function_cla = safe_import(pymod, "cla");
268  s_python_function_clf = safe_import(pymod, "clf");
269  s_python_function_errorbar = safe_import(pymod, "errorbar");
270  s_python_function_tight_layout = safe_import(pymod, "tight_layout");
271  s_python_function_stem = safe_import(pymod, "stem");
272  s_python_function_xkcd = safe_import(pymod, "xkcd");
273  s_python_function_text = safe_import(pymod, "text");
274  s_python_function_suptitle = safe_import(pymod, "suptitle");
275  s_python_function_bar = safe_import(pymod,"bar");
276  s_python_function_barh = safe_import(pymod, "barh");
277  s_python_function_colorbar = PyObject_GetAttrString(pymod, "colorbar");
278  s_python_function_subplots_adjust = safe_import(pymod,"subplots_adjust");
279  s_python_function_rcparams = PyObject_GetAttrString(pymod, "rcParams");
280  s_python_function_spy = PyObject_GetAttrString(pymod, "spy");
281 #ifndef WITHOUT_NUMPY
282  s_python_function_imshow = safe_import(pymod, "imshow");
283 #endif
284  s_python_empty_tuple = PyTuple_New(0);
285  }
286 
288  Py_Finalize();
289  }
290 };
291 
292 } // end namespace detail
293 
303 inline void backend(const std::string& name)
304 {
305  detail::s_backend = name;
306 }
307 
308 inline 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 
334 namespace detail {
335 
336 #ifndef WITHOUT_NUMPY
337 // Type selector for numpy array conversion
338 template <typename T> struct select_npy_type { const static NPY_TYPES type = NPY_NOTYPE; }; //Default
339 template <> struct select_npy_type<double> { const static NPY_TYPES type = NPY_DOUBLE; };
340 template <> struct select_npy_type<float> { const static NPY_TYPES type = NPY_FLOAT; };
341 template <> struct select_npy_type<bool> { const static NPY_TYPES type = NPY_BOOL; };
342 template <> struct select_npy_type<int8_t> { const static NPY_TYPES type = NPY_INT8; };
343 template <> struct select_npy_type<int16_t> { const static NPY_TYPES type = NPY_SHORT; };
344 template <> struct select_npy_type<int32_t> { const static NPY_TYPES type = NPY_INT; };
345 template <> struct select_npy_type<int64_t> { const static NPY_TYPES type = NPY_INT64; };
346 template <> struct select_npy_type<uint8_t> { const static NPY_TYPES type = NPY_UINT8; };
347 template <> struct select_npy_type<uint16_t> { const static NPY_TYPES type = NPY_USHORT; };
348 template <> struct select_npy_type<uint32_t> { const static NPY_TYPES type = NPY_ULONG; };
349 template <> 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
353 static_assert(sizeof(long long) == 8);
354 template <> struct select_npy_type<long long> { const static NPY_TYPES type = NPY_INT64; };
355 static_assert(sizeof(unsigned long long) == 8);
356 template <> struct select_npy_type<unsigned long long> { const static NPY_TYPES type = NPY_UINT64; };
357 
358 template<typename Numeric>
359 PyObject* get_array(const std::vector<Numeric>& v)
360 {
361  npy_intp vsize = v.size();
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 
378 template<typename Numeric>
379 PyObject* 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 
403 template<typename Numeric>
404 PyObject* 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
416 inline 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
426 template<typename Numeric>
427 PyObject* 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 
441 template<typename Numeric>
442 bool 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
476 template <typename Numeric>
477 void 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 
586 template <typename Numeric>
587 void 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 
628 template <typename Numeric>
629 void 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 
659 template <typename Numeric>
660 void 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 
754 template<typename Numeric>
755 bool 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 
789 template< typename Numeric >
790 bool 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 
821 template< typename Numeric >
822 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)
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 
855 template <typename Numeric>
856 bool 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 
886 template< typename Numeric>
887 bool 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
916 namespace detail {
917 
918 inline 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 
950 inline 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 
955 inline 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
961 void 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 
992 template<typename NumericX, typename NumericY>
993 bool 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 
1025 template<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 
1063 template<typename NumericX, typename NumericY, typename NumericZ>
1064 bool 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 
1160 template<typename Numeric>
1161 bool 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 
1194 template<typename Numeric>
1195 bool 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 
1220 template <typename Numeric>
1221 bool 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 
1261 template <typename Numeric>
1262 bool 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 
1279 template<typename Numeric>
1280 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 = { }) {
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 
1308 inline 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 
1331 template< typename Numeric>
1332 bool 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 
1357 template<typename NumericX, typename NumericY>
1358 bool 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 
1382 template <typename NumericX, typename NumericY, typename NumericZ>
1383 bool 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 
1415 template<typename NumericX, typename NumericY, typename NumericU, typename NumericW>
1416 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 = {})
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 
1451 template<typename NumericX, typename NumericY, typename NumericZ, typename NumericU, typename NumericW, typename NumericV>
1452 bool 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 
1537 template<typename NumericX, typename NumericY>
1538 bool 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 
1564 template<typename NumericX, typename NumericY>
1565 bool 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 
1589 template<typename NumericX, typename NumericY>
1590 bool 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 
1614 template<typename NumericX, typename NumericY>
1615 bool 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 
1639 template<typename NumericX, typename NumericY>
1640 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 = {})
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 
1676 template<typename Numeric>
1677 bool 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 
1702 template<typename NumericX, typename NumericY>
1703 bool 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 
1729 template<typename NumericX, typename NumericY>
1730 bool 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 
1756 template<typename NumericX, typename NumericY>
1757 bool 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 
1783 template<typename NumericX, typename NumericY>
1784 bool 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 
1809 template<typename Numeric>
1810 bool 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 
1817 template<typename Numeric>
1818 bool 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 
1825 template<typename Numeric>
1826 bool 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 
1833 template<typename Numeric>
1834 void 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 
1850 inline 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 
1875 inline 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 
1906 inline 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 
1922 inline 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 
1944 inline 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 
1954 inline 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 
1972 template<typename Numeric>
1973 inline 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 
2000 inline 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 
2028 template<typename Numeric>
2029 void 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 
2047 template<typename Numeric>
2048 void 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 
2067 inline 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 
2082 inline 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 
2096 template<typename Numeric>
2097 inline 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 
2139 template<typename Numeric>
2140 inline void xticks(const std::vector<Numeric> &ticks, const std::map<std::string, std::string>& keywords)
2141 {
2142  xticks(ticks, {}, keywords);
2143 }
2144 
2145 template<typename Numeric>
2146 inline 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 
2188 template<typename Numeric>
2189 inline void yticks(const std::vector<Numeric> &ticks, const std::map<std::string, std::string>& keywords)
2190 {
2191  yticks(ticks, {}, keywords);
2192 }
2193 
2194 template <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 
2209 template <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 
2226 inline 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 
2252 inline 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 
2269 inline 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 
2296 inline 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 
2317 inline 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 
2338 inline 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 
2353 inline 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 
2378 inline 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 
2403 inline 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 
2431 inline 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 
2452 inline 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 
2473 inline 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 
2525 inline 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 
2542 inline 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 
2567 inline 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 
2580 inline 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 
2597 inline 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 
2610 template<typename Numeric>
2611 inline 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 
2625 inline 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 
2649 inline 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 
2668 inline 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 
2680 inline 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 
2692 inline 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 
2704 inline 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?
2741 inline 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 
2755 namespace detail {
2756 
2757 template<typename T>
2758 using is_function = typename std::is_function<std::remove_pointer<std::remove_reference<T>>>::type;
2759 
2760 template<bool obj, typename T>
2762 
2763 template<typename T>
2764 struct is_callable_impl<false, T>
2765 {
2767 }; // a non-object is callable iff it is a function
2768 
2769 template<typename T>
2770 struct 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 
2783 public:
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 
2789 template<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 
2796 template<typename IsYDataCallable>
2797 struct plot_impl { };
2798 
2799 template<>
2800 struct 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 
2840 template<>
2841 struct 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
2859 template<typename... Args>
2860 bool plot() { return true; }
2861 
2862 template<typename A, typename B, typename... Args>
2863 bool plot(const A& a, const B& b, const std::string& format, Args... args)
2864 {
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  */
2872 inline 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 
2876 inline bool plot(const std::vector<double>& y, const std::string& format = "") {
2877  return plot<double>(y,format);
2878 }
2879 
2880 inline 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  */
2887 class Plot
2888 {
2889 public:
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 
2969  ~Plot() {
2970  decref();
2971  }
2972 private:
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
matplotlibcpp::plot_surface
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
matplotlibcpp::Plot::clear
bool clear()
Definition: matplotlibcpp.h:2953
matplotlibcpp::detail::plot_impl
Definition: matplotlibcpp.h:2797
fmt::v8::color
color
Definition: color.h:23
matplotlibcpp::Plot::update
bool update(const std::vector< Numeric > &x, const std::vector< Numeric > &y)
Definition: matplotlibcpp.h:2934
matplotlibcpp::Plot
Definition: matplotlibcpp.h:2887
matplotlibcpp::detail::_interpreter::s_python_function_ylim
PyObject * s_python_function_ylim
Definition: matplotlibcpp.h:75
fmt::v8::detail::value_type
remove_cvref_t< decltype(*detail::range_begin(std::declval< Range >()))> value_type
Definition: ranges.h:226
matplotlibcpp::draw
void draw()
Definition: matplotlibcpp.h:2597
matplotlibcpp::detail::is_callable_impl
Definition: matplotlibcpp.h:2761
matplotlibcpp::detail::_interpreter::s_python_function_xlabel
PyObject * s_python_function_xlabel
Definition: matplotlibcpp.h:81
mm_gui.w
w
Definition: mm_gui.py:119
matplotlibcpp::detail::_interpreter::s_python_function_subplot
PyObject * s_python_function_subplot
Definition: matplotlibcpp.h:69
matplotlibcpp::subplot2grid
void subplot2grid(long nrows, long ncols, long rowid=0, long colid=0, long rowspan=1, long colspan=1)
Definition: matplotlibcpp.h:2269
matplotlibcpp::detail::_interpreter::s_python_function_clf
PyObject * s_python_function_clf
Definition: matplotlibcpp.h:90
matplotlibcpp::detail::_interpreter::s_python_function_margins
PyObject * s_python_function_margins
Definition: matplotlibcpp.h:86
matplotlibcpp::hist
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
size
end IFFT Reshape the symbol vector into two different spatial streams size
Definition: generate_data.m:73
matplotlibcpp::plot
bool plot(const std::vector< Numeric > &x, const std::vector< Numeric > &y, const std::map< std::string, std::string > &keywords)
Definition: matplotlibcpp.h:442
matplotlibcpp::quiver
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
matplotlibcpp::semilogx
bool semilogx(const std::vector< NumericX > &x, const std::vector< NumericY > &y, const std::string &s="")
Definition: matplotlibcpp.h:1565
matplotlibcpp::detail::_interpreter::s_python_function_show
PyObject * s_python_function_show
Definition: matplotlibcpp.h:50
matplotlibcpp::detail::_interpreter::s_python_function_axvspan
PyObject * s_python_function_axvspan
Definition: matplotlibcpp.h:80
matplotlibcpp::backend
void backend(const std::string &name)
Definition: matplotlibcpp.h:303
matplotlibcpp::detail::_interpreter::s_python_function_tight_layout
PyObject * s_python_function_tight_layout
Definition: matplotlibcpp.h:93
matplotlibcpp::detail::_interpreter::~_interpreter
~_interpreter()
Definition: matplotlibcpp.h:287
matplotlibcpp::detail::_interpreter::s_python_function_boxplot
PyObject * s_python_function_boxplot
Definition: matplotlibcpp.h:68
matplotlibcpp::detail::is_callable
Definition: matplotlibcpp.h:2790
matplotlibcpp::stem
bool stem(const std::vector< Numeric > &x, const std::vector< Numeric > &y, const std::map< std::string, std::string > &keywords)
Definition: matplotlibcpp.h:755
matplotlibcpp::imshow
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
matplotlibcpp::detail::_interpreter::s_python_function_fignum_exists
PyObject * s_python_function_fignum_exists
Definition: matplotlibcpp.h:56
matplotlibcpp::detail::get_2darray
PyObject * get_2darray(const std::vector<::std::vector< Numeric >> &v)
Definition: matplotlibcpp.h:379
matplotlibcpp::named_plot
bool named_plot(const std::string &name, const std::vector< Numeric > &y, const std::string &format="")
Definition: matplotlibcpp.h:1677
matplotlibcpp::detail::_interpreter::s_python_function_stem
PyObject * s_python_function_stem
Definition: matplotlibcpp.h:96
matplotlibcpp::yticks
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
matplotlibcpp::detail::is_callable::type
is_callable_impl< std::is_class< T >::value, T >::type type
Definition: matplotlibcpp.h:2793
Catch::Generators::value
GeneratorWrapper< T > value(T &&value)
Definition: catch.hpp:3999
matplotlibcpp::save
void save(const std::string &filename, const int dpi=0)
Definition: matplotlibcpp.h:2625
fmt::v8::align::left
@ left
Definition: core.h:2021
matplotlibcpp::detail::_interpreter::s_python_function_grid
PyObject * s_python_function_grid
Definition: matplotlibcpp.h:88
matplotlibcpp::named_hist
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
matplotlibcpp::xticks
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
matplotlibcpp::detail::_interpreter::s_python_function_xlim
PyObject * s_python_function_xlim
Definition: matplotlibcpp.h:72
matplotlibcpp::detail::_interpreter::s_python_function_title
PyObject * s_python_function_title
Definition: matplotlibcpp.h:76
matplotlibcpp::scatter_colored
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
matplotlibcpp::fignum_exists
bool fignum_exists(long number)
Definition: matplotlibcpp.h:1906
matplotlibcpp::grid
void grid(bool flag)
Definition: matplotlibcpp.h:2525
matplotlibcpp::spy
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
fmt::v8::align::right
@ right
Definition: core.h:2021
matplotlibcpp::Plot::Plot
Plot(const std::string &name, const std::vector< Numeric > &x, const std::vector< Numeric > &y, const std::string &format="")
Definition: matplotlibcpp.h:2892
matplotlibcpp::xkcd
void xkcd()
Definition: matplotlibcpp.h:2580
detail
Definition: fmt.cpp:13
y
y
Definition: simulate_performance.m:74
matplotlibcpp::detail::_interpreter::s_python_function_arrow
PyObject * s_python_function_arrow
Definition: matplotlibcpp.h:49
matplotlibcpp::detail::_interpreter::s_python_function_ginput
PyObject * s_python_function_ginput
Definition: matplotlibcpp.h:74
matplotlibcpp::detail::plot_impl< std::true_type >::operator()
bool operator()(const Iterable &ticks, const Callable &f, const std::string &format)
Definition: matplotlibcpp.h:2844
matplotlibcpp::legend
void legend()
Definition: matplotlibcpp.h:1944
matplotlibcpp::detail::_interpreter::safe_import
PyObject * safe_import(PyObject *module, std::string fname)
Definition: matplotlibcpp.h:135
x
x
Definition: simulate_performance.m:69
y1
y1
Definition: simulate_performance.m:33
matplotlibcpp::detail::_interpreter::get
static _interpreter & get()
Definition: matplotlibcpp.h:119
matplotlibcpp::detail::_interpreter
Definition: matplotlibcpp.h:48
matplotlibcpp::plot3
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
matplotlibcpp::figure_size
void figure_size(size_t w, size_t h)
Definition: matplotlibcpp.h:1922
matplotlibcpp::barh
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
matplotlibcpp::Plot::decref
void decref()
Definition: matplotlibcpp.h:2974
matplotlibcpp::fill
bool fill(const std::vector< Numeric > &x, const std::vector< Numeric > &y, const std::map< std::string, std::string > &keywords)
Definition: matplotlibcpp.h:790
matplotlibcpp::detail::_interpreter::s_python_function_colorbar
PyObject * s_python_function_colorbar
Definition: matplotlibcpp.h:102
matplotlibcpp::rcparams
void rcparams(const std::map< std::string, std::string > &keywords={})
Definition: matplotlibcpp.h:2649
matplotlibcpp::detail::_interpreter::s_python_function_plot
PyObject * s_python_function_plot
Definition: matplotlibcpp.h:57
matplotlibcpp::figure
long figure(long number=-1)
Definition: matplotlibcpp.h:1875
matplotlibcpp::detail::_interpreter::s_python_function_errorbar
PyObject * s_python_function_errorbar
Definition: matplotlibcpp.h:91
matplotlibcpp::detail::_interpreter::_interpreter
_interpreter()
Definition: matplotlibcpp.h:166
matplotlibcpp::close
void close()
Definition: matplotlibcpp.h:2567
matplotlibcpp::detail::_interpreter::s_python_function_annotate
PyObject * s_python_function_annotate
Definition: matplotlibcpp.h:92
matplotlibcpp::detail::_interpreter::s_python_function_ion
PyObject * s_python_function_ion
Definition: matplotlibcpp.h:73
T
T
Definition: simulate_performance.m:4
matplotlibcpp
Definition: matplotlibcpp.h:43
matplotlibcpp::detail::_interpreter::s_python_function_pause
PyObject * s_python_function_pause
Definition: matplotlibcpp.h:53
filename
filename
Definition: parse_all_dl.m:14
matplotlibcpp::detail::_interpreter::s_python_function_fill
PyObject * s_python_function_fill
Definition: matplotlibcpp.h:63
matplotlibcpp::cla
void cla()
Definition: matplotlibcpp.h:2680
matplotlibcpp::detail::get_listlist
PyObject * get_listlist(const std::vector< std::vector< Numeric >> &ll)
Definition: matplotlibcpp.h:427
matplotlibcpp::detail::_interpreter::s_python_function_close
PyObject * s_python_function_close
Definition: matplotlibcpp.h:51
matplotlibcpp::detail::_interpreter::s_python_function_fill_between
PyObject * s_python_function_fill_between
Definition: matplotlibcpp.h:64
matplotlibcpp::Plot::Plot
Plot(const std::string &name="", const std::string &format="")
Definition: matplotlibcpp.h:2930
matplotlibcpp::detail::_interpreter::s_python_function_bar
PyObject * s_python_function_bar
Definition: matplotlibcpp.h:100
matplotlibcpp::detail::_interpreter::s_python_function_gca
PyObject * s_python_function_gca
Definition: matplotlibcpp.h:83
matplotlibcpp::detail::select_npy_type
Definition: matplotlibcpp.h:338
matplotlibcpp::errorbar
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
matplotlibcpp::detail::plot_impl< std::false_type >
Definition: matplotlibcpp.h:2800
plot_csv.rows
list rows
Definition: plot_csv.py:9
matplotlibcpp::detail::_interpreter::s_python_function_figure
PyObject * s_python_function_figure
Definition: matplotlibcpp.h:55
matplotlibcpp::semilogy
bool semilogy(const std::vector< NumericX > &x, const std::vector< NumericY > &y, const std::string &s="")
Definition: matplotlibcpp.h:1590
matplotlibcpp::annotate
bool annotate(std::string annotation, double x, double y)
Definition: matplotlibcpp.h:308
fmt::v8::ptr
auto ptr(T p) -> const void *
Definition: format.h:2680
matplotlibcpp::detail::_interpreter::s_python_function_rcparams
PyObject * s_python_function_rcparams
Definition: matplotlibcpp.h:104
nlohmann::json_v3_11_1NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON::detail2::begin
begin_tag begin(T &&...)
matplotlibcpp::detail::_interpreter::s_python_function_cla
PyObject * s_python_function_cla
Definition: matplotlibcpp.h:89
len
uint16_t len
Definition: eth_common.h:62
i
for i
Definition: generate_data.m:107
matplotlibcpp::detail::_interpreter::s_python_function_yticks
PyObject * s_python_function_yticks
Definition: matplotlibcpp.h:85
matplotlibcpp::xlim
void xlim(Numeric left, Numeric right)
Definition: matplotlibcpp.h:2048
matplotlibcpp::detail::_interpreter::s_python_function_legend
PyObject * s_python_function_legend
Definition: matplotlibcpp.h:71
matplotlibcpp::boxplot
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
matplotlibcpp::colorbar
void colorbar(PyObject *mappable=NULL, const std::map< std::string, float > &keywords={})
Definition: matplotlibcpp.h:1850
matplotlibcpp::set_aspect
void set_aspect(Numeric ratio)
Definition: matplotlibcpp.h:1973
u
Plot Rx waveform for u
Definition: inspect_single_frame.m:108
matplotlibcpp::detail::_interpreter::s_python_function_imshow
PyObject * s_python_function_imshow
Definition: matplotlibcpp.h:66
matplotlibcpp::detail::_interpreter::s_python_function_save
PyObject * s_python_function_save
Definition: matplotlibcpp.h:54
matplotlibcpp::tick_params
void tick_params(const std::map< std::string, std::string > &keywords, const std::string axis="both")
Definition: matplotlibcpp.h:2226
matplotlibcpp::arrow
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
matplotlibcpp::ginput
std::vector< std::array< double, 2 > > ginput(const int numClicks=1, const std::map< std::string, std::string > &keywords={})
Definition: matplotlibcpp.h:2704
matplotlibcpp::subplots_adjust
bool subplots_adjust(const std::map< std::string, double > &keywords={})
Definition: matplotlibcpp.h:1308
matplotlibcpp::contour
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
matplotlibcpp::show
void show(const bool block=true)
Definition: matplotlibcpp.h:2542
matplotlibcpp::named_semilogx
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
matplotlibcpp::bar
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
matplotlibcpp::suptitle
void suptitle(const std::string &suptitlestr, const std::map< std::string, std::string > &keywords={})
Definition: matplotlibcpp.h:2317
matplotlibcpp::detail::_interpreter::s_python_function_subplots_adjust
PyObject * s_python_function_subplots_adjust
Definition: matplotlibcpp.h:103
matplotlibcpp::detail::_interpreter::s_python_function_quiver
PyObject * s_python_function_quiver
Definition: matplotlibcpp.h:58
matplotlibcpp::detail::get_array
PyObject * get_array(const std::vector< Numeric > &v)
Definition: matplotlibcpp.h:359
matplotlibcpp::detail::_interpreter::s_python_function_axis
PyObject * s_python_function_axis
Definition: matplotlibcpp.h:77
matplotlibcpp::detail::plot_impl< std::false_type >::operator()
bool operator()(const IterableX &x, const IterableY &y, const std::string &format)
Definition: matplotlibcpp.h:2803
matplotlibcpp::detail::_interpreter::s_python_function_semilogx
PyObject * s_python_function_semilogx
Definition: matplotlibcpp.h:60
matplotlibcpp::axvspan
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
s
s
Definition: simulate_performance.m:3
matplotlibcpp::detail::_interpreter::kill
static _interpreter & kill()
Definition: matplotlibcpp.h:123
matplotlibcpp::text
void text(Numeric x, Numeric y, const std::string &s="")
Definition: matplotlibcpp.h:1834
matplotlibcpp::detail::_interpreter::s_python_function_tick_params
PyObject * s_python_function_tick_params
Definition: matplotlibcpp.h:87
matplotlibcpp::detail::_interpreter::import_numpy
void import_numpy()
Definition: matplotlibcpp.h:159
extract_version.data
dictionary data
Definition: extract_version.py:8
matplotlibcpp::detail::_interpreter::s_python_function_semilogy
PyObject * s_python_function_semilogy
Definition: matplotlibcpp.h:61
matplotlibcpp::named_loglog
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
matplotlibcpp::detail::_interpreter::s_python_function_contour
PyObject * s_python_function_contour
Definition: matplotlibcpp.h:59
matplotlibcpp::detail::_interpreter::s_python_function_hist
PyObject * s_python_function_hist
Definition: matplotlibcpp.h:65
matplotlibcpp::pause
void pause(Numeric interval)
Definition: matplotlibcpp.h:2611
matplotlibcpp::axvline
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
matplotlibcpp::detail::s_backend
static std::string s_backend
Definition: matplotlibcpp.h:46
matplotlibcpp::detail::_interpreter::s_python_function_draw
PyObject * s_python_function_draw
Definition: matplotlibcpp.h:52
matplotlibcpp::detail::_interpreter::s_python_function_barh
PyObject * s_python_function_barh
Definition: matplotlibcpp.h:101
std
Definition: json.hpp:5213
matplotlibcpp::detail::_interpreter::s_python_function_xticks
PyObject * s_python_function_xticks
Definition: matplotlibcpp.h:84
matplotlibcpp::tight_layout
void tight_layout()
Definition: matplotlibcpp.h:2741
matplotlibcpp::subplot
void subplot(long nrows, long ncols, long plot_number)
Definition: matplotlibcpp.h:2252
matplotlibcpp::detail::_interpreter::interkeeper
static _interpreter & interkeeper(bool should_kill)
Definition: matplotlibcpp.h:128
matplotlibcpp::set_zlabel
void set_zlabel(const std::string &str, const std::map< std::string, std::string > &keywords={})
Definition: matplotlibcpp.h:2473
fmt::v8::detail::copy
OutputIterator copy(const RangeT &range, OutputIterator out)
Definition: ranges.h:26
matplotlibcpp::detail::_interpreter::s_python_function_loglog
PyObject * s_python_function_loglog
Definition: matplotlibcpp.h:62
matplotlibcpp::set_aspect_equal
void set_aspect_equal()
Definition: matplotlibcpp.h:2000
y2
y2
Definition: simulate_performance.m:35
matplotlibcpp::clf
void clf()
Definition: matplotlibcpp.h:2668
matplotlibcpp::detail::_interpreter::s_python_function_xkcd
PyObject * s_python_function_xkcd
Definition: matplotlibcpp.h:97
matplotlibcpp::detail::_interpreter::s_python_function_suptitle
PyObject * s_python_function_suptitle
Definition: matplotlibcpp.h:99
matplotlibcpp::xlabel
void xlabel(const std::string &str, const std::map< std::string, std::string > &keywords={})
Definition: matplotlibcpp.h:2431
matplotlibcpp::detail::is_callable_impl< false, T >::type
is_function< T > type
Definition: matplotlibcpp.h:2766
matplotlibcpp::detail::_interpreter::s_python_function_ylabel
PyObject * s_python_function_ylabel
Definition: matplotlibcpp.h:82
matplotlibcpp::named_semilogy
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
matplotlibcpp::ylim
void ylim(Numeric left, Numeric right)
Definition: matplotlibcpp.h:2029
matplotlibcpp::detail::select_npy_type::type
const static NPY_TYPES type
Definition: matplotlibcpp.h:338
matplotlibcpp::detail::imshow
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
matplotlibcpp::title
void title(const std::string &titlestr, const std::map< std::string, std::string > &keywords={})
Definition: matplotlibcpp.h:2296
matplotlibcpp::axis
void axis(const std::string &axisstr)
Definition: matplotlibcpp.h:2338
matplotlibcpp::detail::_interpreter::s_python_function_axhline
PyObject * s_python_function_axhline
Definition: matplotlibcpp.h:78
matplotlibcpp::Plot::remove
void remove()
Definition: matplotlibcpp.h:2958
matplotlibcpp::loglog
bool loglog(const std::vector< NumericX > &x, const std::vector< NumericY > &y, const std::string &s="")
Definition: matplotlibcpp.h:1615
matplotlibcpp::detail::_interpreter::s_python_empty_tuple
PyObject * s_python_empty_tuple
Definition: matplotlibcpp.h:95
matplotlibcpp::ion
void ion()
Definition: matplotlibcpp.h:2692
matplotlibcpp::detail::_interpreter::s_python_function_axvline
PyObject * s_python_function_axvline
Definition: matplotlibcpp.h:79
matplotlibcpp::Plot::~Plot
~Plot()
Definition: matplotlibcpp.h:2969
matplotlibcpp::margins
void margins(Numeric margin)
Definition: matplotlibcpp.h:2194
matplotlibcpp::detail::_interpreter::s_python_function_spy
PyObject * s_python_function_spy
Definition: matplotlibcpp.h:105
matplotlibcpp::detail::_interpreter::s_python_function_scatter
PyObject * s_python_function_scatter
Definition: matplotlibcpp.h:67
nlohmann::json_v3_11_1NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON::detail2::end
end_tag end(T &&...)
matplotlibcpp::scatter
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
utils::format
std::string format(const T &value)
Definition: utils.h:15
fmt::v8::detail::type
type
Definition: core.h:1131
matplotlibcpp::detail::_interpreter::s_python_colormap
PyObject * s_python_colormap
Definition: matplotlibcpp.h:94
matplotlibcpp::axhline
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
matplotlibcpp::detail::_interpreter::s_python_function_text
PyObject * s_python_function_text
Definition: matplotlibcpp.h:98
matplotlibcpp::detail::is_function
typename std::is_function< std::remove_pointer< std::remove_reference< T > >>::type is_function
Definition: matplotlibcpp.h:2758
matplotlibcpp::fill_between
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
matplotlibcpp::ylabel
void ylabel(const std::string &str, const std::map< std::string, std::string > &keywords={})
Definition: matplotlibcpp.h:2452
matplotlibcpp::detail::_interpreter::s_python_function_subplot2grid
PyObject * s_python_function_subplot2grid
Definition: matplotlibcpp.h:70