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