Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2ce9760

Browse files
author
Benno Evers
committed
Update documentation after introducing numpy
1 parent ac61b3f commit 2ce9760

File tree

4 files changed

+59
-44
lines changed

4 files changed

+59
-44
lines changed

Makefile

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
examples: minimal basic modern
22

33
minimal: examples/minimal.cpp matplotlibcpp.h
4-
cd examples && g++ minimal.cpp -lpython2.7 -o minimal -std=c++11
4+
cd examples && g++ -DWITHOUT_NUMPY minimal.cpp -I/usr/include/python2.7 -lpython2.7 -o minimal -std=c++11
55

66
basic: examples/basic.cpp matplotlibcpp.h
7-
cd examples && g++ basic.cpp -lpython2.7 -o basic
7+
cd examples && g++ basic.cpp -I/usr/include/python2.7 -lpython2.7 -o basic
88

99
modern: examples/modern.cpp matplotlibcpp.h
10-
cd examples && g++ modern.cpp -lpython2.7 -o modern -std=c++11
10+
cd examples && g++ modern.cpp -I/usr/include/python2.7 -lpython2.7 -o modern -std=c++11
1111

README.md

+15-15
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Complete minimal example:
1717
plt::show();
1818
}
1919

20-
// g++ minimal.cpp -std=c++11 -lpython2.7
20+
// g++ minimal.cpp -std=c++11 -I/usr/include/python2.7 -lpython2.7
2121

2222
Result: ![Minimal example](./examples/minimal.png)
2323

@@ -54,7 +54,7 @@ A more comprehensive example:
5454
plt::save("./basic.png");
5555
}
5656

57-
// g++ basic.cpp -lpython2.7
57+
// g++ basic.cpp -I/usr/include/python2.7 -lpython2.7
5858

5959
Result: ![Basic example](./examples/basic.png)
6060

@@ -87,37 +87,39 @@ matplotlib-cpp doesn't require C++11, but will enable some additional syntactic
8787
plt::show();
8888
}
8989

90-
// g++ modern.cpp -std=c++11 -lpython
90+
// g++ modern.cpp -std=c++11 -I/usr/include/python2.7 -lpython
9191

9292
Result: ![Modern example](./examples/modern.png)
9393

9494
Installation
9595
------------
96+
9697
matplotlib-cpp works by wrapping the popular python plotting library matplotlib. (matplotlib.org)
9798
This means you have to have a working python installation, including development headers.
9899
On Ubuntu:
99100

100-
sudo aptitude install python-matplotlib python2.7-dev
101+
sudo aptitude install python-matplotlib python-numpy python2.7-dev
102+
103+
If, for some reason, you're unable to get a working installation of numpy on your system,
104+
you can add the define `WITHOUT_NUMPY` to erase this dependency.
101105

102106
The C++-part of the library consists of the single header file `matplotlibcpp.h` which can be placed
103107
anywhere.
108+
104109
Since a python interpreter is opened internally, it is necessary to link against `libpython2.7` in order to use
105110
matplotlib-cpp.
106111

107112
# Python 3
108113

109-
The code is written in a way that should support both python2 and python3.
110-
By default, matplotlib-cpp will try to "just work" and include the header `python2.7/Python.h`.
114+
This library supports both python2 and python3 (although the python3 support is probably far less tested,
115+
so it is recommended to prefer python2.7). To switch the used python version, simply change
116+
the compiler flags accordingly.
111117

112-
To modify this behaviour the define `MATPLOTLIBCPP_PYTHON_HEADER`,
113-
can be set to an absolute or relative path:
118+
g++ example.cpp -I/usr/include/python3.6 -lpython3.6
114119

115-
#define MATPLOTLIBCPP_PYTHON_HEADER /usr/include/python3.6/Python.h
116-
#include "matplotlibcpp.h"
120+
The same technique can be used for linking against a custom build of python
117121

118-
or
119-
120-
g++ -DMATPLOTLIBCPP_PYTHON_HEADER=Python.h -I/usr/include/python3.6 <...>
122+
g++ example.cpp -I/usr/local/include/fancy-python4 -L/usr/local/lib -lfancy-python4
121123

122124

123125
Why?
@@ -152,7 +154,5 @@ Todo/Issues/Wishlist
152154
* Right now, only a small subset of matplotlibs functionality is exposed. Stuff like xlabel()/ylabel() etc. should
153155
be easy to add.
154156

155-
* A lot of copying could be avoided if we generate numpy arrays directly instead of python lists
156-
157157
* If you use Anaconda on Windows, you might need to set PYTHONHOME to Anaconda home directory and QT_QPA_PLATFORM_PLUGIN_PATH to %PYTHONHOME%Library/plugins/platforms. The latter is for especially when you get the error which says 'This application failed to start because it could not find or load the Qt platform plugin "windows"
158158
in "".'

examples/minimal.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
namespace plt = matplotlibcpp;
44

55
int main() {
6-
plt::plot({1,2,3,4});
6+
plt::plot({1,3,2,4});
77
plt::show();
88
}

matplotlibcpp.h

+40-25
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,23 @@
66
#include <algorithm>
77
#include <stdexcept>
88
#include <iostream>
9+
#include <stdint.h> // <cstdint> requires c++11 support
910

1011
#if __cplusplus > 199711L || _MSC_VER > 1800
1112
#include <functional>
1213
#endif
1314

