irafhy
Interval arithmetic based Reachability Analysis Framework for Hybrid Automaton
matplotlibcpp.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <vector>
4 #include <map>
5 #include <array>
6 #include <numeric>
7 #include <algorithm>
8 #include <stdexcept>
9 #include <iostream>
10 #include <cstdint> // <cstdint> requires c++11 support
11 #include <functional>
12 
13 #include <Python.h>
14 
15 #ifndef WITHOUT_NUMPY
16 # define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
17 # include <numpy/arrayobject.h>
18 
19 # ifdef WITH_OPENCV
20 # include <opencv2/opencv.hpp>
21 # endif // WITH_OPENCV
22 
23 /*
24  * A bunch of constants were removed in OpenCV 4 in favour of enum classes, so
25  * define the ones we need here.
26  */
27 # if CV_MAJOR_VERSION > 3
28 # define CV_BGR2RGB cv::COLOR_BGR2RGB
29 # define CV_BGRA2RGBA cv::COLOR_BGRA2RGBA
30 # endif
31 #endif // WITHOUT_NUMPY
32 
33 #if PY_MAJOR_VERSION >= 3
34 # define PyString_FromString PyUnicode_FromString
35 # define PyInt_FromLong PyLong_FromLong
36 # define PyString_FromString PyUnicode_FromString
37 #endif
38 
39 
40 namespace matplotlibcpp {
41 namespace detail {
42 
43 static std::string s_backend;
44 
45 struct _interpreter {
80  PyObject *s_python_colormap;
88 
89 
90  /* For now, _interpreter is implemented as a singleton since its currently not possible to have
91  multiple independent embedded python interpreters without patching the python source code
92  or starting a separate process for each.
93  http://bytes.com/topic/python/answers/793370-multiple-independent-python-interpreters-c-c-program
94  */
95 
96  static _interpreter& get() {
97  static _interpreter ctx;
98  return ctx;
99  }
100 
101  PyObject* safe_import(PyObject* module, std::string fname) {
102  PyObject* fn = PyObject_GetAttrString(module, fname.c_str());
103 
104  if (!fn)
105  throw std::runtime_error(std::string("Couldn't find required function: ") + fname);
106 
107  if (!PyFunction_Check(fn))
108  throw std::runtime_error(fname + std::string(" is unexpectedly not a PyFunction."));
109 
110  return fn;
111  }
112 
113 private:
114 
115 #ifndef WITHOUT_NUMPY
116 # if PY_MAJOR_VERSION >= 3
117 
118  void *import_numpy() {
119  import_array(); // initialize C-API
120  return NULL;
121  }
122 
123 # else
124 
125  void import_numpy() {
126  import_array(); // initialize C-API
127  }
128 
129 # endif
130 #endif
131 
133 
134  // optional but recommended
135 #if PY_MAJOR_VERSION >= 3
136  wchar_t name[] = L"plotting";
137 #else
138  char name[] = "plotting";
139 #endif
140  Py_SetProgramName(name);
141  Py_Initialize();
142 
143 #ifndef WITHOUT_NUMPY
144  import_numpy(); // initialize numpy C-API
145 #endif
146 
147  PyObject* matplotlibname = PyString_FromString("matplotlib");
148  PyObject* pyplotname = PyString_FromString("matplotlib.pyplot");
149  PyObject* cmname = PyString_FromString("matplotlib.cm");
150  PyObject* pylabname = PyString_FromString("pylab");
151  if (!pyplotname || !pylabname || !matplotlibname || !cmname) {
152  throw std::runtime_error("couldnt create string");
153  }
154 
155  PyObject* matplotlib = PyImport_Import(matplotlibname);
156  Py_DECREF(matplotlibname);
157  if (!matplotlib) {
158  PyErr_Print();
159  throw std::runtime_error("Error loading module matplotlib!");
160  }
161 
162  // matplotlib.use() must be called *before* pylab, matplotlib.pyplot,
163  // or matplotlib.backends is imported for the first time
164  if (!s_backend.empty()) {
165  PyObject_CallMethod(matplotlib, const_cast<char*>("use"), const_cast<char*>("s"), s_backend.c_str());
166  }
167 
168  PyObject* pymod = PyImport_Import(pyplotname);
169  Py_DECREF(pyplotname);
170  if (!pymod) { throw std::runtime_error("Error loading module matplotlib.pyplot!"); }
171 
172  s_python_colormap = PyImport_Import(cmname);
173  Py_DECREF(cmname);
174  if (!s_python_colormap) { throw std::runtime_error("Error loading module matplotlib.cm!"); }
175 
176  PyObject* pylabmod = PyImport_Import(pylabname);
177  Py_DECREF(pylabname);
178  if (!pylabmod) { throw std::runtime_error("Error loading module pylab!"); }
179 
180  s_python_function_show = safe_import(pymod, "show");
181  s_python_function_close = safe_import(pymod, "close");
182  s_python_function_draw = safe_import(pymod, "draw");
183  s_python_function_pause = safe_import(pymod, "pause");
184  s_python_function_figure = safe_import(pymod, "figure");
185  s_python_function_fignum_exists = safe_import(pymod, "fignum_exists");
186  s_python_function_plot = safe_import(pymod, "plot");
187  s_python_function_quiver = safe_import(pymod, "quiver");
188  s_python_function_semilogx = safe_import(pymod, "semilogx");
189  s_python_function_semilogy = safe_import(pymod, "semilogy");
190  s_python_function_loglog = safe_import(pymod, "loglog");
191  s_python_function_fill = safe_import(pymod, "fill");
192  s_python_function_fill_between = safe_import(pymod, "fill_between");
193  s_python_function_hist = safe_import(pymod,"hist");
194  s_python_function_scatter = safe_import(pymod,"scatter");
195  s_python_function_subplot = safe_import(pymod, "subplot");
196  s_python_function_legend = safe_import(pymod, "legend");
197  s_python_function_ylim = safe_import(pymod, "ylim");
198  s_python_function_title = safe_import(pymod, "title");
199  s_python_function_axis = safe_import(pymod, "axis");
200  s_python_function_xlabel = safe_import(pymod, "xlabel");
201  s_python_function_ylabel = safe_import(pymod, "ylabel");
202  s_python_function_xticks = safe_import(pymod, "xticks");
203  s_python_function_yticks = safe_import(pymod, "yticks");
204  s_python_function_grid = safe_import(pymod, "grid");
205  s_python_function_xlim = safe_import(pymod, "xlim");
206  s_python_function_ion = safe_import(pymod, "ion");
207  s_python_function_ginput = safe_import(pymod, "ginput");
208  s_python_function_save = safe_import(pylabmod, "savefig");
209  s_python_function_annotate = safe_import(pymod,"annotate");
210  s_python_function_clf = safe_import(pymod, "clf");
211  s_python_function_errorbar = safe_import(pymod, "errorbar");
212  s_python_function_tight_layout = safe_import(pymod, "tight_layout");
213  s_python_function_stem = safe_import(pymod, "stem");
214  s_python_function_xkcd = safe_import(pymod, "xkcd");
215  s_python_function_text = safe_import(pymod, "text");
216  s_python_function_suptitle = safe_import(pymod, "suptitle");
217  s_python_function_bar = safe_import(pymod,"bar");
218  s_python_function_subplots_adjust = safe_import(pymod,"subplots_adjust");
219 #ifndef WITHOUT_NUMPY
220  s_python_function_imshow = safe_import(pymod, "imshow");
221 #endif
222 
223  s_python_empty_tuple = PyTuple_New(0);
224  }
225 
227  Py_Finalize();
228  }
229 };
230 
231 } // end namespace detail
232 
233 // must be called before the first regular call to matplotlib to have any effect
234 inline void backend(const std::string& name)
235 {
236  detail::s_backend = name;
237 }
238 
239 inline bool annotate(std::string annotation, double x, double y)
240 {
241  PyObject * xy = PyTuple_New(2);
242  PyObject * str = PyString_FromString(annotation.c_str());
243 
244  PyTuple_SetItem(xy,0,PyFloat_FromDouble(x));
245  PyTuple_SetItem(xy,1,PyFloat_FromDouble(y));
246 
247  PyObject* kwargs = PyDict_New();
248  PyDict_SetItemString(kwargs, "xy", xy);
249 
250  PyObject* args = PyTuple_New(1);
251  PyTuple_SetItem(args, 0, str);
252 
253  PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_annotate, args, kwargs);
254 
255  Py_DECREF(args);
256  Py_DECREF(kwargs);
257 
258  if(res) Py_DECREF(res);
259 
260  return res;
261 }
262 
263 #ifndef WITHOUT_NUMPY
264 // Type selector for numpy array conversion
265 template <typename T> struct select_npy_type { const static NPY_TYPES type = NPY_NOTYPE; }; //Default
266 template <> struct select_npy_type<double> { const static NPY_TYPES type = NPY_DOUBLE; };
267 template <> struct select_npy_type<float> { const static NPY_TYPES type = NPY_FLOAT; };
268 template <> struct select_npy_type<bool> { const static NPY_TYPES type = NPY_BOOL; };
269 template <> struct select_npy_type<int8_t> { const static NPY_TYPES type = NPY_INT8; };
270 template <> struct select_npy_type<int16_t> { const static NPY_TYPES type = NPY_SHORT; };
271 template <> struct select_npy_type<int32_t> { const static NPY_TYPES type = NPY_INT; };
272 template <> struct select_npy_type<int64_t> { const static NPY_TYPES type = NPY_INT64; };
273 template <> struct select_npy_type<uint8_t> { const static NPY_TYPES type = NPY_UINT8; };
274 template <> struct select_npy_type<uint16_t> { const static NPY_TYPES type = NPY_USHORT; };
275 template <> struct select_npy_type<uint32_t> { const static NPY_TYPES type = NPY_ULONG; };
276 template <> struct select_npy_type<uint64_t> { const static NPY_TYPES type = NPY_UINT64; };
277 
278 template<typename Numeric>
279 PyObject* get_array(const std::vector<Numeric>& v)
280 {
281  detail::_interpreter::get(); //interpreter needs to be initialized for the numpy commands to work
282  NPY_TYPES type = select_npy_type<Numeric>::type;
283  if (type == NPY_NOTYPE)
284  {
285  std::vector<double> vd(v.size());
286  npy_intp vsize = v.size();
287  std::copy(v.begin(),v.end(),vd.begin());
288  PyObject* varray = PyArray_SimpleNewFromData(1, &vsize, NPY_DOUBLE, (void*)(vd.data()));
289  return varray;
290  }
291 
292  npy_intp vsize = v.size();
293  PyObject* varray = PyArray_SimpleNewFromData(1, &vsize, type, (void*)(v.data()));
294  return varray;
295 }
296 
297 template<typename Numeric>
298 PyObject* get_2darray(const std::vector<::std::vector<Numeric>>& v)
299 {
300  detail::_interpreter::get(); //interpreter needs to be initialized for the numpy commands to work
301  if (v.size() < 1) throw std::runtime_error("get_2d_array v too small");
302 
303  npy_intp vsize[2] = {static_cast<npy_intp>(v.size()),
304  static_cast<npy_intp>(v[0].size())};
305 
306  PyArrayObject *varray =
307  (PyArrayObject *)PyArray_SimpleNew(2, vsize, NPY_DOUBLE);
308 
309  double *vd_begin = static_cast<double *>(PyArray_DATA(varray));
310 
311  for (const ::std::vector<Numeric> &v_row : v) {
312  if (v_row.size() != static_cast<size_t>(vsize[1]))
313  throw std::runtime_error("Missmatched array size");
314  std::copy(v_row.begin(), v_row.end(), vd_begin);
315  vd_begin += vsize[1];
316  }
317 
318  return reinterpret_cast<PyObject *>(varray);
319 }
320 
321 #else // fallback if we don't have numpy: copy every element of the given vector
322 
323 template<typename Numeric>
324 PyObject* get_array(const std::vector<Numeric>& v)
325 {
326  PyObject* list = PyList_New(v.size());
327  for(size_t i = 0; i < v.size(); ++i) {
328  PyList_SetItem(list, i, PyFloat_FromDouble(v.at(i)));
329  }
330  return list;
331 }
332 
333 #endif // WITHOUT_NUMPY
334 
335 template<typename Numeric>
336 bool plot(const std::vector<Numeric> &x, const std::vector<Numeric> &y, const std::map<std::string, std::string>& keywords)
337 {
338  assert(x.size() == y.size());
339 
340  // using numpy arrays
341  PyObject* xarray = get_array(x);
342  PyObject* yarray = get_array(y);
343 
344  // construct positional args
345  PyObject* args = PyTuple_New(2);
346  PyTuple_SetItem(args, 0, xarray);
347  PyTuple_SetItem(args, 1, yarray);
348 
349  // construct keyword args
350  PyObject* kwargs = PyDict_New();
351  for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
352  {
353  PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
354  }
355 
356  PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_plot, args, kwargs);
357 
358  Py_DECREF(args);
359  Py_DECREF(kwargs);
360  if(res) Py_DECREF(res);
361 
362  return res;
363 }
364 
365 template <typename Numeric>
366 void plot_surface(const std::vector<::std::vector<Numeric>> &x,
367  const std::vector<::std::vector<Numeric>> &y,
368  const std::vector<::std::vector<Numeric>> &z,
369  const std::map<std::string, std::string> &keywords =
370  std::map<std::string, std::string>())
371 {
372  // We lazily load the modules here the first time this function is called
373  // because I'm not sure that we can assume "matplotlib installed" implies
374  // "mpl_toolkits installed" on all platforms, and we don't want to require
375  // it for people who don't need 3d plots.
376  static PyObject *mpl_toolkitsmod = nullptr, *axis3dmod = nullptr;
377  if (!mpl_toolkitsmod) {
379 
380  PyObject* mpl_toolkits = PyString_FromString("mpl_toolkits");
381  PyObject* axis3d = PyString_FromString("mpl_toolkits.mplot3d");
382  if (!mpl_toolkits || !axis3d) { throw std::runtime_error("couldnt create string"); }
383 
384  mpl_toolkitsmod = PyImport_Import(mpl_toolkits);
385  Py_DECREF(mpl_toolkits);
386  if (!mpl_toolkitsmod) { throw std::runtime_error("Error loading module mpl_toolkits!"); }
387 
388  axis3dmod = PyImport_Import(axis3d);
389  Py_DECREF(axis3d);
390  if (!axis3dmod) { throw std::runtime_error("Error loading module mpl_toolkits.mplot3d!"); }
391  }
392 
393  assert(x.size() == y.size());
394  assert(y.size() == z.size());
395 
396  // using numpy arrays
397  PyObject *xarray = get_2darray(x);
398  PyObject *yarray = get_2darray(y);
399  PyObject *zarray = get_2darray(z);
400 
401  // construct positional args
402  PyObject *args = PyTuple_New(3);
403  PyTuple_SetItem(args, 0, xarray);
404  PyTuple_SetItem(args, 1, yarray);
405  PyTuple_SetItem(args, 2, zarray);
406 
407  // Build up the kw args.
408  PyObject *kwargs = PyDict_New();
409  PyDict_SetItemString(kwargs, "rstride", PyInt_FromLong(1));
410  PyDict_SetItemString(kwargs, "cstride", PyInt_FromLong(1));
411 
412  PyObject *python_colormap_coolwarm = PyObject_GetAttrString(
414 
415  PyDict_SetItemString(kwargs, "cmap", python_colormap_coolwarm);
416 
417  for (std::map<std::string, std::string>::const_iterator it = keywords.begin();
418  it != keywords.end(); ++it) {
419  PyDict_SetItemString(kwargs, it->first.c_str(),
420  PyString_FromString(it->second.c_str()));
421  }
422 
423 
424  PyObject *fig =
427  if (!fig) throw std::runtime_error("Call to figure() failed.");
428 
429  PyObject *gca_kwargs = PyDict_New();
430  PyDict_SetItemString(gca_kwargs, "projection", PyString_FromString("3d"));
431 
432  PyObject *gca = PyObject_GetAttrString(fig, "gca");
433  if (!gca) throw std::runtime_error("No gca");
434  Py_INCREF(gca);
435  PyObject *axis = PyObject_Call(
437 
438  if (!axis) throw std::runtime_error("No axis");
439  Py_INCREF(axis);
440 
441  Py_DECREF(gca);
442  Py_DECREF(gca_kwargs);
443 
444  PyObject *plot_surface = PyObject_GetAttrString(axis, "plot_surface");
445  if (!plot_surface) throw std::runtime_error("No surface");
446  Py_INCREF(plot_surface);
447  PyObject *res = PyObject_Call(plot_surface, args, kwargs);
448  if (!res) throw std::runtime_error("failed surface");
449  Py_DECREF(plot_surface);
450 
451  Py_DECREF(axis);
452  Py_DECREF(args);
453  Py_DECREF(kwargs);
454  if (res) Py_DECREF(res);
455 }
456 
457 template<typename Numeric>
458 bool stem(const std::vector<Numeric> &x, const std::vector<Numeric> &y, const std::map<std::string, std::string>& keywords)
459 {
460  assert(x.size() == y.size());
461 
462  // using numpy arrays
463  PyObject* xarray = get_array(x);
464  PyObject* yarray = get_array(y);
465 
466  // construct positional args
467  PyObject* args = PyTuple_New(2);
468  PyTuple_SetItem(args, 0, xarray);
469  PyTuple_SetItem(args, 1, yarray);
470 
471  // construct keyword args
472  PyObject* kwargs = PyDict_New();
473  for (std::map<std::string, std::string>::const_iterator it =
474  keywords.begin(); it != keywords.end(); ++it) {
475  PyDict_SetItemString(kwargs, it->first.c_str(),
476  PyString_FromString(it->second.c_str()));
477  }
478 
479  PyObject* res = PyObject_Call(
481 
482  Py_DECREF(args);
483  Py_DECREF(kwargs);
484  if (res)
485  Py_DECREF(res);
486 
487  return res;
488 }
489 
490 template< typename Numeric >
491 bool fill(const std::vector<Numeric>& x, const std::vector<Numeric>& y, const std::map<std::string, std::string>& keywords)
492 {
493  assert(x.size() == y.size());
494 
495  // using numpy arrays
496  PyObject* xarray = get_array(x);
497  PyObject* yarray = get_array(y);
498 
499  // construct positional args
500  PyObject* args = PyTuple_New(2);
501  PyTuple_SetItem(args, 0, xarray);
502  PyTuple_SetItem(args, 1, yarray);
503 
504  // construct keyword args
505  PyObject* kwargs = PyDict_New();
506  for (auto it = keywords.begin(); it != keywords.end(); ++it) {
507  PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
508  }
509 
510  PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_fill, args, kwargs);
511 
512  Py_DECREF(args);
513  Py_DECREF(kwargs);
514 
515  if (res) Py_DECREF(res);
516 
517  return res;
518 }
519 
520 template< typename Numeric >
521 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)
522 {
523  assert(x.size() == y1.size());
524  assert(x.size() == y2.size());
525 
526  // using numpy arrays
527  PyObject* xarray = get_array(x);
528  PyObject* y1array = get_array(y1);
529  PyObject* y2array = get_array(y2);
530 
531  // construct positional args
532  PyObject* args = PyTuple_New(3);
533  PyTuple_SetItem(args, 0, xarray);
534  PyTuple_SetItem(args, 1, y1array);
535  PyTuple_SetItem(args, 2, y2array);
536 
537  // construct keyword args
538  PyObject* kwargs = PyDict_New();
539  for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it) {
540  PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
541  }
542 
543  PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_fill_between, args, kwargs);
544 
545  Py_DECREF(args);
546  Py_DECREF(kwargs);
547  if(res) Py_DECREF(res);
548 
549  return res;
550 }
551 
552 template< typename Numeric>
553 bool hist(const std::vector<Numeric>& y, long bins=10,std::string color="b",
554  double alpha=1.0, bool cumulative=false)
555 {
556 
557  PyObject* yarray = get_array(y);
558 
559  PyObject* kwargs = PyDict_New();
560  PyDict_SetItemString(kwargs, "bins", PyLong_FromLong(bins));
561  PyDict_SetItemString(kwargs, "color", PyString_FromString(color.c_str()));
562  PyDict_SetItemString(kwargs, "alpha", PyFloat_FromDouble(alpha));
563  PyDict_SetItemString(kwargs, "cumulative", cumulative ? Py_True : Py_False);
564 
565  PyObject* plot_args = PyTuple_New(1);
566 
567  PyTuple_SetItem(plot_args, 0, yarray);
568 
569 
570  PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_hist, plot_args, kwargs);
571 
572 
573  Py_DECREF(plot_args);
574  Py_DECREF(kwargs);
575  if(res) Py_DECREF(res);
576 
577  return res;
578 }
579 
580 #ifndef WITHOUT_NUMPY
581  namespace internal {
582  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)
583  {
584  assert(type == NPY_UINT8 || type == NPY_FLOAT);
585  assert(colors == 1 || colors == 3 || colors == 4);
586 
587  detail::_interpreter::get(); //interpreter needs to be initialized for the numpy commands to work
588 
589  // construct args
590  npy_intp dims[3] = { rows, columns, colors };
591  PyObject *args = PyTuple_New(1);
592  PyTuple_SetItem(args, 0, PyArray_SimpleNewFromData(colors == 1 ? 2 : 3, dims, type, ptr));
593 
594  // construct keyword args
595  PyObject* kwargs = PyDict_New();
596  for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
597  {
598  PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
599  }
600 
601  PyObject *res = PyObject_Call(detail::_interpreter::get().s_python_function_imshow, args, kwargs);
602  Py_DECREF(args);
603  Py_DECREF(kwargs);
604  if (!res)
605  throw std::runtime_error("Call to imshow() failed");
606  Py_DECREF(res);
607  }
608  }
609 
610  void imshow(const unsigned char *ptr, const int rows, const int columns, const int colors, const std::map<std::string, std::string> &keywords = {})
611  {
612  internal::imshow((void *) ptr, NPY_UINT8, rows, columns, colors, keywords);
613  }
614 
615  void imshow(const float *ptr, const int rows, const int columns, const int colors, const std::map<std::string, std::string> &keywords = {})
616  {
617  internal::imshow((void *) ptr, NPY_FLOAT, rows, columns, colors, keywords);
618  }
619 
620 #ifdef WITH_OPENCV
621  void imshow(const cv::Mat &image, const std::map<std::string, std::string> &keywords = {})
622  {
623  // Convert underlying type of matrix, if needed
624  cv::Mat image2;
625  NPY_TYPES npy_type = NPY_UINT8;
626  switch (image.type() & CV_MAT_DEPTH_MASK) {
627  case CV_8U:
628  image2 = image;
629  break;
630  case CV_32F:
631  image2 = image;
632  npy_type = NPY_FLOAT;
633  break;
634  default:
635  image.convertTo(image2, CV_MAKETYPE(CV_8U, image.channels()));
636  }
637 
638  // If color image, convert from BGR to RGB
639  switch (image2.channels()) {
640  case 3:
641  cv::cvtColor(image2, image2, CV_BGR2RGB);
642  break;
643  case 4:
644  cv::cvtColor(image2, image2, CV_BGRA2RGBA);
645  }
646 
647  internal::imshow(image2.data, npy_type, image2.rows, image2.cols, image2.channels(), keywords);
648  }
649 #endif // WITH_OPENCV
650 #endif // WITHOUT_NUMPY
651 
652 template<typename NumericX, typename NumericY>
653 bool scatter(const std::vector<NumericX>& x,
654  const std::vector<NumericY>& y,
655  const double s=1.0) // The marker size in points**2
656 {
657  assert(x.size() == y.size());
658 
659  PyObject* xarray = get_array(x);
660  PyObject* yarray = get_array(y);
661 
662  PyObject* kwargs = PyDict_New();
663  PyDict_SetItemString(kwargs, "s", PyLong_FromLong(s));
664 
665  PyObject* plot_args = PyTuple_New(2);
666  PyTuple_SetItem(plot_args, 0, xarray);
667  PyTuple_SetItem(plot_args, 1, yarray);
668 
669  PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_scatter, plot_args, kwargs);
670 
671  Py_DECREF(plot_args);
672  Py_DECREF(kwargs);
673  if(res) Py_DECREF(res);
674 
675  return res;
676 }
677 
678 template <typename Numeric>
679 bool bar(const std::vector<Numeric> & x,
680  const std::vector<Numeric> & y,
681  std::string ec = "black",
682  std::string ls = "-",
683  double lw = 1.0,
684  const std::map<std::string, std::string> & keywords = {}) {
685  PyObject * xarray = get_array(x);
686  PyObject * yarray = get_array(y);
687 
688  PyObject * kwargs = PyDict_New();
689 
690  PyDict_SetItemString(kwargs, "ec", PyString_FromString(ec.c_str()));
691  PyDict_SetItemString(kwargs, "ls", PyString_FromString(ls.c_str()));
692  PyDict_SetItemString(kwargs, "lw", PyFloat_FromDouble(lw));
693 
694  for (std::map<std::string, std::string>::const_iterator it =
695  keywords.begin();
696  it != keywords.end();
697  ++it) {
698  PyDict_SetItemString(
699  kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
700  }
701 
702  PyObject * plot_args = PyTuple_New(2);
703  PyTuple_SetItem(plot_args, 0, xarray);
704  PyTuple_SetItem(plot_args, 1, yarray);
705 
706  PyObject * res = PyObject_Call(
707  detail::_interpreter::get().s_python_function_bar, plot_args, kwargs);
708 
709  Py_DECREF(plot_args);
710  Py_DECREF(kwargs);
711  if (res) Py_DECREF(res);
712 
713  return res;
714 }
715 
716 template <typename Numeric>
717 bool bar(const std::vector<Numeric> & y,
718  std::string ec = "black",
719  std::string ls = "-",
720  double lw = 1.0,
721  const std::map<std::string, std::string> & keywords = {}) {
722  using T = typename std::remove_reference<decltype(y)>::type::value_type;
723 
724  std::vector<T> x;
725  for (std::size_t i = 0; i < y.size(); i++) { x.push_back(i); }
726 
727  return bar(x, y, ec, ls, lw, keywords);
728 }
729 
730 inline bool subplots_adjust(const std::map<std::string, double>& keywords = {})
731 {
732 
733  PyObject* kwargs = PyDict_New();
734  for (std::map<std::string, double>::const_iterator it =
735  keywords.begin(); it != keywords.end(); ++it) {
736  PyDict_SetItemString(kwargs, it->first.c_str(),
737  PyFloat_FromDouble(it->second));
738  }
739 
740 
741  PyObject* plot_args = PyTuple_New(0);
742 
743  PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_subplots_adjust, plot_args, kwargs);
744 
745  Py_DECREF(plot_args);
746  Py_DECREF(kwargs);
747  if(res) Py_DECREF(res);
748 
749  return res;
750 }
751 
752 template< typename Numeric>
753 bool named_hist(std::string label,const std::vector<Numeric>& y, long bins=10, std::string color="b", double alpha=1.0)
754 {
755  PyObject* yarray = get_array(y);
756 
757  PyObject* kwargs = PyDict_New();
758  PyDict_SetItemString(kwargs, "label", PyString_FromString(label.c_str()));
759  PyDict_SetItemString(kwargs, "bins", PyLong_FromLong(bins));
760  PyDict_SetItemString(kwargs, "color", PyString_FromString(color.c_str()));
761  PyDict_SetItemString(kwargs, "alpha", PyFloat_FromDouble(alpha));
762 
763 
764  PyObject* plot_args = PyTuple_New(1);
765  PyTuple_SetItem(plot_args, 0, yarray);
766 
767  PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_hist, plot_args, kwargs);
768 
769  Py_DECREF(plot_args);
770  Py_DECREF(kwargs);
771  if(res) Py_DECREF(res);
772 
773  return res;
774 }
775 
776 template<typename NumericX, typename NumericY>
777 bool plot(const std::vector<NumericX>& x, const std::vector<NumericY>& y, const std::string& s = "")
778 {
779  assert(x.size() == y.size());
780 
781  PyObject* xarray = get_array(x);
782  PyObject* yarray = get_array(y);
783 
784  PyObject* pystring = PyString_FromString(s.c_str());
785 
786  PyObject* plot_args = PyTuple_New(3);
787  PyTuple_SetItem(plot_args, 0, xarray);
788  PyTuple_SetItem(plot_args, 1, yarray);
789  PyTuple_SetItem(plot_args, 2, pystring);
790 
791  PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_plot, plot_args);
792 
793  Py_DECREF(plot_args);
794  if(res) Py_DECREF(res);
795 
796  return res;
797 }
798 
799 template<typename NumericX, typename NumericY, typename NumericU, typename NumericW>
800 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 = {})
801 {
802  assert(x.size() == y.size() && x.size() == u.size() && u.size() == w.size());
803 
804  PyObject* xarray = get_array(x);
805  PyObject* yarray = get_array(y);
806  PyObject* uarray = get_array(u);
807  PyObject* warray = get_array(w);
808 
809  PyObject* plot_args = PyTuple_New(4);
810  PyTuple_SetItem(plot_args, 0, xarray);
811  PyTuple_SetItem(plot_args, 1, yarray);
812  PyTuple_SetItem(plot_args, 2, uarray);
813  PyTuple_SetItem(plot_args, 3, warray);
814 
815  // construct keyword args
816  PyObject* kwargs = PyDict_New();
817  for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
818  {
819  PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
820  }
821 
822  PyObject* res = PyObject_Call(
824 
825  Py_DECREF(kwargs);
826  Py_DECREF(plot_args);
827  if (res)
828  Py_DECREF(res);
829 
830  return res;
831 }
832 
833 template<typename NumericX, typename NumericY>
834 bool stem(const std::vector<NumericX>& x, const std::vector<NumericY>& y, const std::string& s = "")
835 {
836  assert(x.size() == y.size());
837 
838  PyObject* xarray = get_array(x);
839  PyObject* yarray = get_array(y);
840 
841  PyObject* pystring = PyString_FromString(s.c_str());
842 
843  PyObject* plot_args = PyTuple_New(3);
844  PyTuple_SetItem(plot_args, 0, xarray);
845  PyTuple_SetItem(plot_args, 1, yarray);
846  PyTuple_SetItem(plot_args, 2, pystring);
847 
848  PyObject* res = PyObject_CallObject(
850 
851  Py_DECREF(plot_args);
852  if (res)
853  Py_DECREF(res);
854 
855  return res;
856 }
857 
858 template<typename NumericX, typename NumericY>
859 bool semilogx(const std::vector<NumericX>& x, const std::vector<NumericY>& y, const std::string& s = "")
860 {
861  assert(x.size() == y.size());
862 
863  PyObject* xarray = get_array(x);
864  PyObject* yarray = get_array(y);
865 
866  PyObject* pystring = PyString_FromString(s.c_str());
867 
868  PyObject* plot_args = PyTuple_New(3);
869  PyTuple_SetItem(plot_args, 0, xarray);
870  PyTuple_SetItem(plot_args, 1, yarray);
871  PyTuple_SetItem(plot_args, 2, pystring);
872 
873  PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_semilogx, plot_args);
874 
875  Py_DECREF(plot_args);
876  if(res) Py_DECREF(res);
877 
878  return res;
879 }
880 
881 template<typename NumericX, typename NumericY>
882 bool semilogy(const std::vector<NumericX>& x, const std::vector<NumericY>& y, const std::string& s = "")
883 {
884  assert(x.size() == y.size());
885 
886  PyObject* xarray = get_array(x);
887  PyObject* yarray = get_array(y);
888 
889  PyObject* pystring = PyString_FromString(s.c_str());
890 
891  PyObject* plot_args = PyTuple_New(3);
892  PyTuple_SetItem(plot_args, 0, xarray);
893  PyTuple_SetItem(plot_args, 1, yarray);
894  PyTuple_SetItem(plot_args, 2, pystring);
895 
896  PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_semilogy, plot_args);
897 
898  Py_DECREF(plot_args);
899  if(res) Py_DECREF(res);
900 
901  return res;
902 }
903 
904 template<typename NumericX, typename NumericY>
905 bool loglog(const std::vector<NumericX>& x, const std::vector<NumericY>& y, const std::string& s = "")
906 {
907  assert(x.size() == y.size());
908 
909  PyObject* xarray = get_array(x);
910  PyObject* yarray = get_array(y);
911 
912  PyObject* pystring = PyString_FromString(s.c_str());
913 
914  PyObject* plot_args = PyTuple_New(3);
915  PyTuple_SetItem(plot_args, 0, xarray);
916  PyTuple_SetItem(plot_args, 1, yarray);
917  PyTuple_SetItem(plot_args, 2, pystring);
918 
919  PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_loglog, plot_args);
920 
921  Py_DECREF(plot_args);
922  if(res) Py_DECREF(res);
923 
924  return res;
925 }
926 
927 template<typename NumericX, typename NumericY>
928 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 = {})
929 {
930  assert(x.size() == y.size());
931 
932  PyObject* xarray = get_array(x);
933  PyObject* yarray = get_array(y);
934  PyObject* yerrarray = get_array(yerr);
935 
936  // construct keyword args
937  PyObject* kwargs = PyDict_New();
938  for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
939  {
940  PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
941  }
942 
943  PyDict_SetItemString(kwargs, "yerr", yerrarray);
944 
945  PyObject *plot_args = PyTuple_New(2);
946  PyTuple_SetItem(plot_args, 0, xarray);
947  PyTuple_SetItem(plot_args, 1, yarray);
948 
949  PyObject *res = PyObject_Call(detail::_interpreter::get().s_python_function_errorbar, plot_args, kwargs);
950 
951  Py_DECREF(kwargs);
952  Py_DECREF(plot_args);
953 
954  if (res)
955  Py_DECREF(res);
956  else
957  throw std::runtime_error("Call to errorbar() failed.");
958 
959  return res;
960 }
961 
962 template<typename Numeric>
963 bool named_plot(const std::string& name, const std::vector<Numeric>& y, const std::string& format = "")
964 {
965  PyObject* kwargs = PyDict_New();
966  PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str()));
967 
968  PyObject* yarray = get_array(y);
969 
970  PyObject* pystring = PyString_FromString(format.c_str());
971 
972  PyObject* plot_args = PyTuple_New(2);
973 
974  PyTuple_SetItem(plot_args, 0, yarray);
975  PyTuple_SetItem(plot_args, 1, pystring);
976 
977  PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_plot, plot_args, kwargs);
978 
979  Py_DECREF(kwargs);
980  Py_DECREF(plot_args);
981  if (res) Py_DECREF(res);
982 
983  return res;
984 }
985 
986 template<typename Numeric>
987 bool named_plot(const std::string& name, const std::vector<Numeric>& x, const std::vector<Numeric>& y, const std::string& format = "")
988 {
989  PyObject* kwargs = PyDict_New();
990  PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str()));
991 
992  PyObject* xarray = get_array(x);
993  PyObject* yarray = get_array(y);
994 
995  PyObject* pystring = PyString_FromString(format.c_str());
996 
997  PyObject* plot_args = PyTuple_New(3);
998  PyTuple_SetItem(plot_args, 0, xarray);
999  PyTuple_SetItem(plot_args, 1, yarray);
1000  PyTuple_SetItem(plot_args, 2, pystring);
1001 
1002  PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_plot, plot_args, kwargs);
1003 
1004  Py_DECREF(kwargs);
1005  Py_DECREF(plot_args);
1006  if (res) Py_DECREF(res);
1007 
1008  return res;
1009 }
1010 
1011 template<typename Numeric>
1012 bool named_semilogx(const std::string& name, const std::vector<Numeric>& x, const std::vector<Numeric>& y, const std::string& format = "")
1013 {
1014  PyObject* kwargs = PyDict_New();
1015  PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str()));
1016 
1017  PyObject* xarray = get_array(x);
1018  PyObject* yarray = get_array(y);
1019 
1020  PyObject* pystring = PyString_FromString(format.c_str());
1021 
1022  PyObject* plot_args = PyTuple_New(3);
1023  PyTuple_SetItem(plot_args, 0, xarray);
1024  PyTuple_SetItem(plot_args, 1, yarray);
1025  PyTuple_SetItem(plot_args, 2, pystring);
1026 
1027  PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_semilogx, plot_args, kwargs);
1028 
1029  Py_DECREF(kwargs);
1030  Py_DECREF(plot_args);
1031  if (res) Py_DECREF(res);
1032 
1033  return res;
1034 }
1035 
1036 template<typename Numeric>
1037 bool named_semilogy(const std::string& name, const std::vector<Numeric>& x, const std::vector<Numeric>& y, const std::string& format = "")
1038 {
1039  PyObject* kwargs = PyDict_New();
1040  PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str()));
1041 
1042  PyObject* xarray = get_array(x);
1043  PyObject* yarray = get_array(y);
1044 
1045  PyObject* pystring = PyString_FromString(format.c_str());
1046 
1047  PyObject* plot_args = PyTuple_New(3);
1048  PyTuple_SetItem(plot_args, 0, xarray);
1049  PyTuple_SetItem(plot_args, 1, yarray);
1050  PyTuple_SetItem(plot_args, 2, pystring);
1051 
1052  PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_semilogy, plot_args, kwargs);
1053 
1054  Py_DECREF(kwargs);
1055  Py_DECREF(plot_args);
1056  if (res) Py_DECREF(res);
1057 
1058  return res;
1059 }
1060 
1061 template<typename Numeric>
1062 bool named_loglog(const std::string& name, const std::vector<Numeric>& x, const std::vector<Numeric>& y, const std::string& format = "")
1063 {
1064  PyObject* kwargs = PyDict_New();
1065  PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str()));
1066 
1067  PyObject* xarray = get_array(x);
1068  PyObject* yarray = get_array(y);
1069 
1070  PyObject* pystring = PyString_FromString(format.c_str());
1071 
1072  PyObject* plot_args = PyTuple_New(3);
1073  PyTuple_SetItem(plot_args, 0, xarray);
1074  PyTuple_SetItem(plot_args, 1, yarray);
1075  PyTuple_SetItem(plot_args, 2, pystring);
1076 
1077  PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_loglog, plot_args, kwargs);
1078 
1079  Py_DECREF(kwargs);
1080  Py_DECREF(plot_args);
1081  if (res) Py_DECREF(res);
1082 
1083  return res;
1084 }
1085 
1086 template<typename Numeric>
1087 bool plot(const std::vector<Numeric>& y, const std::string& format = "")
1088 {
1089  std::vector<Numeric> x(y.size());
1090  for(size_t i=0; i<x.size(); ++i) x.at(i) = i;
1091  return plot(x,y,format);
1092 }
1093 
1094 template<typename Numeric>
1095 bool plot(const std::vector<Numeric>& y, const std::map<std::string, std::string>& keywords)
1096 {
1097  std::vector<Numeric> x(y.size());
1098  for(size_t i=0; i<x.size(); ++i) x.at(i) = i;
1099  return plot(x,y,keywords);
1100 }
1101 
1102 template<typename Numeric>
1103 bool stem(const std::vector<Numeric>& y, const std::string& format = "")
1104 {
1105  std::vector<Numeric> x(y.size());
1106  for (size_t i = 0; i < x.size(); ++i) x.at(i) = i;
1107  return stem(x, y, format);
1108 }
1109 
1110 template<typename Numeric>
1111 void text(Numeric x, Numeric y, const std::string& s = "")
1112 {
1113  PyObject* args = PyTuple_New(3);
1114  PyTuple_SetItem(args, 0, PyFloat_FromDouble(x));
1115  PyTuple_SetItem(args, 1, PyFloat_FromDouble(y));
1116  PyTuple_SetItem(args, 2, PyString_FromString(s.c_str()));
1117 
1118  PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_text, args);
1119  if(!res) throw std::runtime_error("Call to text() failed.");
1120 
1121  Py_DECREF(args);
1122  Py_DECREF(res);
1123 }
1124 
1125 
1126 inline long figure(long number = -1)
1127 {
1128  PyObject *res;
1129  if (number == -1)
1131  else {
1132  assert(number > 0);
1133 
1134  // Make sure interpreter is initialised
1136 
1137  PyObject *args = PyTuple_New(1);
1138  PyTuple_SetItem(args, 0, PyLong_FromLong(number));
1139  res = PyObject_CallObject(detail::_interpreter::get().s_python_function_figure, args);
1140  Py_DECREF(args);
1141  }
1142 
1143  if(!res) throw std::runtime_error("Call to figure() failed.");
1144 
1145  PyObject* num = PyObject_GetAttrString(res, "number");
1146  if (!num) throw std::runtime_error("Could not get number attribute of figure object");
1147  const long figureNumber = PyLong_AsLong(num);
1148 
1149  Py_DECREF(num);
1150  Py_DECREF(res);
1151 
1152  return figureNumber;
1153 }
1154 
1155 inline bool fignum_exists(long number)
1156 {
1157  // Make sure interpreter is initialised
1159 
1160  PyObject *args = PyTuple_New(1);
1161  PyTuple_SetItem(args, 0, PyLong_FromLong(number));
1162  PyObject *res = PyObject_CallObject(detail::_interpreter::get().s_python_function_fignum_exists, args);
1163  if(!res) throw std::runtime_error("Call to fignum_exists() failed.");
1164 
1165  bool ret = PyObject_IsTrue(res);
1166  Py_DECREF(res);
1167  Py_DECREF(args);
1168 
1169  return ret;
1170 }
1171 
1172 inline void figure_size(size_t w, size_t h)
1173 {
1174  // Make sure interpreter is initialised
1176 
1177  const size_t dpi = 100;
1178  PyObject* size = PyTuple_New(2);
1179  PyTuple_SetItem(size, 0, PyFloat_FromDouble((double)w / dpi));
1180  PyTuple_SetItem(size, 1, PyFloat_FromDouble((double)h / dpi));
1181 
1182  PyObject* kwargs = PyDict_New();
1183  PyDict_SetItemString(kwargs, "figsize", size);
1184  PyDict_SetItemString(kwargs, "dpi", PyLong_FromSize_t(dpi));
1185 
1186  PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_figure,
1188 
1189  Py_DECREF(kwargs);
1190 
1191  if(!res) throw std::runtime_error("Call to figure_size() failed.");
1192  Py_DECREF(res);
1193 }
1194 
1195 inline void legend()
1196 {
1198  if(!res) throw std::runtime_error("Call to legend() failed.");
1199 
1200  Py_DECREF(res);
1201 }
1202 
1203 template<typename Numeric>
1204 void ylim(Numeric left, Numeric right)
1205 {
1206  PyObject* list = PyList_New(2);
1207  PyList_SetItem(list, 0, PyFloat_FromDouble(left));
1208  PyList_SetItem(list, 1, PyFloat_FromDouble(right));
1209 
1210  PyObject* args = PyTuple_New(1);
1211  PyTuple_SetItem(args, 0, list);
1212 
1213  PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_ylim, args);
1214  if(!res) throw std::runtime_error("Call to ylim() failed.");
1215 
1216  Py_DECREF(args);
1217  Py_DECREF(res);
1218 }
1219 
1220 template<typename Numeric>
1221 void xlim(Numeric left, Numeric right)
1222 {
1223  PyObject* list = PyList_New(2);
1224  PyList_SetItem(list, 0, PyFloat_FromDouble(left));
1225  PyList_SetItem(list, 1, PyFloat_FromDouble(right));
1226 
1227  PyObject* args = PyTuple_New(1);
1228  PyTuple_SetItem(args, 0, list);
1229 
1230  PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_xlim, args);
1231  if(!res) throw std::runtime_error("Call to xlim() failed.");
1232 
1233  Py_DECREF(args);
1234  Py_DECREF(res);
1235 }
1236 
1237 
1238 inline double* xlim()
1239 {
1240  PyObject* args = PyTuple_New(0);
1241  PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_xlim, args);
1242  PyObject* left = PyTuple_GetItem(res,0);
1243  PyObject* right = PyTuple_GetItem(res,1);
1244 
1245  double* arr = new double[2];
1246  arr[0] = PyFloat_AsDouble(left);
1247  arr[1] = PyFloat_AsDouble(right);
1248 
1249  if(!res) throw std::runtime_error("Call to xlim() failed.");
1250 
1251  Py_DECREF(res);
1252  return arr;
1253 }
1254 
1255 
1256 inline double* ylim()
1257 {
1258  PyObject* args = PyTuple_New(0);
1259  PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_ylim, args);
1260  PyObject* left = PyTuple_GetItem(res,0);
1261  PyObject* right = PyTuple_GetItem(res,1);
1262 
1263  double* arr = new double[2];
1264  arr[0] = PyFloat_AsDouble(left);
1265  arr[1] = PyFloat_AsDouble(right);
1266 
1267  if(!res) throw std::runtime_error("Call to ylim() failed.");
1268 
1269  Py_DECREF(res);
1270  return arr;
1271 }
1272 
1273 template<typename Numeric>
1274 inline void xticks(const std::vector<Numeric> &ticks, const std::vector<std::string> &labels = {}, const std::map<std::string, std::string>& keywords = {})
1275 {
1276  assert(labels.size() == 0 || ticks.size() == labels.size());
1277 
1278  // using numpy array
1279  PyObject* ticksarray = get_array(ticks);
1280 
1281  PyObject* args;
1282  if(labels.size() == 0) {
1283  // construct positional args
1284  args = PyTuple_New(1);
1285  PyTuple_SetItem(args, 0, ticksarray);
1286  } else {
1287  // make tuple of tick labels
1288  PyObject* labelstuple = PyTuple_New(labels.size());
1289  for (size_t i = 0; i < labels.size(); i++)
1290  PyTuple_SetItem(labelstuple, i, PyUnicode_FromString(labels[i].c_str()));
1291 
1292  // construct positional args
1293  args = PyTuple_New(2);
1294  PyTuple_SetItem(args, 0, ticksarray);
1295  PyTuple_SetItem(args, 1, labelstuple);
1296  }
1297 
1298  // construct keyword args
1299  PyObject* kwargs = PyDict_New();
1300  for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
1301  {
1302  PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
1303  }
1304 
1305  PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_xticks, args, kwargs);
1306 
1307  Py_DECREF(args);
1308  Py_DECREF(kwargs);
1309  if(!res) throw std::runtime_error("Call to xticks() failed");
1310 
1311  Py_DECREF(res);
1312 }
1313 
1314 template<typename Numeric>
1315 inline void xticks(const std::vector<Numeric> &ticks, const std::map<std::string, std::string>& keywords)
1316 {
1317  xticks(ticks, {}, keywords);
1318 }
1319 
1320 template<typename Numeric>
1321 inline void yticks(const std::vector<Numeric> &ticks, const std::vector<std::string> &labels = {}, const std::map<std::string, std::string>& keywords = {})
1322 {
1323  assert(labels.size() == 0 || ticks.size() == labels.size());
1324 
1325  // using numpy array
1326  PyObject* ticksarray = get_array(ticks);
1327 
1328  PyObject* args;
1329  if(labels.size() == 0) {
1330  // construct positional args
1331  args = PyTuple_New(1);
1332  PyTuple_SetItem(args, 0, ticksarray);
1333  } else {
1334  // make tuple of tick labels
1335  PyObject* labelstuple = PyTuple_New(labels.size());
1336  for (size_t i = 0; i < labels.size(); i++)
1337  PyTuple_SetItem(labelstuple, i, PyUnicode_FromString(labels[i].c_str()));
1338 
1339  // construct positional args
1340  args = PyTuple_New(2);
1341  PyTuple_SetItem(args, 0, ticksarray);
1342  PyTuple_SetItem(args, 1, labelstuple);
1343  }
1344 
1345  // construct keyword args
1346  PyObject* kwargs = PyDict_New();
1347  for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
1348  {
1349  PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str()));
1350  }
1351 
1352  PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_yticks, args, kwargs);
1353 
1354  Py_DECREF(args);
1355  Py_DECREF(kwargs);
1356  if(!res) throw std::runtime_error("Call to yticks() failed");
1357 
1358  Py_DECREF(res);
1359 }
1360 
1361 template<typename Numeric>
1362 inline void yticks(const std::vector<Numeric> &ticks, const std::map<std::string, std::string>& keywords)
1363 {
1364  yticks(ticks, {}, keywords);
1365 }
1366 
1367 inline void subplot(long nrows, long ncols, long plot_number)
1368 {
1369  // construct positional args
1370  PyObject* args = PyTuple_New(3);
1371  PyTuple_SetItem(args, 0, PyFloat_FromDouble(nrows));
1372  PyTuple_SetItem(args, 1, PyFloat_FromDouble(ncols));
1373  PyTuple_SetItem(args, 2, PyFloat_FromDouble(plot_number));
1374 
1375  PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_subplot, args);
1376  if(!res) throw std::runtime_error("Call to subplot() failed.");
1377 
1378  Py_DECREF(args);
1379  Py_DECREF(res);
1380 }
1381 
1382 inline void title(const std::string &titlestr, const std::map<std::string, std::string> &keywords = {})
1383 {
1384  PyObject* pytitlestr = PyString_FromString(titlestr.c_str());
1385  PyObject* args = PyTuple_New(1);
1386  PyTuple_SetItem(args, 0, pytitlestr);
1387 
1388  PyObject* kwargs = PyDict_New();
1389  for (auto it = keywords.begin(); it != keywords.end(); ++it) {
1390  PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
1391  }
1392 
1393  PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_title, args, kwargs);
1394  if(!res) throw std::runtime_error("Call to title() failed.");
1395 
1396  Py_DECREF(args);
1397  Py_DECREF(kwargs);
1398  Py_DECREF(res);
1399 }
1400 
1401 inline void suptitle(const std::string &suptitlestr, const std::map<std::string, std::string> &keywords = {})
1402 {
1403  PyObject* pysuptitlestr = PyString_FromString(suptitlestr.c_str());
1404  PyObject* args = PyTuple_New(1);
1405  PyTuple_SetItem(args, 0, pysuptitlestr);
1406 
1407  PyObject* kwargs = PyDict_New();
1408  for (auto it = keywords.begin(); it != keywords.end(); ++it) {
1409  PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
1410  }
1411 
1412  PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_suptitle, args, kwargs);
1413  if(!res) throw std::runtime_error("Call to suptitle() failed.");
1414 
1415  Py_DECREF(args);
1416  Py_DECREF(kwargs);
1417  Py_DECREF(res);
1418 }
1419 
1420 inline void axis(const std::string &axisstr)
1421 {
1422  PyObject* str = PyString_FromString(axisstr.c_str());
1423  PyObject* args = PyTuple_New(1);
1424  PyTuple_SetItem(args, 0, str);
1425 
1426  PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_axis, args);
1427  if(!res) throw std::runtime_error("Call to title() failed.");
1428 
1429  Py_DECREF(args);
1430  Py_DECREF(res);
1431 }
1432 
1433 inline void xlabel(const std::string &str, const std::map<std::string, std::string> &keywords = {})
1434 {
1435  PyObject* pystr = PyString_FromString(str.c_str());
1436  PyObject* args = PyTuple_New(1);
1437  PyTuple_SetItem(args, 0, pystr);
1438 
1439  PyObject* kwargs = PyDict_New();
1440  for (auto it = keywords.begin(); it != keywords.end(); ++it) {
1441  PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
1442  }
1443 
1444  PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_xlabel, args, kwargs);
1445  if(!res) throw std::runtime_error("Call to xlabel() failed.");
1446 
1447  Py_DECREF(args);
1448  Py_DECREF(kwargs);
1449  Py_DECREF(res);
1450 }
1451 
1452 inline void ylabel(const std::string &str, const std::map<std::string, std::string>& keywords = {})
1453 {
1454  PyObject* pystr = PyString_FromString(str.c_str());
1455  PyObject* args = PyTuple_New(1);
1456  PyTuple_SetItem(args, 0, pystr);
1457 
1458  PyObject* kwargs = PyDict_New();
1459  for (auto it = keywords.begin(); it != keywords.end(); ++it) {
1460  PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
1461  }
1462 
1463  PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_ylabel, args, kwargs);
1464  if(!res) throw std::runtime_error("Call to ylabel() failed.");
1465 
1466  Py_DECREF(args);
1467  Py_DECREF(kwargs);
1468  Py_DECREF(res);
1469 }
1470 
1471 inline void grid(bool flag)
1472 {
1473  PyObject* pyflag = flag ? Py_True : Py_False;
1474  Py_INCREF(pyflag);
1475 
1476  PyObject* args = PyTuple_New(1);
1477  PyTuple_SetItem(args, 0, pyflag);
1478 
1479  PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_grid, args);
1480  if(!res) throw std::runtime_error("Call to grid() failed.");
1481 
1482  Py_DECREF(args);
1483  Py_DECREF(res);
1484 }
1485 
1486 inline void show(const bool block = true)
1487 {
1488  PyObject* res;
1489  if(block)
1490  {
1491  res = PyObject_CallObject(
1494  }
1495  else
1496  {
1497  PyObject *kwargs = PyDict_New();
1498  PyDict_SetItemString(kwargs, "block", Py_False);
1500  Py_DECREF(kwargs);
1501  }
1502 
1503 
1504  if (!res) throw std::runtime_error("Call to show() failed.");
1505 
1506  Py_DECREF(res);
1507 }
1508 
1509 inline void close()
1510 {
1511  PyObject* res = PyObject_CallObject(
1514 
1515  if (!res) throw std::runtime_error("Call to close() failed.");
1516 
1517  Py_DECREF(res);
1518 }
1519 
1520 inline void xkcd() {
1521  PyObject* res;
1522  PyObject *kwargs = PyDict_New();
1523 
1524  res = PyObject_Call(detail::_interpreter::get().s_python_function_xkcd,
1526 
1527  Py_DECREF(kwargs);
1528 
1529  if (!res)
1530  throw std::runtime_error("Call to show() failed.");
1531 
1532  Py_DECREF(res);
1533 }
1534 
1535 inline void draw()
1536 {
1537  PyObject* res = PyObject_CallObject(
1540 
1541  if (!res) throw std::runtime_error("Call to draw() failed.");
1542 
1543  Py_DECREF(res);
1544 }
1545 
1546 template<typename Numeric>
1547 inline void pause(Numeric interval)
1548 {
1549  PyObject* args = PyTuple_New(1);
1550  PyTuple_SetItem(args, 0, PyFloat_FromDouble(interval));
1551 
1552  PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_pause, args);
1553  if(!res) throw std::runtime_error("Call to pause() failed.");
1554 
1555  Py_DECREF(args);
1556  Py_DECREF(res);
1557 }
1558 
1559 inline void save(const std::string& filename)
1560 {
1561  PyObject* pyfilename = PyString_FromString(filename.c_str());
1562 
1563  PyObject* args = PyTuple_New(1);
1564  PyTuple_SetItem(args, 0, pyfilename);
1565 
1566  PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_save, args);
1567  if (!res) throw std::runtime_error("Call to save() failed.");
1568 
1569  Py_DECREF(args);
1570  Py_DECREF(res);
1571 }
1572 
1573 inline void clf() {
1574  PyObject *res = PyObject_CallObject(
1577 
1578  if (!res) throw std::runtime_error("Call to clf() failed.");
1579 
1580  Py_DECREF(res);
1581 }
1582 
1583  inline void ion() {
1584  PyObject *res = PyObject_CallObject(
1587 
1588  if (!res) throw std::runtime_error("Call to ion() failed.");
1589 
1590  Py_DECREF(res);
1591 }
1592 
1593 inline std::vector<std::array<double, 2>> ginput(const int numClicks = 1, const std::map<std::string, std::string>& keywords = {})
1594 {
1595  PyObject *args = PyTuple_New(1);
1596  PyTuple_SetItem(args, 0, PyLong_FromLong(numClicks));
1597 
1598  // construct keyword args
1599  PyObject* kwargs = PyDict_New();
1600  for(std::map<std::string, std::string>::const_iterator it = keywords.begin(); it != keywords.end(); ++it)
1601  {
1602  PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str()));
1603  }
1604 
1605  PyObject* res = PyObject_Call(
1607 
1608  Py_DECREF(kwargs);
1609  Py_DECREF(args);
1610  if (!res) throw std::runtime_error("Call to ginput() failed.");
1611 
1612  const size_t len = PyList_Size(res);
1613  std::vector<std::array<double, 2>> out;
1614  out.reserve(len);
1615  for (size_t i = 0; i < len; i++) {
1616  PyObject *current = PyList_GetItem(res, i);
1617  std::array<double, 2> position;
1618  position[0] = PyFloat_AsDouble(PyTuple_GetItem(current, 0));
1619  position[1] = PyFloat_AsDouble(PyTuple_GetItem(current, 1));
1620  out.push_back(position);
1621  }
1622  Py_DECREF(res);
1623 
1624  return out;
1625 }
1626 
1627 // Actually, is there any reason not to call this automatically for every plot?
1628 inline void tight_layout() {
1629  PyObject *res = PyObject_CallObject(
1632 
1633  if (!res) throw std::runtime_error("Call to tight_layout() failed.");
1634 
1635  Py_DECREF(res);
1636 }
1637 
1638 // Support for variadic plot() and initializer lists:
1639 
1640 namespace detail {
1641 
1642 template<typename T>
1643 using is_function = typename std::is_function<std::remove_pointer<std::remove_reference<T>>>::type;
1644 
1645 template<bool obj, typename T>
1647 
1648 template<typename T>
1649 struct is_callable_impl<false, T>
1650 {
1652 }; // a non-object is callable iff it is a function
1653 
1654 template<typename T>
1655 struct is_callable_impl<true, T>
1656 {
1657  struct Fallback { void operator()(); };
1658  struct Derived : T, Fallback { };
1659 
1660  template<typename U, U> struct Check;
1661 
1662  template<typename U>
1663  static std::true_type test( ... ); // use a variadic function to make sure (1) it accepts everything and (2) its always the worst match
1664 
1665  template<typename U>
1666  static std::false_type test( Check<void(Fallback::*)(), &U::operator()>* );
1667 
1668 public:
1669  typedef decltype(test<Derived>(nullptr)) type;
1670  typedef decltype(&Fallback::operator()) dtype;
1671  static constexpr bool value = type::value;
1672 }; // an object is callable iff it defines operator()
1673 
1674 template<typename T>
1676 {
1677  // dispatch to is_callable_impl<true, T> or is_callable_impl<false, T> depending on whether T is of class type or not
1679 };
1680 
1681 template<typename IsYDataCallable>
1682 struct plot_impl { };
1683 
1684 template<>
1685 struct plot_impl<std::false_type>
1686 {
1687  template<typename IterableX, typename IterableY>
1688  bool operator()(const IterableX& x, const IterableY& y, const std::string& format)
1689  {
1690  // 2-phase lookup for distance, begin, end
1691  using std::distance;
1692  using std::begin;
1693  using std::end;
1694 
1695  auto xs = distance(begin(x), end(x));
1696  auto ys = distance(begin(y), end(y));
1697  assert(xs == ys && "x and y data must have the same number of elements!");
1698 
1699  PyObject* xlist = PyList_New(xs);
1700  PyObject* ylist = PyList_New(ys);
1701  PyObject* pystring = PyString_FromString(format.c_str());
1702 
1703  auto itx = begin(x), ity = begin(y);
1704  for(size_t i = 0; i < xs; ++i) {
1705  PyList_SetItem(xlist, i, PyFloat_FromDouble(*itx++));
1706  PyList_SetItem(ylist, i, PyFloat_FromDouble(*ity++));
1707  }
1708 
1709  PyObject* plot_args = PyTuple_New(3);
1710  PyTuple_SetItem(plot_args, 0, xlist);
1711  PyTuple_SetItem(plot_args, 1, ylist);
1712  PyTuple_SetItem(plot_args, 2, pystring);
1713 
1714  PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_plot, plot_args);
1715 
1716  Py_DECREF(plot_args);
1717  if(res) Py_DECREF(res);
1718 
1719  return res;
1720  }
1721 };
1722 
1723 template<>
1724 struct plot_impl<std::true_type>
1725 {
1726  template<typename Iterable, typename Callable>
1727  bool operator()(const Iterable& ticks, const Callable& f, const std::string& format)
1728  {
1729  if(begin(ticks) == end(ticks)) return true;
1730 
1731  // We could use additional meta-programming to deduce the correct element type of y,
1732  // but all values have to be convertible to double anyways
1733  std::vector<double> y;
1734  for(auto x : ticks) y.push_back(f(x));
1735  return plot_impl<std::false_type>()(ticks,y,format);
1736  }
1737 };
1738 
1739 } // end namespace detail
1740 
1741 // recursion stop for the above
1742 template<typename... Args>
1743 bool plot() { return true; }
1744 
1745 template<typename A, typename B, typename... Args>
1746 bool plot(const A& a, const B& b, const std::string& format, Args... args)
1747 {
1748  return detail::plot_impl<typename detail::is_callable<B>::type>()(a,b,format) && plot(args...);
1749 }
1750 
1751 /*
1752  * This group of plot() functions is needed to support initializer lists, i.e. calling
1753  * plot( {1,2,3,4} )
1754  */
1755 inline bool plot(const std::vector<double>& x, const std::vector<double>& y, const std::string& format = "") {
1756  return plot<double,double>(x,y,format);
1757 }
1758 
1759 inline bool plot(const std::vector<double>& y, const std::string& format = "") {
1760  return plot<double>(y,format);
1761 }
1762 
1763 inline bool plot(const std::vector<double>& x, const std::vector<double>& y, const std::map<std::string, std::string>& keywords) {
1764  return plot<double>(x,y,keywords);
1765 }
1766 
1767 /*
1768  * This class allows dynamic plots, ie changing the plotted data without clearing and re-plotting
1769  */
1770 
1771 class Plot
1772 {
1773 public:
1774  // default initialization with plot label, some data and format
1775  template<typename Numeric>
1776  Plot(const std::string& name, const std::vector<Numeric>& x, const std::vector<Numeric>& y, const std::string& format = "") {
1777 
1778  assert(x.size() == y.size());
1779 
1780  PyObject* kwargs = PyDict_New();
1781  if(name != "")
1782  PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str()));
1783 
1784  PyObject* xarray = get_array(x);
1785  PyObject* yarray = get_array(y);
1786 
1787  PyObject* pystring = PyString_FromString(format.c_str());
1788 
1789  PyObject* plot_args = PyTuple_New(3);
1790  PyTuple_SetItem(plot_args, 0, xarray);
1791  PyTuple_SetItem(plot_args, 1, yarray);
1792  PyTuple_SetItem(plot_args, 2, pystring);
1793 
1794  PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_plot, plot_args, kwargs);
1795 
1796  Py_DECREF(kwargs);
1797  Py_DECREF(plot_args);
1798 
1799  if(res)
1800  {
1801  line= PyList_GetItem(res, 0);
1802 
1803  if(line)
1804  set_data_fct = PyObject_GetAttrString(line,"set_data");
1805  else
1806  Py_DECREF(line);
1807  Py_DECREF(res);
1808  }
1809  }
1810 
1811  // shorter initialization with name or format only
1812  // basically calls line, = plot([], [])
1813  Plot(const std::string& name = "", const std::string& format = "")
1814  : Plot(name, std::vector<double>(), std::vector<double>(), format) {}
1815 
1816  template<typename Numeric>
1817  bool update(const std::vector<Numeric>& x, const std::vector<Numeric>& y) {
1818  assert(x.size() == y.size());
1819  if(set_data_fct)
1820  {
1821  PyObject* xarray = get_array(x);
1822  PyObject* yarray = get_array(y);
1823 
1824  PyObject* plot_args = PyTuple_New(2);
1825  PyTuple_SetItem(plot_args, 0, xarray);
1826  PyTuple_SetItem(plot_args, 1, yarray);
1827 
1828  PyObject* res = PyObject_CallObject(set_data_fct, plot_args);
1829  if (res) Py_DECREF(res);
1830  return res;
1831  }
1832  return false;
1833  }
1834 
1835  // clears the plot but keep it available
1836  bool clear() {
1837  return update(std::vector<double>(), std::vector<double>());
1838  }
1839 
1840  // definitely remove this line
1841  void remove() {
1842  if(line)
1843  {
1844  auto remove_fct = PyObject_GetAttrString(line,"remove");
1845  PyObject* args = PyTuple_New(0);
1846  PyObject* res = PyObject_CallObject(remove_fct, args);
1847  if (res) Py_DECREF(res);
1848  }
1849  decref();
1850  }
1851 
1852  ~Plot() {
1853  decref();
1854  }
1855 private:
1856 
1857  void decref() {
1858  if(line)
1859  Py_DECREF(line);
1860  if(set_data_fct)
1861  Py_DECREF(set_data_fct);
1862  }
1863 
1864 
1865  PyObject* line = nullptr;
1866  PyObject* set_data_fct = nullptr;
1867 };
1868 
1869 } // end namespace matplotlibcpp
bool named_plot(const std::string &name, const std::vector< Numeric > &y, const std::string &format="")
Definition: matplotlibcpp.h:963
PyObject * s_python_function_text
Definition: matplotlibcpp.h:84
PyObject * s_python_function_clf
Definition: matplotlibcpp.h:76
PyObject * s_python_colormap
Definition: matplotlibcpp.h:80
void ylim(Numeric left, Numeric right)
Definition: matplotlibcpp.h:1204
void xticks(const std::vector< Numeric > &ticks, const std::vector< std::string > &labels={}, const std::map< std::string, std::string > &keywords={})
Definition: matplotlibcpp.h:1274
Plot(const std::string &name="", const std::string &format="")
Definition: matplotlibcpp.h:1813
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 >())
Definition: matplotlibcpp.h:366
PyObject * s_python_function_show
Definition: matplotlibcpp.h:46
PyObject * s_python_function_ylim
Definition: matplotlibcpp.h:68
bool fignum_exists(long number)
Definition: matplotlibcpp.h:1155
void grid(bool flag)
Definition: matplotlibcpp.h:1471
void xkcd()
Definition: matplotlibcpp.h:1520
PyObject * s_python_function_xlabel
Definition: matplotlibcpp.h:71
void yticks(const std::vector< Numeric > &ticks, const std::vector< std::string > &labels={}, const std::map< std::string, std::string > &keywords={})
Definition: matplotlibcpp.h:1321
PyObject * s_python_function_grid
Definition: matplotlibcpp.h:75
PyObject * s_python_function_fignum_exists
Definition: matplotlibcpp.h:52
~_interpreter()
Definition: matplotlibcpp.h:226
PyObject * s_python_function_subplot
Definition: matplotlibcpp.h:63
PyObject * s_python_function_xlim
Definition: matplotlibcpp.h:65
Definition: matplotlibcpp.h:1675
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:753
PyObject * s_python_function_title
Definition: matplotlibcpp.h:69
PyObject * s_python_function_tight_layout
Definition: matplotlibcpp.h:79
bool stem(const std::vector< Numeric > &x, const std::vector< Numeric > &y, const std::map< std::string, std::string > &keywords)
Definition: matplotlibcpp.h:458
typename std::is_function< std::remove_pointer< std::remove_reference< T > >>::type is_function
Definition: matplotlibcpp.h:1643
void close()
Definition: matplotlibcpp.h:1509
PyObject * s_python_function_ginput
Definition: matplotlibcpp.h:67
PyObject * s_python_function_stem
Definition: matplotlibcpp.h:82
bool clear()
Definition: matplotlibcpp.h:1836
bool hist(const std::vector< Numeric > &y, long bins=10, std::string color="b", double alpha=1.0, bool cumulative=false)
Definition: matplotlibcpp.h:553
void figure_size(size_t w, size_t h)
Definition: matplotlibcpp.h:1172
is_callable_impl< std::is_class< T >::value, T >::type type
Definition: matplotlibcpp.h:1678
bool plot(const std::vector< Numeric > &x, const std::vector< Numeric > &y, const std::map< std::string, std::string > &keywords)
Definition: matplotlibcpp.h:336
bool semilogx(const std::vector< NumericX > &x, const std::vector< NumericY > &y, const std::string &s="")
Definition: matplotlibcpp.h:859
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:800
bool semilogy(const std::vector< NumericX > &x, const std::vector< NumericY > &y, const std::string &s="")
Definition: matplotlibcpp.h:882
PyObject * s_python_function_annotate
Definition: matplotlibcpp.h:78
void backend(const std::string &name)
Definition: matplotlibcpp.h:234
PyObject * s_python_function_errorbar
Definition: matplotlibcpp.h:77
PyObject * s_python_function_ion
Definition: matplotlibcpp.h:66
_interpreter()
Definition: matplotlibcpp.h:132
PyObject * s_python_function_close
Definition: matplotlibcpp.h:47
PyObject * s_python_function_bar
Definition: matplotlibcpp.h:86
void legend()
Definition: matplotlibcpp.h:1195
Definition: matplotlibcpp.h:265
PyObject * safe_import(PyObject *module, std::string fname)
Definition: matplotlibcpp.h:101
bool fill(const std::vector< Numeric > &x, const std::vector< Numeric > &y, const std::map< std::string, std::string > &keywords)
Definition: matplotlibcpp.h:491
Definition: matplotlibcpp.h:1682
static _interpreter & get()
Definition: matplotlibcpp.h:96
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:928
long figure(long number=-1)
Definition: matplotlibcpp.h:1126
void show(const bool block=true)
Definition: matplotlibcpp.h:1486
PyObject * s_python_function_pause
Definition: matplotlibcpp.h:49
bool operator()(const IterableX &x, const IterableY &y, const std::string &format)
Definition: matplotlibcpp.h:1688
bool update(const std::vector< Numeric > &x, const std::vector< Numeric > &y)
Definition: matplotlibcpp.h:1817
bool named_semilogy(const std::string &name, const std::vector< Numeric > &x, const std::vector< Numeric > &y, const std::string &format="")
Definition: matplotlibcpp.h:1037
PyObject * s_python_function_plot
Definition: matplotlibcpp.h:53
std::vector< std::array< double, 2 > > ginput(const int numClicks=1, const std::map< std::string, std::string > &keywords={})
Definition: matplotlibcpp.h:1593
PyObject * s_python_function_yticks
Definition: matplotlibcpp.h:74
PyObject * s_python_function_fill_between
Definition: matplotlibcpp.h:59
PyObject * s_python_function_fill
Definition: matplotlibcpp.h:58
PyObject * s_python_function_save
Definition: matplotlibcpp.h:50
PyObject * s_python_function_figure
Definition: matplotlibcpp.h:51
Definition: matplotlibcpp.h:40
PyObject * s_python_function_subplots_adjust
Definition: matplotlibcpp.h:87
bool subplots_adjust(const std::map< std::string, double > &keywords={})
Definition: matplotlibcpp.h:730
Definition: matplotlibcpp.h:45
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:679
PyObject * s_python_function_legend
Definition: matplotlibcpp.h:64
PyObject * s_python_function_axis
Definition: matplotlibcpp.h:70
bool named_semilogx(const std::string &name, const std::vector< Numeric > &x, const std::vector< Numeric > &y, const std::string &format="")
Definition: matplotlibcpp.h:1012
Definition: matplotlibcpp.h:1771
PyObject * s_python_function_imshow
Definition: matplotlibcpp.h:61
bool annotate(std::string annotation, double x, double y)
Definition: matplotlibcpp.h:239
void suptitle(const std::string &suptitlestr, const std::map< std::string, std::string > &keywords={})
Definition: matplotlibcpp.h:1401
PyObject * s_python_function_quiver
Definition: matplotlibcpp.h:54
PyObject * s_python_function_semilogx
Definition: matplotlibcpp.h:55
void pause(Numeric interval)
Definition: matplotlibcpp.h:1547
void xlim(Numeric left, Numeric right)
Definition: matplotlibcpp.h:1221
PyObject * s_python_function_semilogy
Definition: matplotlibcpp.h:56
void text(Numeric x, Numeric y, const std::string &s="")
Definition: matplotlibcpp.h:1111
void import_numpy()
Definition: matplotlibcpp.h:125
PyObject * s_python_function_xticks
Definition: matplotlibcpp.h:73
PyObject * s_python_function_loglog
Definition: matplotlibcpp.h:57
void clf()
Definition: matplotlibcpp.h:1573
PyObject * s_python_function_xkcd
Definition: matplotlibcpp.h:83
void decref()
Definition: matplotlibcpp.h:1857
void xlabel(const std::string &str, const std::map< std::string, std::string > &keywords={})
Definition: matplotlibcpp.h:1433
PyObject * s_python_function_hist
Definition: matplotlibcpp.h:60
bool named_loglog(const std::string &name, const std::vector< Numeric > &x, const std::vector< Numeric > &y, const std::string &format="")
Definition: matplotlibcpp.h:1062
PyObject * s_python_function_draw
Definition: matplotlibcpp.h:48
PyObject * s_python_function_ylabel
Definition: matplotlibcpp.h:72
void ion()
Definition: matplotlibcpp.h:1583
bool operator()(const Iterable &ticks, const Callable &f, const std::string &format)
Definition: matplotlibcpp.h:1727
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)
Definition: matplotlibcpp.h:582
void subplot(long nrows, long ncols, long plot_number)
Definition: matplotlibcpp.h:1367
void title(const std::string &titlestr, const std::map< std::string, std::string > &keywords={})
Definition: matplotlibcpp.h:1382
void save(const std::string &filename)
Definition: matplotlibcpp.h:1559
void ylabel(const std::string &str, const std::map< std::string, std::string > &keywords={})
Definition: matplotlibcpp.h:1452
void axis(const std::string &axisstr)
Definition: matplotlibcpp.h:1420
bool loglog(const std::vector< NumericX > &x, const std::vector< NumericY > &y, const std::string &s="")
Definition: matplotlibcpp.h:905
void imshow(const unsigned char *ptr, const int rows, const int columns, const int colors, const std::map< std::string, std::string > &keywords={})
Definition: matplotlibcpp.h:610
PyObject * s_python_function_suptitle
Definition: matplotlibcpp.h:85
void draw()
Definition: matplotlibcpp.h:1535
Plot(const std::string &name, const std::vector< Numeric > &x, const std::vector< Numeric > &y, const std::string &format="")
Definition: matplotlibcpp.h:1776
void tight_layout()
Definition: matplotlibcpp.h:1628
~Plot()
Definition: matplotlibcpp.h:1852
is_function< T > type
Definition: matplotlibcpp.h:1651
PyObject * get_array(const std::vector< Numeric > &v)
Definition: matplotlibcpp.h:279
PyObject * get_2darray(const std::vector<::std::vector< Numeric >> &v)
Definition: matplotlibcpp.h:298
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:521
bool scatter(const std::vector< NumericX > &x, const std::vector< NumericY > &y, const double s=1.0)
Definition: matplotlibcpp.h:653
Definition: matplotlibcpp.h:1646
PyObject * s_python_function_scatter
Definition: matplotlibcpp.h:62
PyObject * s_python_empty_tuple
Definition: matplotlibcpp.h:81