Skip to content

Commit fb4cdf9

Browse files
tirtadwipamlava
tirtadwipam
authored andcommitted
Support for stem and xkcd (#43)
* Add support for stem and xkcd * Add README for xkcd
1 parent 71bd59b commit fb4cdf9

File tree

4 files changed

+153
-0
lines changed

4 files changed

+153
-0
lines changed

README.md

+30
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,36 @@ int main()
9393
9494
Result: ![Modern example](./examples/modern.png)
9595
96+
Or some *funny-looking xkcd-styled* example:
97+
```cpp
98+
#include "matplotlibcpp.h"
99+
#include <vector>
100+
#include <cmath>
101+
102+
namespace plt = matplotlibcpp;
103+
104+
int main() {
105+
std::vector<double> t(1000);
106+
std::vector<double> x(t.size());
107+
108+
for(size_t i = 0; i < t.size(); i++) {
109+
t[i] = i / 100.0;
110+
x[i] = sin(2.0 * M_PI * 1.0 * t[i]);
111+
}
112+
113+
plt::xkcd();
114+
plt::plot(t, x);
115+
plt::title("AN ORDINARY SIN WAVE");
116+
plt::save("xkcd.png");
117+
}
118+
119+
```
120+
g++ xkcd.cpp -std=c++11 -I/usr/include/python2.7 -lpython2.7
121+
122+
**Result:**
123+
124+
![Minimal example](./examples/xkcd.png)
125+
96126
Installation
97127
------------
98128

examples/xkcd.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include "../matplotlibcpp.h"
2+
#include <vector>
3+
#include <cmath>
4+
5+
namespace plt = matplotlibcpp;
6+
7+
int main() {
8+
std::vector<double> t(1000);
9+
std::vector<double> x(t.size());
10+
11+
for(size_t i = 0; i < t.size(); i++) {
12+
t[i] = i / 100.0;
13+
x[i] = sin(2.0 * M_PI * 1.0 * t[i]);
14+
}
15+
16+
plt::xkcd();
17+
plt::plot(t, x);
18+
plt::title("AN ORDINARY SIN WAVE");
19+
plt::save("xkcd.png");
20+
}
21+

examples/xkcd.png

77.6 KB
Loading

matplotlibcpp.h

+102
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ namespace matplotlibcpp {
5555
PyObject *s_python_function_annotate;
5656
PyObject *s_python_function_tight_layout;
5757
PyObject *s_python_empty_tuple;
58+
PyObject *s_python_function_stem;
59+
PyObject *s_python_function_xkcd;
5860

5961
/* For now, _interpreter is implemented as a singleton since its currently not possible to have
6062
multiple independent embedded python interpreters without patching the python source code
@@ -133,6 +135,8 @@ namespace matplotlibcpp {
133135
s_python_function_clf = PyObject_GetAttrString(pymod, "clf");
134136
s_python_function_errorbar = PyObject_GetAttrString(pymod, "errorbar");
135137
s_python_function_tight_layout = PyObject_GetAttrString(pymod, "tight_layout");
138+
s_python_function_stem = PyObject_GetAttrString(pymod, "stem");
139+
s_python_function_xkcd = PyObject_GetAttrString(pymod, "xkcd");
136140

137141
if( !s_python_function_show
138142
|| !s_python_function_draw
@@ -158,6 +162,8 @@ namespace matplotlibcpp {
158162
|| !s_python_function_errorbar
159163
|| !s_python_function_errorbar
160164
|| !s_python_function_tight_layout
165+
|| !s_python_function_stem
166+
|| !s_python_function_xkcd
161167
) { throw std::runtime_error("Couldn't find required function!"); }
162168

163169
if ( !PyFunction_Check(s_python_function_show)
@@ -183,6 +189,8 @@ namespace matplotlibcpp {
183189
|| !PyFunction_Check(s_python_function_clf)
184190
|| !PyFunction_Check(s_python_function_tight_layout)
185191
|| !PyFunction_Check(s_python_function_errorbar)
192+
|| !PyFunction_Check(s_python_function_stem)
193+
|| !PyFunction_Check(s_python_function_xkcd)
186194
) { throw std::runtime_error("Python object is unexpectedly not a PyFunction."); }
187195

188196
s_python_empty_tuple = PyTuple_New(0);
@@ -302,6 +310,39 @@ namespace matplotlibcpp {
302310
return res;
303311
}
304312

313+
template<typename Numeric>
314+
bool stem(const std::vector<Numeric> &x, const std::vector<Numeric> &y, const std::map<std::string, std::string>& keywords)
315+
{
316+
assert(x.size() == y.size());
317+
318+
// using numpy arrays
319+
PyObject* xarray = get_array(x);
320+
PyObject* yarray = get_array(y);
321+
322+
// construct positional args
323+
PyObject* args = PyTuple_New(2);
324+
PyTuple_SetItem(args, 0, xarray);
325+
PyTuple_SetItem(args, 1, yarray);
326+
327+
// construct keyword args
328+
PyObject* kwargs = PyDict_New();
329+
for (std::map<std::string, std::string>::const_iterator it =
330+
keywords.begin(); it != keywords.end(); ++it) {
331+
PyDict_SetItemString(kwargs, it->first.c_str(),
332+
PyString_FromString(it->second.c_str()));
333+
}
334+
335+
PyObject* res = PyObject_Call(
336+
detail::_interpreter::get().s_python_function_stem, args, kwargs);
337+
338+
Py_DECREF(args);
339+
Py_DECREF(kwargs);
340+
if (res)
341+
Py_DECREF(res);
342+
343+
return res;
344+
}
345+
305346
template< typename Numeric >
306347
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)
307348
{
@@ -409,6 +450,31 @@ namespace matplotlibcpp {
409450
return res;
410451
}
411452

453+
template<typename NumericX, typename NumericY>
454+
bool stem(const std::vector<NumericX>& x, const std::vector<NumericY>& y, const std::string& s = "")
455+
{
456+
assert(x.size() == y.size());
457+
458+
PyObject* xarray = get_array(x);
459+
PyObject* yarray = get_array(y);
460+
461+
PyObject* pystring = PyString_FromString(s.c_str());
462+
463+
PyObject* plot_args = PyTuple_New(3);
464+
PyTuple_SetItem(plot_args, 0, xarray);
465+
PyTuple_SetItem(plot_args, 1, yarray);
466+
PyTuple_SetItem(plot_args, 2, pystring);
467+
468+
PyObject* res = PyObject_CallObject(
469+
detail::_interpreter::get().s_python_function_stem, plot_args);
470+
471+
Py_DECREF(plot_args);
472+
if (res)
473+
Py_DECREF(res);
474+
475+
return res;
476+
}
477+
412478
template<typename NumericX, typename NumericY>
413479
bool semilogx(const std::vector<NumericX>& x, const std::vector<NumericY>& y, const std::string& s = "")
414480
{
@@ -642,6 +708,14 @@ namespace matplotlibcpp {
642708
return plot(x,y,format);
643709
}
644710

711+
template<typename Numeric>
712+
bool stem(const std::vector<Numeric>& y, const std::string& format = "")
713+
{
714+
std::vector<Numeric> x(y.size());
715+
for (size_t i = 0; i < x.size(); ++i) x.at(i) = i;
716+
return stem(x, y, format);
717+
}
718+
645719
inline void figure()
646720
{
647721
PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_figure, detail::_interpreter::get().s_python_empty_tuple);
@@ -826,6 +900,19 @@ namespace matplotlibcpp {
826900
Py_DECREF(res);
827901
}
828902

903+
inline void xkcd() {
904+
PyObject* res;
905+
PyObject *kwargs = PyDict_New();
906+
907+
res = PyObject_Call(detail::_interpreter::get().s_python_function_xkcd,
908+
detail::_interpreter::get().s_python_empty_tuple, kwargs);
909+
910+
if (!res)
911+
throw std::runtime_error("Call to show() failed.");
912+
913+
Py_DECREF(res);
914+
}
915+
829916
inline void draw()
830917
{
831918
PyObject* res = PyObject_CallObject(
@@ -1015,6 +1102,21 @@ namespace matplotlibcpp {
10151102
return plot<double>(x,y,keywords);
10161103
}
10171104

1105+
bool stem(const std::vector<double>& x, const std::vector<double>& y, const std::string& format = "")
1106+
{
1107+
return stem<double, double>(x, y, format);
1108+
}
1109+
1110+
bool stem(const std::vector<double>& y, const std::string& format = "")
1111+
{
1112+
return stem<double>(y, format);
1113+
}
1114+
1115+
bool stem(const std::vector<double>& x, const std::vector<double>& y, const std::map<std::string, std::string>& keywords)
1116+
{
1117+
return stem<double>(x, y, keywords);
1118+
}
1119+
10181120
bool named_plot(const std::string& name, const std::vector<double>& x, const std::vector<double>& y, const std::string& format = "") {
10191121
return named_plot<double>(name,x,y,format);
10201122
}

0 commit comments

Comments
 (0)