14-
// i.e. g++ -DMATPLOTLIBCPP_PYTHON_HEADER=/usr/include/python3.6/Python.h [...]
15-
#ifdef MATPLOTLIBCPP_PYTHON_HEADER
16-
#define STRINGIFY_(x) #x
17-
#define STRINGIFY(x) STRINGIFY_(x)
18-
#include STRINGIFY(MATPLOTLIBCPP_PYTHON_HEADER)
19-
#else // This should stay the default for backwards compatibility
20-
#include <python2.7/Python.h>
21-
#endif
15+
#include <Python.h>
16+
17+
#ifndef WITHOUT_NUMPY
18+
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
19+
#include <numpy/arrayobject.h>
20+
#endif // WITHOUT_NUMPY
2221

2322
#if PY_MAJOR_VERSION >= 3
2423
#define PyString_FromString PyUnicode_FromString
2524
#endif
2625

27-
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
28-
#include <numpy/arrayobject.h>
2926

3027
namespace matplotlibcpp {
3128

@@ -68,14 +65,16 @@ namespace matplotlibcpp {
6865

6966
// optional but recommended
7067
#if PY_MAJOR_VERSION >= 3
71-
wchar_t name[] = L"plotting";
68+
wchar_t name[] = L"plotting";
7269
#else
73-
char name[] = "plotting";
70+
char name[] = "plotting";
7471
#endif
7572
Py_SetProgramName(name);
7673
Py_Initialize();
7774

75+
#ifndef WITHOUT_NUMPY
7876
import_array(); // initialize numpy C-API
77+
#endif
7978

8079
PyObject* pyplotname = PyString_FromString("matplotlib.pyplot");
8180
PyObject* pylabname = PyString_FromString("pylab");
@@ -182,19 +181,21 @@ namespace matplotlibcpp {
182181

183182
return res;
184183
}
184+
185+
#ifndef WITHOUT_NUMPY
185186
// Type selector for numpy array conversion
186187
template <typename T> struct select_npy_type { const static NPY_TYPES type = NPY_NOTYPE; }; //Default
187188
template <> struct select_npy_type<double> { const static NPY_TYPES type = NPY_DOUBLE; };
188189
template <> struct select_npy_type<float> { const static NPY_TYPES type = NPY_FLOAT; };
189190
template <> struct select_npy_type<bool> { const static NPY_TYPES type = NPY_BOOL; };
190-
template <> struct select_npy_type<std::int8_t> { const static NPY_TYPES type = NPY_INT8; };
191-
template <> struct select_npy_type<std::int16_t> { const static NPY_TYPES type = NPY_SHORT; };
192-
template <> struct select_npy_type<std::int32_t> { const static NPY_TYPES type = NPY_INT; };
193-
template <> struct select_npy_type<std::int64_t> { const static NPY_TYPES type = NPY_INT64; };
194-
template <> struct select_npy_type<std::uint8_t> { const static NPY_TYPES type = NPY_UINT8; };
195-
template <> struct select_npy_type<std::uint16_t> { const static NPY_TYPES type = NPY_USHORT; };
196-
template <> struct select_npy_type<std::uint32_t> { const static NPY_TYPES type = NPY_ULONG; };
197-
template <> struct select_npy_type<std::uint64_t> { const static NPY_TYPES type = NPY_UINT64; };
191+
template <> struct select_npy_type<int8_t> { const static NPY_TYPES type = NPY_INT8; };
192+
template <> struct select_npy_type<int16_t> { const static NPY_TYPES type = NPY_SHORT; };
193+
template <> struct select_npy_type<int32_t> { const static NPY_TYPES type = NPY_INT; };
194+
template <> struct select_npy_type<int64_t> { const static NPY_TYPES type = NPY_INT64; };
195+
template <> struct select_npy_type<uint8_t> { const static NPY_TYPES type = NPY_UINT8; };
196+
template <> struct select_npy_type<uint16_t> { const static NPY_TYPES type = NPY_USHORT; };
197+
template <> struct select_npy_type<uint32_t> { const static NPY_TYPES type = NPY_ULONG; };
198+
template <> struct select_npy_type<uint64_t> { const static NPY_TYPES type = NPY_UINT64; };
198199

199200
template<typename Numeric>
200201
PyObject* get_array(const std::vector<Numeric>& v)
@@ -203,18 +204,32 @@ namespace matplotlibcpp {
203204
NPY_TYPES type = select_npy_type<Numeric>::type;
204205
if (type == NPY_NOTYPE)
205206
{
206-
std::vector<double> vd(v.size());
207-
npy_intp vsize = v.size();
208-
std::copy(v.begin(),v.end(),vd.begin());
209-
PyObject* varray = PyArray_SimpleNewFromData(1, &vsize, NPY_DOUBLE, (void*)(vd.data()));
210-
return varray;
207+
std::vector<double> vd(v.size());
208+
npy_intp vsize = v.size();
209+
std::copy(v.begin(),v.end(),vd.begin());
210+
PyObject* varray = PyArray_SimpleNewFromData(1, &vsize, NPY_DOUBLE, (void*)(vd.data()));
211+
return varray;
211212
}
212213

213214
npy_intp vsize = v.size();
214215
PyObject* varray = PyArray_SimpleNewFromData(1, &vsize, type, (void*)(v.data()));
215216
return varray;
216217
}
217218

219+
#else // fallback if we don't have numpy: copy every element of the given vector
220+
221+
template<typename Numeric>
222+
PyObject* get_array(const std::vector<Numeric>& v)
223+
{
224+
PyObject* list = PyList_New(v.size());
225+
for(size_t i = 0; i < v.size(); ++i) {
226+
PyList_SetItem(list, i, PyFloat_FromDouble(v.at(i)));
227+
}
228+
return list;
229+
}
230+
231+
#endif // WITHOUT_NUMPY
232+
218233
template<typename Numeric>
219234
bool plot(const std::vector<Numeric> &x, const std::vector<Numeric> &y, const std::map<std::string, std::string>& keywords)
220235
{

0 commit comments

Comments
 (0)