Nsound  0.9.4
Plotter.cc
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 //
3 // $Id: Plotter.cc 874 2014-09-08 02:21:29Z weegreenblobbie $
4 //
5 // Copyright (c) 2005-2006 Nick Hilton
6 //
7 // weegreenblobbie_yahoo_com (replace '_' with '@' and '.')
8 //
9 //-----------------------------------------------------------------------------
10 
11 //-----------------------------------------------------------------------------
12 //
13 // This program is free software; you can redistribute it and/or modify
14 // it under the terms of the GNU General Public License as published by
15 // the Free Software Foundation; either version 2 of the License, or
16 // (at your option) any later version.
17 //
18 // This program is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 // GNU Library General Public License for more details.
22 //
23 // You should have received a copy of the GNU General Public License
24 // along with this program; if not, write to the Free Software
25 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 //
27 //-----------------------------------------------------------------------------
28 
29 #include <Nsound/AudioStream.h>
30 #include <Nsound/Buffer.h>
31 #include <Nsound/FFTChunk.h>
32 #include <Nsound/FFTransform.h>
33 #include <Nsound/Generator.h>
34 #include <Nsound/Plotter.h>
35 
36 //#include <numpy/arrayobject.h>
37 
38 #include <iostream>
39 #include <sstream>
40 
41 using namespace Nsound;
42 
43 using std::cout;
44 using std::cerr;
45 
47 
48 #define PRINT_LINE __FILE__ << ":" << __LINE__ << ": "
49 
50 #define MIN(a,b) ((a) < (b) ? (a) : (b))
51 #define MAX(a,b) ((a) > (b) ? (a) : (b))
52 
54 boolean Plotter::hold_is_on_ = false;
55 boolean Plotter::grid_is_on_ = true;
56 
57 float64 Plotter::xmin_ = 1e300;
58 float64 Plotter::xmax_ = -1e300;
59 float64 Plotter::ymin_ = 1e300;
60 float64 Plotter::ymax_ = -1e300;
61 
63 
64 // Statically allocate one plotter object so show() works propperly.
66 
67 #ifndef NSOUND_PLATFORM_OS_WINDOWS
68  #pragma GCC diagnostic ignored "-Wold-style-cast"
69 #endif
70 
71 //-----------------------------------------------------------------------------
72 Axes::
73 Axes(PyObject * axes_ptr)
74  : axes_ptr_(axes_ptr)
75 {
76 }
77 
78 Axes::
79 Axes(const Axes & rhs)
80  : axes_ptr_(rhs.axes_ptr_)
81 {
82 }
83 
84 Axes::
86 {
87 }
88 
89 Axes &
90 Axes::
91 operator=(const Axes & rhs)
92 {
93  axes_ptr_ = rhs.axes_ptr_;
94  return *this;
95 }
96 
97 #define M_CHECK_PY_PTR_RETURN( a, msg ) \
98  if( PyErr_Occurred() || (a) == NULL) \
99  { \
100  PyErr_Print(); \
101  M_THROW( msg ); \
102  return; \
103  }
104 
105 #define M_CHECK_PY_PTR( a, msg ) \
106  if( PyErr_Occurred() || (a) == NULL) \
107  { \
108  PyErr_Print(); \
109  M_THROW( msg ); \
110  }
111 
112 //-----------------------------------------------------------------------------
113 Plotter::
115 {
116  #ifdef NSOUND_C_PYLAB
117 
118  ++count_;
119 
120  if(Plotter::state_ != BOOTING)
121  {
122  return;
123  }
124 
125  #ifndef NSOUND_IN_PYTHON_MODULE
126 
127  Py_Initialize();
128 
129  // Initialize/import the Numeric::arrayobject module
130 // import_array();
131 
132  if(PyErr_Occurred())
133  {
134  PyErr_Print();
135  M_THROW("Py_Initialize() failed");
136  return;
137  }
138 
139  #endif
140 
141  //---------------------------------------------------------------------
142  // importing modules
143 
144  PyObject * matplotlib = PyImport_ImportModule("matplotlib");
145 
146  M_CHECK_PY_PTR_RETURN( matplotlib, "import matplotlib failed." );
147 
148  PyObject * pylab = PyImport_ImportModule("matplotlib.pylab");
149 
150  M_CHECK_PY_PTR_RETURN( pylab, "import matplotlib.pylab failed." );
151 
152  Py_DECREF(matplotlib);
153 
154  //---------------------------------------------------------------------
155  // Grabbing pylab's funciton dictionary
156 
157  PyObject * pylab_dict = PyModule_GetDict(pylab);
158 
159  M_CHECK_PY_PTR_RETURN( pylab_dict, "dir(pylab) failed" );
160 
161  table_.insert(StringPyObjectPair("pylab", pylab_dict));
162 
163  Py_DECREF(pylab);
164 
165  std::vector< std::string > functions;
166 
167  functions.push_back("axhline");
168  functions.push_back("axis");
169  functions.push_back("axvline");
170  functions.push_back("close");
171  functions.push_back("detrend");
172  functions.push_back("figure");
173  functions.push_back("gca");
174  functions.push_back("hold");
175  functions.push_back("imshow");
176  functions.push_back("legend");
177  functions.push_back("plot");
178  functions.push_back("show");
179  functions.push_back("subplot");
180  functions.push_back("text");
181  functions.push_back("title");
182  functions.push_back("window_hanning");
183  functions.push_back("xlabel");
184  functions.push_back("xlim");
185  functions.push_back("ylabel");
186  functions.push_back("ylim");
187 
188  const uint32 N_FUNCTIONS = static_cast<uint32>(functions.size());
189 
190  for(uint32 i = 0; i < N_FUNCTIONS; ++i)
191  {
192  PyObject * func = PyDict_GetItemString(
193  pylab_dict, functions[i].c_str());
194 
196  func, "PyDict_GetItemString('" << functions[i] << "') failed");
197 
198  if(! PyCallable_Check(func))
199  {
200  M_THROW("pylab." << functions[i] << " isn't callable?!");
201  }
202 
203  table_.insert(
204  StringPyObjectPair("pylab." + functions[i], func));
205  }
206 
207  // Globals
208 
209  PyObject * __main__ = PyImport_ImportModule("__main__");
210 
211  M_CHECK_PY_PTR_RETURN(__main__, "PyImport_ImportModule() failed");
212 
213  PyObject * globals = PyModule_GetDict(__main__);
214 
215  M_CHECK_PY_PTR_RETURN(globals, "globals() failed");
216 
217  table_.insert(StringPyObjectPair("globals", globals));
218 
219  Py_DECREF(__main__);
220 
221  run_string("import matplotlib.pylab as _pylab_nsound_");
222 
224 
225  #endif
226 }
227 
228 //-----------------------------------------------------------------------------
229 Plotter::
231 {
232  #ifdef NSOUND_C_PYLAB
233 
234  --count_;
235 
236  if(count_ == 0)
237  {
238  #ifndef NSOUND_IN_PYTHON_MODULE
239 
240  Py_Finalize();
241 
242  #endif
243 
245  }
246 
247  #endif
248 }
249 
250 void
251 Plotter::
253 {
254  #ifdef NSOUND_C_PYLAB
255 
257  {
258  return;
259  }
260 
261  // Call pylab.show()
262 
263  PyObject * ret = PyObject_CallObject(table_["pylab.show"], NULL);
264 
265  M_CHECK_PY_PTR_RETURN(ret, "pylab.show() failed");
266 
267  Py_DECREF(ret);
268 
269  #else
270  // This function is overwridden in the Python module,
271  // See the file shadowed.i for how this is implemented in Python module
272 
273  #ifndef NSOUND_IN_PYTHON_MODULE
274 
275  static bool once = true;
276 
277  if(once)
278  {
279  once = false;
280  std::cerr
281  << "WARNING: Nsound::Plotter::show(): Nsound wasn't "
282  "compiled with matplotlib" << std::endl;
283  std::cerr.flush();
284  }
285  #endif
286  #endif
287 }
288 
289 //-----------------------------------------------------------------------------
290 PyObject *
291 Plotter::
292 _make_kwargs(const std::string & kwargs) const
293 {
294  #ifdef NSOUND_C_PYLAB
295 
296  if(kwargs == "") return PyDict_New();
297 
298  std::stringstream ss;
299 
300  ss << "dict(" << kwargs << ")\n";
301 
302  PyCodeObject * code = (PyCodeObject*) Py_CompileString(
303  ss.str().c_str(), "Plotter.cc", Py_eval_input);
304 
305  M_CHECK_PY_PTR(code, "Py_CompileString() failed");
306 
307  PyObject * globals = table_["globals"];
308 
309  PyObject * locals = PyDict_New();
310 
311  M_CHECK_PY_PTR(locals, "PyDict_New() failed");
312 
313  PyObject * kwdict = PyEval_EvalCode(code, globals, locals);
314 
315  Py_DECREF(code);
316  Py_DECREF(locals);
317 
318  return kwdict;
319 
320  #endif
321 
322  return NULL;
323 }
324 
325 void
326 Plotter::
328  const float64 & y_pos,
329  const std::string & kwargs)
330 {
331  #ifdef NSOUND_C_PYLAB
332 
334  {
335  return;
336  }
337 
338  PyObject * args = Py_BuildValue("(d)", y_pos);
339 
340  M_CHECK_PY_PTR_RETURN(args, "Py_BuildValue() failed");
341 
342  PyObject * kw_args = _make_kwargs(kwargs);
343 
344  PyObject * ret = PyObject_Call(table_["pylab.axhline"], args, kw_args);
345 
346  Py_DECREF(args);
347  Py_XDECREF(kw_args);
348 
349  M_CHECK_PY_PTR_RETURN(ret, "pylab.axhline() failed");
350 
351  Py_DECREF(ret);
352 
353  #endif
354 }
355 
356 void
357 Plotter::
359  const float64 & x_pos,
360  const std::string & kwargs)
361 {
362  #ifdef NSOUND_C_PYLAB
363 
365  {
366  return;
367  }
368 
369  PyObject * args = Py_BuildValue("(d)", x_pos);
370 
371  M_CHECK_PY_PTR_RETURN(args, "Py_BuildValue() failed");
372 
373  PyObject * kw_args = _make_kwargs(kwargs);
374 
375  PyObject * ret = PyObject_Call(table_["pylab.axvline"], args, kw_args);
376 
377  Py_DECREF(args);
378  Py_XDECREF(kw_args);
379 
380  M_CHECK_PY_PTR_RETURN(ret, "pylab.axvline() failed");
381 
382  Py_DECREF(ret);
383 
384  #endif
385 }
386 
387 void
388 Plotter::
390  const float64 & xmin,
391  const float64 & xmax)
392 {
393  #ifdef NSOUND_C_PYLAB
394 
396  {
397  return;
398  }
399 
400  M_ASSERT_VALUE(xmin, <, xmax);
401 
402  PyObject * args = Py_BuildValue("(d, d)", xmin, xmax);
403 
404  M_CHECK_PY_PTR_RETURN(args, "Py_BuildValue() failed");
405 
406  PyObject * kw_args = NULL; //_make_kwargs(kwargs);
407 
408  PyObject * ret = PyObject_Call(table_["pylab.xlim"], args, kw_args);
409 
410  Py_DECREF(args);
411  Py_XDECREF(kw_args);
412 
413  M_CHECK_PY_PTR_RETURN(ret, "pylab.xlim() failed");
414 
415  Py_DECREF(ret);
416 
417  #endif
418 }
419 
420 void
421 Plotter::
423  const float64 & ymin,
424  const float64 & ymax)
425 {
426  #ifdef NSOUND_C_PYLAB
427 
429  {
430  return;
431  }
432 
433  M_ASSERT_VALUE(ymin, <, ymax);
434 
435  PyObject * args = Py_BuildValue("(d, d)", ymin, ymax);
436 
437  M_CHECK_PY_PTR_RETURN(args, "Py_BuildValue() failed");
438 
439  PyObject * kw_args = NULL; //_make_kwargs(kwargs);
440 
441  PyObject * ret = PyObject_Call(table_["pylab.ylim"], args, kw_args);
442 
443  Py_DECREF(args);
444  Py_XDECREF(kw_args);
445 
446  M_CHECK_PY_PTR_RETURN(ret, "pylab.ylim() failed");
447 
448  Py_DECREF(ret);
449 
450  #endif
451 }
452 
453 void
454 Plotter::
455 figure(const std::string & kwargs) const
456 {
457  #ifdef NSOUND_C_PYLAB
458 
460  {
461  return;
462  }
463 
464 //~ if(Plotter::state_ != INITALIZED || hold_is_on_)
465 //~ {
466 //~ hold_is_on_ = false; // toggle it.
467 //~ return;
468 //~ }
469 
470  PyObject * args = Py_BuildValue("()");
471 
472  M_CHECK_PY_PTR_RETURN(args, "Py_BuildValue() failed");
473 
474  PyObject * kw_args = _make_kwargs(kwargs);
475 
476  PyObject * ret = PyObject_Call(table_["pylab.figure"], args, kw_args);
477 
478  Py_DECREF(args);
479  Py_XDECREF(kw_args);
480 
481  M_CHECK_PY_PTR_RETURN(ret, "pylab.figure() failed");
482 
483  Py_DECREF(ret);
484 
485 //~ // Reset limits
486 //~ xmax_ = -1e20;
487 //~ xmin_ = 1e20;
488 //~ ymin_ = xmin_;
489 //~ ymax_ = xmax_;
490 
491  #endif
492 }
493 
494 void
495 Plotter::
496 grid(boolean flag)
497 {
498 //~ grid_is_on_ = flag;
499 
500  if(flag)
501  {
502  run_string(
503  "try:\n"
504  " ax__ = _pylab_nsound_.gca();\n"
505  " ax__.grid(True);\n"
506  "except:\n"
507  " pass\n\n");
508  }
509 
510  else
511  {
512  run_string(
513  "try:\n"
514  " ax__ = _pylab_nsound_.gca();\n"
515  " ax__.grid(False);\n"
516  "except:\n"
517  " pass\n\n");
518  }
519 
520 
521 }
522 
523 void
524 Plotter::
526 {
527  #ifdef NSOUND_C_PYLAB
528 
530  {
531  return;
532  }
533 
534  PyObject * args = Py_BuildValue("(s)", "all");
535 
536  M_CHECK_PY_PTR_RETURN(args, "Py_BuildValue() failed");
537 
538  PyObject * kw_args = NULL; //_make_kwargs(kwargs);
539 
540  PyObject * ret = PyObject_Call(table_["pylab.close"], args, kw_args);
541 
542  Py_DECREF(args);
543  Py_XDECREF(kw_args);
544 
545  M_CHECK_PY_PTR_RETURN(ret, "pylab.close() failed");
546 
547  Py_DECREF(ret);
548 
549  #endif
550 }
551 
552 void
553 Plotter::
554 hold(boolean flag)
555 {
556  #ifdef NSOUND_C_PYLAB
557 
558  hold_is_on_ = flag;
559 
561  {
562  return;
563  }
564 
565  // Put the list in a tuple.
566  PyObject * args = NULL;
567 
568  if(hold_is_on_)
569  {
570  args = PyTuple_Pack(1, Py_True);
571  }
572  else
573  {
574  args = PyTuple_Pack(1, Py_False);
575  }
576 
577  PyObject * ret = PyObject_CallObject(table_["pylab.hold"], args);
578 
579  Py_DECREF(args);
580 
581  M_CHECK_PY_PTR_RETURN(ret, "pylab.hold() failed");
582 
583  if(hold_is_on_)
584  {
585  grid(false);
586  }
587 
588  #endif
589 }
590 
591 void
592 Plotter::
593 imagesc(const AudioStream & Z, const std::string & kwargs)
594 {
595  imagesc(Buffer(), Buffer(), Z, kwargs);
596 }
597 
598 void
599 Plotter::
601  const Buffer & x_axis,
602  const Buffer & y_axis,
603  const AudioStream & Z,
604  const std::string & kwargs)
605 {
606  #ifdef NSOUND_C_PYLAB
607 
609  {
610  return;
611  }
612 
613  uint32 M = Z.getNChannels();
614  uint32 N = Z.getLength();
615  uint32 x_size = x_axis.getLength();
616  uint32 y_size = y_axis.getLength();
617 
618  if(N == 0)
619  {
620  M_THROW("Nsound::Plotter::imagesc(): "
621  << "Z has zero columns! ("
622  << M
623  << " x "
624  << N
625  << ")");
626  return;
627  }
628 
629  if(x_size > 0 && x_size != N)
630  {
631  M_THROW("Nsound::Plotter::imagesc(): "
632  << "shape mismatch between x_axis and Z ("
633  << x_size
634  << " != "
635  << N
636  << ")");
637  return;
638  }
639 
640  if(y_size > 0 && y_size != M)
641  {
642  M_THROW("Nsound::Plotter::imagesc(): "
643  << "shape mismatch between y_axis and Z ("
644  << y_size
645  << " != "
646  << M
647  << ")");
648  return;
649  }
650 
651  float64 xmin = 0.0;
652  float64 xmax = 0.0;
653  float64 ymin = 0.0;
654  float64 ymax = 0.0;
655 
656  if(x_size == 0 && y_size == 0)
657  {
658  xmin = -0.5;
659  xmax = static_cast<float64>(N - 1) + 0.5;
660  ymin = -0.5;
661  ymax = static_cast<float64>(M - 1) + 0.5;
662  }
663  else if(x_size > 0 && y_size > 0)
664  {
665  float64 dx = x_axis[1] - x_axis[0];
666  float64 dy = y_axis[1] - y_axis[0];
667 
668  xmin = x_axis[0] - 0.5 * dx;
669  xmax = x_axis[N - 1] + 0.5 * dx;
670  ymin = y_axis[0] - 0.5 * dy;
671  ymax = y_axis[M - 1] + 0.5 * dy;
672  }
673 
674  // Create python list of lists to represent the matrix
675 
676  PyObject * matrix_list = PyList_New(M);
677 
678  M_CHECK_PY_PTR_RETURN(matrix_list, "PyList_New() failed");
679 
680  for(uint32 m = 0; m < M; ++m)
681  {
682  PyObject * array = makePyListFromBuffer(Z[m]);
683 
684  M_CHECK_PY_PTR_RETURN(array, "makePyListFromBuffer() failed");
685 
686  PyList_SET_ITEM(matrix_list, m, array);
687  }
688 
689  // Now build imshow's arguments and keyword args
690 
691  PyObject * args = Py_BuildValue("(O)", matrix_list);
692 
693  M_CHECK_PY_PTR_RETURN(args, "Py_BuildValue() failed");
694 
695  // build keywords
696  std::stringstream ss;
697 
698  ss << "extent=["
699  << xmin << "," << xmax << "," << ymin << "," << ymax << "],"
700  << "interpolation='nearest',"
701  << "origin='lower'";
702 
703  if(kwargs != "")
704  {
705  ss << "," << kwargs;
706  }
707 
708  PyObject * kw_args = _make_kwargs(ss.str());
709 
710  // Call pylab.plot().
711  PyObject * ret = PyObject_Call(table_["pylab.imshow"], args, kw_args);
712 
713  Py_DECREF(args);
714  Py_XDECREF(kw_args);
715 
716  M_CHECK_PY_PTR_RETURN(ret, "pylab.imshow() failed");
717 
718  Py_DECREF(ret);
719 
721  // Axis tight & Grid
722 
723  run_string(
724  "try:\n"
725  " ax__ = _pylab_nsound_.gca();\n"
726  " trash__ = ax__.axis('tight');\n"
727  "except:\n"
728  " pass\n\n");
729 
730  if(grid_is_on_)
731  {
732  run_string(
733  "try:\n"
734  " ax__ = _pylab_nsound_.gca();\n"
735  " ax__.grid(True);\n"
736  "except:\n"
737  " pass\n\n");
738  }
739 
740  #endif
741 }
742 
743 void
744 Plotter::
745 legend(const std::string & kwargs)
746 {
747  #ifdef NSOUND_C_PYLAB
748 
749  // Create args & kwargs.
750  PyObject * args = Py_BuildValue("()");
751  PyObject * kw_args = _make_kwargs(kwargs);
752 
753  PyObject * ret = PyObject_Call(table_["pylab.legend"], args, kw_args);
754 
755  M_CHECK_PY_PTR_RETURN(ret, "pylab.legend() failed");
756 
757  Py_DECREF(args);
758  Py_DECREF(kw_args);
759 
760  #endif
761 }
762 
763 void
764 Plotter::
766  const Buffer & buffer,
767  const std::string & fmt,
768  const std::string & kwargs)
769 {
770  plot(Buffer(), buffer, fmt, kwargs);
771 }
772 
773 void
774 Plotter::
776  const Buffer & x,
777  const Buffer & y,
778  const std::string & fmt,
779  const std::string & kwargs)
780 {
781  #ifdef NSOUND_C_PYLAB
782 
784  {
785  return;
786  }
787 
788  M_ASSERT_VALUE(y.getLength(), >, 0);
789 
790  PyObject * x_list = NULL;
791 
792  // X may be empty here.
793  if(x.getLength() > 0)
794  {
795  M_ASSERT_VALUE(x.getLength(), ==, y.getLength());
796 
797  x_list = makePyListFromBuffer(x);
798  }
799 
800  PyObject * y_list = makePyListFromBuffer(y);
801 
802  // Put the list in a tuple.
803  PyObject * args = NULL;
804 
805  // Count how many items are going into args.
806  uint32 n_args = 1;
807 
808  if(x_list != NULL) ++n_args;
809  if(fmt != "") ++n_args;
810 
811  args = PyTuple_New(n_args);
812 
813  M_CHECK_PY_PTR_RETURN(args, "PyTuple_New() failed");
814 
815  Py_ssize_t pos = 0;
816 
817  if(x_list != NULL)
818  {
819  PyTuple_SetItem(args, pos, x_list);
820  pos += 1;
821  }
822 
823  PyTuple_SetItem(args, pos, y_list);
824  pos += 1;
825 
826  PyObject * fmt_str = NULL;
827 
828  if(fmt != "")
829  {
830  fmt_str = PyString_FromString(fmt.c_str());
832  fmt_str, "PyString_FromString('" << fmt << "') failed");
833  PyTuple_SetItem(args, pos, fmt_str);
834  }
835 
836  PyObject * kw_args = _make_kwargs(kwargs);
837 
838  // Call pylab.plot().
839  PyObject * ret = PyObject_Call(table_["pylab.plot"], args, kw_args);
840 
841  Py_DECREF(kw_args);
842  Py_DECREF(args);
843 
844  M_CHECK_PY_PTR_RETURN(ret, "pylab.plot() failed");
845 
846  Py_DECREF(ret);
847 
848 //~ ///////////////////////////////////////////////////////////////////////
849 //~ // Setup plot limits to make stuff fit nicely
850 
851 //~ float64 xmin = 0.0;
852 //~ float64 xmax = y.getLength() - 1;
853 
854 //~ if(x.getLength() > 0)
855 //~ {
856 //~ xmin = x[0];
857 //~ xmax = x[x.getLength() - 1];
858 //~ }
859 
860 //~ float64 ymin = y.getMin();
861 //~ float64 ymax = y.getMax();
862 
863 //~ float64 margin = 0.05;
864 
865 //~ float64 dist = xmax - xmin;
866 
867 //~ xmin -= margin * dist;
868 //~ xmax += margin * dist;
869 
870 //~ dist = ymax - ymin;
871 
872 //~ ymin -= margin * dist;
873 //~ ymax += margin * dist;
874 
875 //~ // Create python list for [xmin, xmax, ymin, ymax]
876 
877 //~ PyObject * limits = PyList_New(4);
878 //~ PyList_SET_ITEM(limits, 0, PyFloat_FromDouble(xmin - 1e-19));
879 //~ PyList_SET_ITEM(limits, 1, PyFloat_FromDouble(xmax + 1e-19));
880 //~ PyList_SET_ITEM(limits, 2, PyFloat_FromDouble(ymin - 1e-19));
881 //~ PyList_SET_ITEM(limits, 3, PyFloat_FromDouble(ymax + 1e-19));
882 
883 //~ args = PyTuple_Pack(1, limits);
884 
885 //~ // Call pylab.axis().
886 //~ ret = PyObject_CallObject(table_["pylab.axis"], args);
887 
888 //~ Py_DECREF(args);
889 //~ Py_DECREF(limits);
890 
891 //~ if(!ret)
892 //~ {
893 //~ PyErr_Print();
894 //~ cerr << PRINT_LINE
895 //~ << "failed to call python pylab.axis()"
896 //~ << "\n";
897 //~ return;
898 //~ }
899 
900  if(grid_is_on_)
901  {
902  run_string(
903  "try:\n"
904  " ax__ = _pylab_nsound_.gca();\n"
905  " ax__.grid(True);\n"
906  "except:\n"
907  " pass\n\n");
908  }
909 
910  #endif
911 }
912 
913 void
914 Plotter::
916  const float64 & x,
917  const float64 & y,
918  const std::string & fmt,
919  const std::string & kwargs)
920 {
921  #ifdef NSOUND_C_PYLAB
922 
923  Buffer xx(1); xx << x;
924  Buffer yy(1); yy << y;
925 
926  plot(xx, yy, fmt, kwargs);
927 
928  #endif
929 }
930 
931 void
932 Plotter::
933 run_string(const std::string & command) const
934 {
935  #ifdef NSOUND_C_PYLAB
936 
937  std::string str = command + "\n";
938 
939  PyObject * ret = PyRun_String(
940  str.c_str(), Py_file_input, table_["globals"], NULL);
941 
942  M_CHECK_PY_PTR_RETURN(ret, "run_string() failed");
943 
944  Py_DECREF(ret);
945 
946  #endif
947 }
948 
949 void
950 Plotter::
951 savefig(const std::string & filename, const std::string & kwargs)
952 {
953  #ifdef NSOUND_C_PYLAB
954 
956  {
957  return;
958  }
959 
960  std::stringstream ss;
961 
962  ss << "savefig('"
963  << filename
964  << "'";
965 
966  if(kwargs.length() > 0)
967  {
968  ss << ", " << kwargs;
969  }
970 
971  ss << ")";
972 
973  run_string(ss.str());
974 
975 //~ std::string command(ss.str());
976 
977 //~ PyObject * ret = PyRun_String(command.c_str(), Py_eval_input, table_["pylab"], NULL);
978 
979 //~ if(!ret)
980 //~ {
981 //~ PyErr_Print();
982 //~ cerr << PRINT_LINE
983 //~ << "failed to call python '"
984 //~ << command
985 //~ << "'"
986 //~ << "\n";
987 //~ return;
988 //~ }
989 
990  #endif
991 }
992 
993 void
994 Plotter::
995 set_xscale(const std::string & s)
996 {
997  if(s != "log" && s != "linear") return;
998 
999  std::stringstream ss;
1000 
1001  ss
1002  << "try:\n"
1003  << " ax = _pylab_nsound_.gca();\n"
1004  << " ax.set_xscale('" << s << "')\n"
1005  << "except:\n"
1006  << " pass\n\n";
1007 
1008  run_string(ss.str());
1009 }
1010 
1011 void
1012 Plotter::
1013 set_yscale(const std::string & s)
1014 {
1015  if(s != "log" && s != "linear") return;
1016 
1017  std::stringstream ss;
1018 
1019  ss
1020  << "try:\n"
1021  << " ax = _pylab_nsound_.gca();\n"
1022  << " ax.set_yscale('" << s << "')\n"
1023  << "except:\n"
1024  << " pass\n\n";
1025 
1026  run_string(ss.str());
1027 }
1028 
1029 Axes
1030 Plotter::
1032  const uint32 n_rows,
1033  const uint32 n_columns,
1034  const uint32 n,
1035  const std::string & kwargs,
1036  Axes * sharex,
1037  Axes * sharey)
1038 {
1039  #ifdef NSOUND_C_PYLAB
1040 
1042  {
1043  return Axes(NULL);
1044  }
1045 
1046  // args
1047  PyObject * args = Py_BuildValue("(iii)", n_rows, n_columns, n);
1048 
1049  // kwargs
1050  PyObject * kw_args = _make_kwargs(kwargs);
1051 
1052  // Stick in sharex & sharey
1053  if(sharex != NULL)
1054  {
1055  PyObject * key = PyString_FromString("sharex");
1056  PyDict_SetItem(kw_args, key, sharex->get_axes());
1057  }
1058 
1059  if(sharey != NULL)
1060  {
1061  PyObject * key = PyString_FromString("sharey");
1062  PyDict_SetItem(kw_args, key, sharey->get_axes());
1063  }
1064 
1065  // Call pylab.subplot()
1066  PyObject * ret = PyObject_Call(table_["pylab.subplot"], args, kw_args);
1067 
1068  Py_DECREF(args);
1069  Py_DECREF(kw_args);
1070 
1071  M_CHECK_PY_PTR(ret, "pylab.subplot() failed");
1072 
1073  if(grid_is_on_)
1074  {
1075  run_string(
1076  "try:\n"
1077  " ax = _pylab_nsound_.gca();\n"
1078  " ax.grid(True);\n"
1079  "except:\n"
1080  " pass\n\n");
1081  }
1082 
1083  return Axes(ret);
1084 
1085  #endif
1086 
1087  return Axes(NULL);
1088 }
1089 
1090 void
1091 Plotter::
1093  const float64 & x,
1094  const float64 & y,
1095  const std::string & text,
1096  const std::string & kwargs)
1097 {
1098  #ifdef NSOUND_C_PYLAB
1099 
1101  {
1102  return;
1103  }
1104 
1105  // Create a python string.
1106 
1107  PyObject * args = Py_BuildValue("(dds)",
1108  x, y, text.c_str());
1109 
1110  PyObject * kw_args = _make_kwargs(kwargs);
1111 
1112  // Call pylab.title()
1113  PyObject * ret = PyObject_Call(table_["pylab.text"], args, kw_args);
1114 
1115  Py_DECREF(kw_args);
1116  Py_DECREF(args);
1117 
1118  M_CHECK_PY_PTR_RETURN(ret, "pylab.text() failed");
1119 
1120  Py_DECREF(ret);
1121 
1122  #endif
1123 }
1124 
1125 void
1126 Plotter::
1127 title(const std::string & title, const std::string & kwargs)
1128 {
1129  #ifdef NSOUND_C_PYLAB
1130 
1132  {
1133  return;
1134  }
1135 
1136  PyObject * args = Py_BuildValue("(s)", title.c_str());
1137  PyObject * kw_args = _make_kwargs(kwargs);
1138 
1139  // Call pylab.title()
1140  PyObject * ret = PyObject_Call(table_["pylab.title"], args, kw_args);
1141 
1142  Py_DECREF(kw_args);
1143  Py_DECREF(args);
1144 
1145  M_CHECK_PY_PTR_RETURN(ret, "pylab.title() failed");
1146 
1147  Py_DECREF(ret);
1148 
1149  #endif
1150 }
1151 
1152 void
1153 Plotter::
1154 xlabel(const std::string & label, const std::string & kwargs)
1155 {
1156  #ifdef NSOUND_C_PYLAB
1157 
1159  {
1160  return;
1161  }
1162 
1163  PyObject * args = Py_BuildValue("(s)", label.c_str());
1164  PyObject * kw_args = _make_kwargs(kwargs);
1165 
1166  PyObject * ret = PyObject_Call(table_["pylab.xlabel"], args, kw_args);
1167 
1168  Py_DECREF(kw_args);
1169  Py_DECREF(args);
1170 
1171  M_CHECK_PY_PTR_RETURN(ret, "pylab.xlabel() failed");
1172 
1173  Py_DECREF(ret);
1174 
1175  #endif
1176 }
1177 
1178 void
1179 Plotter::
1180 ylabel(const std::string & label, const std::string & kwargs)
1181 {
1182  #ifdef NSOUND_C_PYLAB
1183 
1185  {
1186  return;
1187  }
1188 
1189  PyObject * args = Py_BuildValue("(s)", label.c_str());
1190  PyObject * kw_args = _make_kwargs(kwargs);
1191 
1192  PyObject * ret = PyObject_Call(table_["pylab.ylabel"], args, kw_args);
1193 
1194  Py_DECREF(kw_args);
1195  Py_DECREF(args);
1196 
1197  M_CHECK_PY_PTR_RETURN(ret, "pylab.ylabel() failed");
1198 
1199  Py_DECREF(ret);
1200 
1201  #endif
1202 }
1203 
1204 #ifdef NSOUND_C_PYLAB
1205  PyObject *
1206  Plotter::
1207  makePyListFromBuffer(const Buffer & buffer) const
1208  {
1209  uint32 n_samples = buffer.getLength();
1210 
1211  PyObject * py_list = PyList_New(n_samples);
1212 
1213  M_CHECK_PY_PTR(py_list, "PyList_New() failed");
1214 
1215  for(uint32 i = 0; i < n_samples; ++i)
1216  {
1217  PyList_SET_ITEM(py_list, i,
1218  PyFloat_FromDouble(static_cast<float64>(buffer[i])));
1219  }
1220 
1221  return py_list;
1222  }
1223 
1224  PyObject *
1225  Plotter::
1226  makePyIntFromUint32(const uint32 & i) const
1227  {
1228  PyObject * py_int = PyInt_FromLong(i);
1229 
1230  M_CHECK_PY_PTR(py_int, "PyInt_FromLong() failed");
1231 
1232  return py_int;
1233  }
1234 
1235 #endif
1236 
1237 // :mode=c++:
PyObject * makePyIntFromUint32(const uint32 &i) const
Create a PyInt.
unsigned int uint32
Definition: Nsound.h:153
void xlabel(const std::string &label, const std::string &kwargs="")
Add a label x axis.
Definition: Plotter.cc:1154
void grid(boolean flag)
Sets the grid state.
Definition: Plotter.cc:496
#define M_ASSERT_VALUE(a, op, value)
Definition: Macros.h:76
PyObject * get_axes()
Definition: Plotter.h:62
PyObject * _make_kwargs(const std::string &kwargs) const
Definition: Plotter.cc:292
static void show()
Acutally draw the plots to the screen.
Definition: Plotter.cc:252
static PylabTable table_
Definition: Plotter.h:209
void savefig(const std::string &filename, const std::string &kwargs="")
Saves the last figure drawn to filename.
Definition: Plotter.cc:951
static boolean grid_is_on_
Definition: Plotter.h:220
void plot(const Buffer &y, const std::string &fmt="", const std::string &kwargs="")
Plots the Buffer on the current figure.
Definition: Plotter.cc:765
static float64 xmin_
Definition: Plotter.h:223
void axvline(const float64 &x_pos=0.0, const std::string &kwargs="")
Draws a vertical line at x and spans ymin to ymax (ralitive).
Definition: Plotter.cc:358
#define M_CHECK_PY_PTR(a, msg)
Definition: Plotter.cc:105
uint32 getLength() const
Returns the number of samples of audio data in the stream.
Definition: AudioStream.cc:197
void hide()
Hides all plots, prevents any plot window being rendered to the screen. Usefull if only saveing plots...
Definition: Plotter.cc:525
void figure(const std::string &kwargs="") const
Creates a new figure window to plot in.
Definition: Plotter.cc:455
A wrapper around a Matplotlib Axes object.
Definition: Plotter.h:54
void title(const std::string &title, const std::string &kwargs="")
Add a title to the plot at the top and centered.
Definition: Plotter.cc:1127
std::pair< std::string, PyObject * > StringPyObjectPair
Definition: Plotter.h:198
void legend(const std::string &kwargs="")
Shows the legend on the current axes.
Definition: Plotter.cc:745
static float64 ymin_
Definition: Plotter.h:225
void xlim(const float64 &xmin, const float64 &xmax)
Sets the limit for the x & y axis.
Definition: Plotter.cc:389
PyObject * makePyListFromBuffer(const Buffer &buffer) const
Create a PyList object from a buffer!
static boolean hold_is_on_
Definition: Plotter.h:221
double float64
Definition: Nsound.h:146
void set_yscale(const std::string &s)
Sets the y axis scaling: log or linear.
Definition: Plotter.cc:1013
void set_xscale(const std::string &s)
Sets the x axis scaling: log or linear.
Definition: Plotter.cc:995
uint32 getLength() const
Returns the number of samples in the Buffer.
Definition: Buffer.h:587
Plotter()
Construct the Plotter.
Definition: Plotter.cc:114
Axes subplot(const uint32 n_rows, const uint32 n_cols, const uint32 n, const std::string &kwargs="", Axes *sharex=NULL, Axes *sharey=NULL)
Creates a figure in a subplot, subplot(A, B, C, **kwargs)
Definition: Plotter.cc:1031
void ylim(const float64 &ymin, const float64 &ymax)
Definition: Plotter.cc:422
void PyObject
Definition: Plotter.h:46
PyObject * axes_ptr_
Definition: Plotter.h:62
uint32 getNChannels(void) const
Returns the number of audio channels in the stream.
Definition: AudioStream.h:212
void imagesc(const AudioStream &Z, const std::string &kwargs="")
Plots the AudioStream like a 2D matrix.
Definition: Plotter.cc:593
void text(const float64 &x, const float64 &y, const std::string &text, const std::string &kwargs="")
Adds text at the x, y data point.
Definition: Plotter.cc:1092
void hold(boolean flag)
Sets the hold state.
Definition: Plotter.cc:554
#define M_THROW(message)
Definition: Macros.h:108
Axes & operator=(const Axes &rhs)
Definition: Plotter.cc:91
static float64 xmax_
Definition: Plotter.h:224
Axes(PyObject *axes_ptr)
Definition: Plotter.cc:73
static PlotterState state_
Definition: Plotter.h:218
void ylabel(const std::string &label, const std::string &kwargs="")
Add a label y axis.
Definition: Plotter.cc:1180
A Buffer for storing audio samples.
Definition: Buffer.h:60
signed int int32
Definition: Nsound.h:142
#define M_CHECK_PY_PTR_RETURN(a, msg)
Definition: Plotter.cc:97
void axhline(const float64 &y_pos=0.0, const std::string &kwargs="")
Draws a horizontal line at y and spans xmin to xmax (ralitive).
Definition: Plotter.cc:327
std::map< std::string, PyObject * > PylabTable
Definition: Plotter.h:203
static int32 count_
Definition: Plotter.h:207
void run_string(const std::string &command) const
executes the python string
Definition: Plotter.cc:933
static float64 ymax_
Definition: Plotter.h:226
static Plotter g_plotter
Definition: Plotter.cc:65
virtual ~Plotter()
Deconstruct the Plotter.
Definition: Plotter.cc:230