diff --git a/.gitignore b/.gitignore index 7622be79..60d7cfa3 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,4 @@ # Build /examples/build/* +/build diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..394826e8 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,109 @@ +cmake_minimum_required(VERSION 3.0) + +project(matplotlibcpp VERSION 0.1.0 LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_EXTENSIONS OFF) + +LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") + +# Call find_package(PythonInterp) first to get the currently active Python version and use that for +# setting the version to find for find_package(PythonLibs) +find_package(PythonInterp REQUIRED) +set(Python_ADDITIONAL_VERSIONS ${PYTHON_VERSION_STRING}) +find_package(PythonLibs REQUIRED) + +find_package(NumPy) # In case numpy headers are at non-standard locations + +add_library(${PROJECT_NAME} INTERFACE) +target_include_directories(${PROJECT_NAME} INTERFACE + $) +target_include_directories(${PROJECT_NAME} INTERFACE ${PYTHON_INCLUDE_DIRS} ${NumPy_INCLUDE_DIRS}) +target_link_libraries(${PROJECT_NAME} INTERFACE ${PYTHON_LIBRARIES}) +if(NOT NumPy_FOUND) + target_compile_definitions(${PROJECT_NAME} INTERFACE "-DWITHOUT_NUMPY") +else() + set(NUMPY_DEP "NumPy") +endif() + +install(TARGETS ${PROJECT_NAME} EXPORT "${PROJECT_NAME}Targets" + LIBRARY DESTINATION "lib" + ARCHIVE DESTINATION "lib" + RUNTIME DESTINATION "bin" + INCLUDES DESTINATION "include" + ) + +install(DIRECTORY "include/${PROJECT_NAME}" + DESTINATION "include" + FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp" + PATTERN ".svn" EXCLUDE + ) + +if(NumPy_FOUND) +install(FILES cmake/FindNumPy.cmake + DESTINATION "share/${PROJECT_NAME}/cmake" + ) +endif() + +include(cmake/GenerateAndInstallConfig.cmake) +generate_and_install_config_file( + INCLUDE_DIRS "include" + LIBRARIES + DEPS "PythonLibs ${Python_ADDITIONAL_VERSIONS}" ${NUMPY_DEP} + DEPS_INCLUDE_DIRS PYTHON ${NUMPY_DEP} + DEPS_LIBRARIES PYTHON + ) + +# Examples +option(MATPLOTLIBCPP_EXAMPLES "Build matplotlib examples" OFF) + +if(MATPLOTLIBCPP_EXAMPLES) + add_executable(animation "examples/animation.cpp") + target_link_libraries(animation matplotlibcpp) + + add_executable(bar "examples/bar.cpp") + target_link_libraries(bar matplotlibcpp) + + add_executable(basic "examples/basic.cpp") + target_link_libraries(basic matplotlibcpp) + + add_executable(fill "examples/fill.cpp") + target_link_libraries(fill matplotlibcpp) + + add_executable(fill_inbetween "examples/fill_inbetween.cpp") + target_link_libraries(fill_inbetween matplotlibcpp) + + if(NumPy_FOUND) + add_executable(imshow "examples/imshow.cpp") + target_link_libraries(imshow matplotlibcpp) + endif() + + add_executable(minimal "examples/minimal.cpp") + target_link_libraries(minimal matplotlibcpp) + + add_executable(modern "examples/modern.cpp") + target_link_libraries(modern matplotlibcpp) + + add_executable(nonblock "examples/nonblock.cpp") + target_link_libraries(nonblock matplotlibcpp) + + add_executable(quiver "examples/quiver.cpp") + target_link_libraries(quiver matplotlibcpp) + + add_executable(subplot "examples/subplot.cpp") + target_link_libraries(subplot matplotlibcpp) + + add_executable(subplot2grid "examples/subplot2grid.cpp") + target_link_libraries(subplot2grid matplotlibcpp) + + if(NumPy_FOUND) + add_executable(surface "examples/surface.cpp") + target_link_libraries(surface matplotlibcpp) + endif() + + add_executable(update "examples/update.cpp") + target_link_libraries(update matplotlibcpp) + + add_executable(xkcd "examples/xkcd.cpp") + target_link_libraries(xkcd matplotlibcpp) +endif(MATPLOTLIBCPP_EXAMPLES) diff --git a/Makefile b/Makefile deleted file mode 100644 index 4faeb0e5..00000000 --- a/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -# Use C++11 -CXXFLAGS += -std=c++11 - -# Default to using system's default version of python -PYTHON_BIN ?= python -PYTHON_CONFIG := $(PYTHON_BIN)-config -PYTHON_INCLUDE ?= $(shell $(PYTHON_CONFIG) --includes) -CXXFLAGS += $(PYTHON_INCLUDE) -LDFLAGS += $(shell $(PYTHON_CONFIG) --libs) - -# Either finds numpy or set -DWITHOUT_NUMPY -CXXFLAGS += $(shell $(PYTHON_BIN) $(CURDIR)/numpy_flags.py) -WITHOUT_NUMPY := $(findstring $(CXXFLAGS), WITHOUT_NUMPY) - -# Examples requiring numpy support to compile -EXAMPLES_NUMPY := surface -EXAMPLES := minimal basic modern animation nonblock xkcd quiver bar fill_inbetween fill update subplot2grid \ - $(if WITHOUT_NUMPY,,$(EXAMPLES_NUMPY)) - -# Prefix every example with 'examples/build/' -EXAMPLE_TARGETS := $(patsubst %,examples/build/%,$(EXAMPLES)) - -.PHONY: examples - -examples: $(EXAMPLE_TARGETS) - -# Assume every *.cpp file is a separate example -$(EXAMPLE_TARGETS): examples/build/%: examples/%.cpp - mkdir -p examples/build - $(CXX) -o $@ $< $(CXXFLAGS) $(LDFLAGS) - -clean: - rm -f ${EXAMPLE_TARGETS} diff --git a/README.md b/README.md index 72bab39f..385f5f4e 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ A more comprehensive example: namespace plt = matplotlibcpp; -int main() +int main() { // Prepare data. int n = 5000; @@ -73,26 +73,26 @@ Alternatively, matplotlib-cpp also supports some C++11-powered syntactic sugar: using namespace std; namespace plt = matplotlibcpp; -int main() -{ +int main() +{ // Prepare data. int n = 5000; // number of data points - vector x(n),y(n); + vector x(n),y(n); for(int i=0; i cd contrib -> WinBuild.cmd -``` -The `WinBuild.cmd` will set up temporal ENV variables and build binaries in (matplotlib root)/examples with the Release configuration. - -3. Find exe files in examples/build/Release -Note: platforms folder is necessary to make qt works. diff --git a/contrib/WinBuild.cmd b/contrib/WinBuild.cmd deleted file mode 100644 index 9dfd627d..00000000 --- a/contrib/WinBuild.cmd +++ /dev/null @@ -1,61 +0,0 @@ -@echo off -@setlocal EnableDelayedExpansion - -REM ------Set Your Environment------------------------------- -if NOT DEFINED MSVC_VERSION set MSVC_VERSION=15 -if NOT DEFINED CMAKE_CONFIG set CMAKE_CONFIG=Release -if NOT DEFINED PYTHONHOME set PYTHONHOME=C:/Users/%username%/Anaconda3 -REM --------------------------------------------------------- - -set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7" -set VALUE_NAME=15.0 - -if "%MSVC_VERSION%"=="14" ( - if "%processor_architecture%" == "AMD64" ( - set CMAKE_GENERATOR=Visual Studio 14 2015 Win64 - ) else ( - set CMAKE_GENERATOR=Visual Studio 14 2015 - ) -) else if "%MSVC_VERSION%"=="12" ( - if "%processor_architecture%" == "AMD64" ( - set CMAKE_GENERATOR=Visual Studio 12 2013 Win64 - ) else ( - set CMAKE_GENERATOR=Visual Studio 12 2013 - ) -) else if "%MSVC_VERSION%"=="15" ( - if "%processor_architecture%" == "AMD64" ( - set CMAKE_GENERATOR=Visual Studio 15 2017 Win64 - ) else ( - set CMAKE_GENERATOR=Visual Studio 15 2017 - ) -) -if "%MSVC_VERSION%"=="15" ( - for /F "usebackq tokens=1,2,*" %%A in (`REG QUERY %KEY_NAME% /v %VALUE_NAME%`) do ( - set batch_file=%%CVC\Auxiliary\Build\vcvarsall.bat - ) -) else ( - set batch_file=!VS%MSVC_VERSION%0COMNTOOLS!..\..\VC\vcvarsall.bat -) -call "%batch_file%" %processor_architecture% - -pushd .. -pushd examples -if NOT EXIST build mkdir build -pushd build - -cmake -G"!CMAKE_GENERATOR!" ^ - -DPYTHONHOME:STRING=%PYTHONHOME%^ - -DCMAKE_BUILD_TYPE:STRING=%CMAKE_CONFIG% ^ - %~dp0 -cmake --build . --config %CMAKE_CONFIG% - -pushd %CMAKE_CONFIG% -if not EXIST platforms mkdir platforms -if EXIST %PYTHONHOME%/Library/plugins/platforms/qwindows.dll ^ -cp %PYTHONHOME%/Library/plugins/platforms/qwindows.dll ./platforms/ -popd -REM move ./%CMAKE_CONFIG% ../ -popd -popd -popd -@endlocal diff --git a/examples/animation.cpp b/examples/animation.cpp index d9794300..e195bb1f 100644 --- a/examples/animation.cpp +++ b/examples/animation.cpp @@ -1,6 +1,6 @@ #define _USE_MATH_DEFINES #include -#include "../matplotlibcpp.h" +#include "matplotlibcpp/matplotlibcpp.h" namespace plt = matplotlibcpp; @@ -9,6 +9,8 @@ int main() int n = 1000; std::vector x, y, z; + plt::init(); // Required for Python 3 (doesn't hurt for Python 2) + for(int i=0; i -#include -#include "../matplotlibcpp.h" +#include "matplotlibcpp/matplotlibcpp.h" namespace plt = matplotlibcpp; int main(int argc, char **argv) { @@ -11,6 +9,8 @@ int main(int argc, char **argv) { test_data.push_back(i); } + plt::init(); // Required for Python 3 (doesn't hurt for Python 2) + plt::bar(test_data); plt::show(); diff --git a/examples/basic.cpp b/examples/basic.cpp index 2dc34c74..290218b6 100644 --- a/examples/basic.cpp +++ b/examples/basic.cpp @@ -1,44 +1,41 @@ #define _USE_MATH_DEFINES #include #include -#include "../matplotlibcpp.h" +#include "matplotlibcpp/matplotlibcpp.h" namespace plt = matplotlibcpp; -int main() +int main() { - // Prepare data. - int n = 5000; - std::vector x(n), y(n), z(n), w(n,2); - for(int i=0; i x(n), y(n), z(n), w(n,2); + for(int i=0; i using namespace std; @@ -16,6 +16,8 @@ int main() { const int a = 1; const double b = 0.2; + plt::init(); // Required for Python 3 (doesn't hurt for Python 2) + for (double dt = 0; dt < 2 * M_PI; dt += M_PI/2.0) { vector x1, y1, x2, y2; for (double th : theta) { diff --git a/examples/fill_between.png b/examples/fill_between.png deleted file mode 100644 index a199423b..00000000 Binary files a/examples/fill_between.png and /dev/null differ diff --git a/examples/fill_inbetween.cpp b/examples/fill_inbetween.cpp index 788d0086..87f1cbde 100644 --- a/examples/fill_inbetween.cpp +++ b/examples/fill_inbetween.cpp @@ -1,5 +1,5 @@ #define _USE_MATH_DEFINES -#include "../matplotlibcpp.h" +#include "matplotlibcpp/matplotlibcpp.h" #include #include @@ -23,6 +23,7 @@ int main() { keywords["color"] = "grey"; keywords["hatch"] = "-"; + plt::init(); // Required for Python 3 (doesn't hurt for Python 2) plt::fill_between(x, y, z, keywords); plt::show(); } diff --git a/examples/fill_inbetween.png b/examples/fill_inbetween.png new file mode 100644 index 00000000..7a63ad7c Binary files /dev/null and b/examples/fill_inbetween.png differ diff --git a/examples/imshow.cpp b/examples/imshow.cpp index b11661e4..c8c1c704 100644 --- a/examples/imshow.cpp +++ b/examples/imshow.cpp @@ -1,7 +1,7 @@ #define _USE_MATH_DEFINES #include #include -#include "../matplotlibcpp.h" +#include "matplotlibcpp/matplotlibcpp.h" using namespace std; namespace plt = matplotlibcpp; @@ -20,6 +20,8 @@ int main() const float* zptr = &(z[0]); const int colors = 1; + plt::init(); // Required for Python 3 (doesn't hurt for Python 2) + plt::title("My matrix"); plt::imshow(zptr, nrows, ncols, colors); diff --git a/examples/minimal.cpp b/examples/minimal.cpp index fbe1e1cd..57a40f42 100644 --- a/examples/minimal.cpp +++ b/examples/minimal.cpp @@ -1,8 +1,9 @@ -#include "../matplotlibcpp.h" +#include "matplotlibcpp/matplotlibcpp.h" namespace plt = matplotlibcpp; int main() { + plt::init(); // Required for Python 3 (doesn't hurt for Python 2) plt::plot({1,3,2,4}); plt::show(); } diff --git a/examples/minimal.png b/examples/minimal.png index 0f6cf373..3f5962e4 100644 Binary files a/examples/minimal.png and b/examples/minimal.png differ diff --git a/examples/modern.cpp b/examples/modern.cpp index a8aa0c75..78d8efba 100644 --- a/examples/modern.cpp +++ b/examples/modern.cpp @@ -1,27 +1,29 @@ #define _USE_MATH_DEFINES #include -#include "../matplotlibcpp.h" +#include "matplotlibcpp/matplotlibcpp.h" using namespace std; namespace plt = matplotlibcpp; -int main() +int main() { // plot(y) - the x-coordinates are implicitly set to [0,1,...,n) - //plt::plot({1,2,3,4}); - + //plt::plot({1,2,3,4}); + // Prepare data for parametric plot. int n = 5000; // number of data points - vector x(n),y(n); + vector x(n),y(n); for(int i=0; i -#include "../matplotlibcpp.h" +#include "matplotlibcpp/matplotlibcpp.h" namespace plt = matplotlibcpp; @@ -19,6 +19,8 @@ int main() z.at(i) = log(i); } + plt::init(); // Required for Python 3 (doesn't hurt for Python 2) + // Plot line from given x and y data. Color is selected automatically. plt::subplot(2,2,1); plt::plot(x, y); @@ -40,6 +42,7 @@ int main() plt::legend(); plt::show(false); + plt::pause(0.1); cout << "matplotlibcpp::show() is working in an non-blocking mode" << endl; getchar(); diff --git a/examples/quiver.cpp b/examples/quiver.cpp index ea3c3eca..68c1b47d 100644 --- a/examples/quiver.cpp +++ b/examples/quiver.cpp @@ -1,4 +1,4 @@ -#include "../matplotlibcpp.h" +#include "matplotlibcpp/matplotlibcpp.h" namespace plt = matplotlibcpp; @@ -15,6 +15,8 @@ int main() } } + plt::init(); // Required for Python 3 (doesn't hurt for Python 2) + plt::quiver(x, y, u, v); plt::show(); -} \ No newline at end of file +} diff --git a/examples/quiver.png b/examples/quiver.png index 9d7be1ee..7f5eef98 100644 Binary files a/examples/quiver.png and b/examples/quiver.png differ diff --git a/examples/subplot.cpp b/examples/subplot.cpp index bee322e0..b8988eac 100644 --- a/examples/subplot.cpp +++ b/examples/subplot.cpp @@ -1,11 +1,11 @@ #define _USE_MATH_DEFINES #include -#include "../matplotlibcpp.h" +#include "matplotlibcpp/matplotlibcpp.h" using namespace std; namespace plt = matplotlibcpp; -int main() +int main() { // Prepare data int n = 500; @@ -16,10 +16,12 @@ int main() z.at(i) = 100.0 / i; } + plt::init(); // Required for Python 3 (doesn't hurt for Python 2) + // Set the "super title" plt::suptitle("My plot"); plt::subplot(1, 2, 1); - plt::plot(x, y, "r-"); + plt::plot(x, y, "r-"); plt::subplot(1, 2, 2); plt::plot(x, z, "k-"); // Add some text to the plot diff --git a/examples/subplot2grid.cpp b/examples/subplot2grid.cpp index f590e51c..e675b49d 100644 --- a/examples/subplot2grid.cpp +++ b/examples/subplot2grid.cpp @@ -1,8 +1,7 @@ #define _USE_MATH_DEFINES #include -#include "../matplotlibcpp.h" +#include "matplotlibcpp/matplotlibcpp.h" -using namespace std; namespace plt = matplotlibcpp; int main() @@ -17,19 +16,21 @@ int main() w.at(i) = sin(2*M_PI*i/1000.0); } + plt::init(); // Required for Python 3 (doesn't hurt for Python 2) + // Set the "super title" plt::suptitle("My plot"); - const long nrows=3, ncols=3; + const long nrows = 3, ncols = 3; long row = 2, col = 2; plt::subplot2grid(nrows, ncols, row, col); - plt::plot(x, w, "g-"); + plt::plot(x, w, "g-"); long spanr = 1, spanc = 2; col = 0; plt::subplot2grid(nrows, ncols, row, col, spanr, spanc); - plt::plot(x, v, "r-"); + plt::plot(x, v, "r-"); spanr = 2, spanc = 3; row = 0, col = 0; @@ -38,7 +39,6 @@ int main() // Add some text to the plot plt::text(100., -0.5, "Hello!"); - // Show plots - plt::show(); + plt::show(); } diff --git a/examples/surface.cpp b/examples/surface.cpp index 4865f061..f643d0e8 100644 --- a/examples/surface.cpp +++ b/examples/surface.cpp @@ -1,4 +1,4 @@ -#include "../matplotlibcpp.h" +#include "matplotlibcpp/matplotlibcpp.h" #include @@ -19,6 +19,8 @@ int main() z.push_back(z_row); } + plt::init(); // Required for Python 3 (doesn't hurt for Python 2) + plt::plot_surface(x, y, z); plt::show(); } diff --git a/examples/update.cpp b/examples/update.cpp index 64f49067..b91d8d84 100644 --- a/examples/update.cpp +++ b/examples/update.cpp @@ -1,7 +1,7 @@ #define _USE_MATH_DEFINES #include -#include "../matplotlibcpp.h" #include +#include "matplotlibcpp/matplotlibcpp.h" namespace plt = matplotlibcpp; @@ -33,6 +33,8 @@ int main() std::vector xt(2), yt(2); + plt::init(); // Required for Python 3 (doesn't hurt for Python 2) + plt::title("Tangent of a sine curve"); plt::xlim(x.front(), x.back()); plt::ylim(-a, a); diff --git a/examples/xkcd.cpp b/examples/xkcd.cpp index fa41cfc4..f32791ce 100644 --- a/examples/xkcd.cpp +++ b/examples/xkcd.cpp @@ -1,7 +1,6 @@ -#define _USE_MATH_DEFINES -#include -#include "../matplotlibcpp.h" +#include "matplotlibcpp/matplotlibcpp.h" #include +#include namespace plt = matplotlibcpp; @@ -14,6 +13,7 @@ int main() { x[i] = sin(2.0 * M_PI * 1.0 * t[i]); } + plt::init(); // Required for Python 3 (doesn't hurt for Python 2) plt::xkcd(); plt::plot(t, x); plt::title("AN ORDINARY SIN WAVE"); diff --git a/examples/xkcd.png b/examples/xkcd.png index c285e3d8..2aed9106 100644 Binary files a/examples/xkcd.png and b/examples/xkcd.png differ diff --git a/matplotlibcpp.h b/include/matplotlibcpp/matplotlibcpp.h similarity index 83% rename from matplotlibcpp.h rename to include/matplotlibcpp/matplotlibcpp.h index 477bf754..b139e10b 100644 --- a/matplotlibcpp.h +++ b/include/matplotlibcpp/matplotlibcpp.h @@ -44,51 +44,9 @@ namespace detail { static std::string s_backend; struct _interpreter { - PyObject *s_python_function_show; - PyObject *s_python_function_close; - PyObject *s_python_function_draw; - PyObject *s_python_function_pause; - PyObject *s_python_function_save; - PyObject *s_python_function_figure; - PyObject *s_python_function_fignum_exists; - PyObject *s_python_function_plot; - PyObject *s_python_function_quiver; - PyObject *s_python_function_semilogx; - PyObject *s_python_function_semilogy; - PyObject *s_python_function_loglog; - PyObject *s_python_function_fill; - PyObject *s_python_function_fill_between; - PyObject *s_python_function_hist; - PyObject *s_python_function_imshow; - PyObject *s_python_function_scatter; - PyObject *s_python_function_subplot; - PyObject *s_python_function_subplot2grid; - PyObject *s_python_function_legend; - PyObject *s_python_function_xlim; - PyObject *s_python_function_ion; - PyObject *s_python_function_ginput; - PyObject *s_python_function_ylim; - PyObject *s_python_function_title; - PyObject *s_python_function_axis; - PyObject *s_python_function_xlabel; - PyObject *s_python_function_ylabel; - PyObject *s_python_function_xticks; - PyObject *s_python_function_yticks; - PyObject *s_python_function_tick_params; - PyObject *s_python_function_grid; - PyObject *s_python_function_clf; - PyObject *s_python_function_errorbar; - PyObject *s_python_function_annotate; - PyObject *s_python_function_tight_layout; + std::unordered_map python_functions; PyObject *s_python_colormap; PyObject *s_python_empty_tuple; - PyObject *s_python_function_stem; - PyObject *s_python_function_xkcd; - PyObject *s_python_function_text; - PyObject *s_python_function_suptitle; - PyObject *s_python_function_bar; - PyObject *s_python_function_subplots_adjust; - /* For now, _interpreter is implemented as a singleton since its currently not possible to have multiple independent embedded python interpreters without patching the python source code @@ -116,20 +74,20 @@ struct _interpreter { private: #ifndef WITHOUT_NUMPY -# if PY_MAJOR_VERSION >= 3 +#if PY_MAJOR_VERSION >= 3 void *import_numpy() { import_array(); // initialize C-API return NULL; } -# else +#else void import_numpy() { import_array(); // initialize C-API } -# endif +#endif #endif _interpreter() { @@ -170,7 +128,7 @@ struct _interpreter { PyObject* pymod = PyImport_Import(pyplotname); Py_DECREF(pyplotname); - if (!pymod) { throw std::runtime_error("Error loading module matplotlib.pyplot!"); } + if(!pymod) { throw std::runtime_error("Error loading module matplotlib.pyplot!"); } s_python_colormap = PyImport_Import(cmname); Py_DECREF(cmname); @@ -178,52 +136,61 @@ struct _interpreter { PyObject* pylabmod = PyImport_Import(pylabname); Py_DECREF(pylabname); - if (!pylabmod) { throw std::runtime_error("Error loading module pylab!"); } - - s_python_function_show = safe_import(pymod, "show"); - s_python_function_close = safe_import(pymod, "close"); - s_python_function_draw = safe_import(pymod, "draw"); - s_python_function_pause = safe_import(pymod, "pause"); - s_python_function_figure = safe_import(pymod, "figure"); - s_python_function_fignum_exists = safe_import(pymod, "fignum_exists"); - s_python_function_plot = safe_import(pymod, "plot"); - s_python_function_quiver = safe_import(pymod, "quiver"); - s_python_function_semilogx = safe_import(pymod, "semilogx"); - s_python_function_semilogy = safe_import(pymod, "semilogy"); - s_python_function_loglog = safe_import(pymod, "loglog"); - s_python_function_fill = safe_import(pymod, "fill"); - s_python_function_fill_between = safe_import(pymod, "fill_between"); - s_python_function_hist = safe_import(pymod,"hist"); - s_python_function_scatter = safe_import(pymod,"scatter"); - s_python_function_subplot = safe_import(pymod, "subplot"); - s_python_function_subplot2grid = safe_import(pymod, "subplot2grid"); - s_python_function_legend = safe_import(pymod, "legend"); - s_python_function_ylim = safe_import(pymod, "ylim"); - s_python_function_title = safe_import(pymod, "title"); - s_python_function_axis = safe_import(pymod, "axis"); - s_python_function_xlabel = safe_import(pymod, "xlabel"); - s_python_function_ylabel = safe_import(pymod, "ylabel"); - s_python_function_xticks = safe_import(pymod, "xticks"); - s_python_function_yticks = safe_import(pymod, "yticks"); - s_python_function_tick_params = safe_import(pymod, "tick_params"); - s_python_function_grid = safe_import(pymod, "grid"); - s_python_function_xlim = safe_import(pymod, "xlim"); - s_python_function_ion = safe_import(pymod, "ion"); - s_python_function_ginput = safe_import(pymod, "ginput"); - s_python_function_save = safe_import(pylabmod, "savefig"); - s_python_function_annotate = safe_import(pymod,"annotate"); - s_python_function_clf = safe_import(pymod, "clf"); - s_python_function_errorbar = safe_import(pymod, "errorbar"); - s_python_function_tight_layout = safe_import(pymod, "tight_layout"); - s_python_function_stem = safe_import(pymod, "stem"); - s_python_function_xkcd = safe_import(pymod, "xkcd"); - s_python_function_text = safe_import(pymod, "text"); - s_python_function_suptitle = safe_import(pymod, "suptitle"); - s_python_function_bar = safe_import(pymod,"bar"); - s_python_function_subplots_adjust = safe_import(pymod,"subplots_adjust"); + if(!pylabmod) { throw std::runtime_error("Error loading module pylab!"); } + + std::vector function_names = { + "show", + "close", + "draw", + "pause", + "figure", + "fignum_exists", + "plot", + "quiver", + "semilogx", + "semilogy", + "loglog", + "fill", + "fill_between", + "hist", + "scatter", + "subplot", + "subplot2grid", + "legend", + "ylim", + "title", + "axis", + "xlabel", + "ylabel", + "xticks", + "yticks", + "tick_params", + "grid", + "xlim", + "ion", + "ginput", + "savefig", + "annotate", + "clf", + "errorbar", + "tight_layout", + "stem", + "xkcd", + "text", + "suptitle", + "bar", + "subplots_adjust", #ifndef WITHOUT_NUMPY - s_python_function_imshow = safe_import(pymod, "imshow"); + "imshow", #endif + }; + + for(size_t i = 0; i < function_names.size(); ++i) + { + const auto &func = function_names[i]; + PyObject *pyobject = safe_import(pymod, func); + python_functions.insert({func, pyobject}); + } s_python_empty_tuple = PyTuple_New(0); } @@ -236,12 +203,20 @@ struct _interpreter { } // end namespace detail // must be called before the first regular call to matplotlib to have any effect -inline void backend(const std::string& name) +void backend(const std::string& name) { detail::s_backend = name; } -inline bool annotate(std::string annotation, double x, double y) +/** + * Needs to be called before using the plotting functions for Python 3 + */ +void init() +{ + Py_Initialize(); +} + +bool annotate(std::string annotation, double x, double y) { PyObject * xy = PyTuple_New(2); PyObject * str = PyString_FromString(annotation.c_str()); @@ -255,7 +230,7 @@ inline bool annotate(std::string annotation, double x, double y) PyObject* args = PyTuple_New(1); PyTuple_SetItem(args, 0, str); - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_annotate, args, kwargs); + PyObject* res = PyObject_Call(detail::_interpreter::get().python_functions["annotate"], args, kwargs); Py_DECREF(args); Py_DECREF(kwargs); @@ -288,13 +263,13 @@ PyObject* get_array(const std::vector& v) if (type == NPY_NOTYPE) { std::vector vd(v.size()); - npy_intp vsize = v.size(); + npy_intp vsize = static_cast(v.size()); std::copy(v.begin(),v.end(),vd.begin()); PyObject* varray = PyArray_SimpleNewFromData(1, &vsize, NPY_DOUBLE, (void*)(vd.data())); return varray; } - npy_intp vsize = v.size(); + npy_intp vsize = static_cast(v.size()); PyObject* varray = PyArray_SimpleNewFromData(1, &vsize, type, (void*)(v.data())); return varray; } @@ -358,7 +333,7 @@ bool plot(const std::vector &x, const std::vector &y, const st PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str())); } - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_plot, args, kwargs); + PyObject* res = PyObject_Call(detail::_interpreter::get().python_functions["plot"], args, kwargs); Py_DECREF(args); Py_DECREF(kwargs); @@ -430,7 +405,7 @@ void plot_surface(const std::vector<::std::vector> &x, PyObject *fig = - PyObject_CallObject(detail::_interpreter::get().s_python_function_figure, + PyObject_CallObject(detail::_interpreter::get().python_functions["figure"], detail::_interpreter::get().s_python_empty_tuple); if (!fig) throw std::runtime_error("Call to figure() failed."); @@ -487,7 +462,7 @@ bool stem(const std::vector &x, const std::vector &y, const st } PyObject* res = PyObject_Call( - detail::_interpreter::get().s_python_function_stem, args, kwargs); + detail::_interpreter::get().python_functions["stem"], args, kwargs); Py_DECREF(args); Py_DECREF(kwargs); @@ -517,7 +492,7 @@ bool fill(const std::vector& x, const std::vector& y, const st PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str())); } - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_fill, args, kwargs); + PyObject* res = PyObject_Call(detail::_interpreter::get().python_functions["fill"], args, kwargs); Py_DECREF(args); Py_DECREF(kwargs); @@ -550,7 +525,7 @@ bool fill_between(const std::vector& x, const std::vector& y1, PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str())); } - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_fill_between, args, kwargs); + PyObject* res = PyObject_Call(detail::_interpreter::get().python_functions["fill_between"], args, kwargs); Py_DECREF(args); Py_DECREF(kwargs); @@ -577,7 +552,7 @@ bool hist(const std::vector& y, long bins=10,std::string color="b", PyTuple_SetItem(plot_args, 0, yarray); - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_hist, plot_args, kwargs); + PyObject* res = PyObject_Call(detail::_interpreter::get().python_functions["hist"], plot_args, kwargs); Py_DECREF(plot_args); @@ -608,7 +583,7 @@ bool hist(const std::vector& y, long bins=10,std::string color="b", PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str())); } - PyObject *res = PyObject_Call(detail::_interpreter::get().s_python_function_imshow, args, kwargs); + PyObject *res = PyObject_Call(detail::_interpreter::get().python_functions["imshow"], args, kwargs); Py_DECREF(args); Py_DECREF(kwargs); if (!res) @@ -681,7 +656,7 @@ bool scatter(const std::vector& x, PyTuple_SetItem(plot_args, 0, xarray); PyTuple_SetItem(plot_args, 1, yarray); - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_scatter, plot_args, kwargs); + PyObject* res = PyObject_Call(detail::_interpreter::get().python_functions["scatter"], plot_args, kwargs); Py_DECREF(plot_args); Py_DECREF(kwargs); @@ -718,8 +693,8 @@ bool bar(const std::vector & x, PyTuple_SetItem(plot_args, 0, xarray); PyTuple_SetItem(plot_args, 1, yarray); - PyObject * res = PyObject_Call( - detail::_interpreter::get().s_python_function_bar, plot_args, kwargs); + PyObject* res = PyObject_Call( + detail::_interpreter::get().python_functions["bar"], plot_args, kwargs); Py_DECREF(plot_args); Py_DECREF(kwargs); @@ -755,7 +730,7 @@ inline bool subplots_adjust(const std::map& keywords = {}) PyObject* plot_args = PyTuple_New(0); - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_subplots_adjust, plot_args, kwargs); + PyObject* res = PyObject_Call(detail::_interpreter::get().python_functions["subplots_adjust"], plot_args, kwargs); Py_DECREF(plot_args); Py_DECREF(kwargs); @@ -779,7 +754,7 @@ bool named_hist(std::string label,const std::vector& y, long bins=10, s PyObject* plot_args = PyTuple_New(1); PyTuple_SetItem(plot_args, 0, yarray); - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_hist, plot_args, kwargs); + PyObject* res = PyObject_Call(detail::_interpreter::get().python_functions["hist"], plot_args, kwargs); Py_DECREF(plot_args); Py_DECREF(kwargs); @@ -803,7 +778,7 @@ bool plot(const std::vector& x, const std::vector& y, const PyTuple_SetItem(plot_args, 1, yarray); PyTuple_SetItem(plot_args, 2, pystring); - PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_plot, plot_args); + PyObject* res = PyObject_CallObject(detail::_interpreter::get().python_functions["plot"], plot_args); Py_DECREF(plot_args); if(res) Py_DECREF(res); @@ -834,8 +809,7 @@ bool quiver(const std::vector& x, const std::vector& y, cons PyDict_SetItemString(kwargs, it->first.c_str(), PyUnicode_FromString(it->second.c_str())); } - PyObject* res = PyObject_Call( - detail::_interpreter::get().s_python_function_quiver, plot_args, kwargs); + PyObject* res = PyObject_Call(detail::_interpreter::get().python_functions["quiver"], plot_args, kwargs); Py_DECREF(kwargs); Py_DECREF(plot_args); @@ -861,7 +835,7 @@ bool stem(const std::vector& x, const std::vector& y, const PyTuple_SetItem(plot_args, 2, pystring); PyObject* res = PyObject_CallObject( - detail::_interpreter::get().s_python_function_stem, plot_args); + detail::_interpreter::get().python_functions["stem"], plot_args); Py_DECREF(plot_args); if (res) @@ -885,7 +859,7 @@ bool semilogx(const std::vector& x, const std::vector& y, co PyTuple_SetItem(plot_args, 1, yarray); PyTuple_SetItem(plot_args, 2, pystring); - PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_semilogx, plot_args); + PyObject* res = PyObject_CallObject(detail::_interpreter::get().python_functions["semilogx"], plot_args); Py_DECREF(plot_args); if(res) Py_DECREF(res); @@ -908,7 +882,7 @@ bool semilogy(const std::vector& x, const std::vector& y, co PyTuple_SetItem(plot_args, 1, yarray); PyTuple_SetItem(plot_args, 2, pystring); - PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_semilogy, plot_args); + PyObject* res = PyObject_CallObject(detail::_interpreter::get().python_functions["semilogy"], plot_args); Py_DECREF(plot_args); if(res) Py_DECREF(res); @@ -931,7 +905,7 @@ bool loglog(const std::vector& x, const std::vector& y, cons PyTuple_SetItem(plot_args, 1, yarray); PyTuple_SetItem(plot_args, 2, pystring); - PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_loglog, plot_args); + PyObject* res = PyObject_CallObject(detail::_interpreter::get().python_functions["loglog"], plot_args); Py_DECREF(plot_args); if(res) Py_DECREF(res); @@ -961,7 +935,7 @@ bool errorbar(const std::vector &x, const std::vector &y, co PyTuple_SetItem(plot_args, 0, xarray); PyTuple_SetItem(plot_args, 1, yarray); - PyObject *res = PyObject_Call(detail::_interpreter::get().s_python_function_errorbar, plot_args, kwargs); + PyObject *res = PyObject_Call(detail::_interpreter::get().python_functions["errorbar"], plot_args, kwargs); Py_DECREF(kwargs); Py_DECREF(plot_args); @@ -974,6 +948,32 @@ bool errorbar(const std::vector &x, const std::vector &y, co return res; } +template +bool scatter(const std::vector& x, const std::vector& y, const std::vector& s, const std::string& format = "") +{ + PyObject* xarray = get_array(x); + PyObject* yarray = get_array(y); + PyObject* sarray = get_array(s); + + PyObject* pystring = PyString_FromString(format.c_str()); + + PyObject* plot_args = PyTuple_New(4); + PyTuple_SetItem(plot_args, 0, xarray); + PyTuple_SetItem(plot_args, 1, yarray); + PyTuple_SetItem(plot_args, 2, sarray); + PyTuple_SetItem(plot_args, 3, pystring); + + PyObject* res = PyObject_CallObject(detail::_interpreter::get().python_functions["scatter"], plot_args); + + Py_DECREF(plot_args); + if(res) Py_DECREF(res); + else + throw std::runtime_error("Call to scatter() failed."); + + return res; +} + + template bool named_plot(const std::string& name, const std::vector& y, const std::string& format = "") { @@ -989,11 +989,11 @@ bool named_plot(const std::string& name, const std::vector& y, const st PyTuple_SetItem(plot_args, 0, yarray); PyTuple_SetItem(plot_args, 1, pystring); - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_plot, plot_args, kwargs); + PyObject* res = PyObject_Call(detail::_interpreter::get().python_functions["plot"], plot_args, kwargs); Py_DECREF(kwargs); Py_DECREF(plot_args); - if (res) Py_DECREF(res); + if(res) Py_DECREF(res); return res; } @@ -1014,11 +1014,11 @@ bool named_plot(const std::string& name, const std::vector& x, const st PyTuple_SetItem(plot_args, 1, yarray); PyTuple_SetItem(plot_args, 2, pystring); - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_plot, plot_args, kwargs); + PyObject* res = PyObject_Call(detail::_interpreter::get().python_functions["plot"], plot_args, kwargs); Py_DECREF(kwargs); Py_DECREF(plot_args); - if (res) Py_DECREF(res); + if(res) Py_DECREF(res); return res; } @@ -1039,11 +1039,11 @@ bool named_semilogx(const std::string& name, const std::vector& x, cons PyTuple_SetItem(plot_args, 1, yarray); PyTuple_SetItem(plot_args, 2, pystring); - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_semilogx, plot_args, kwargs); + PyObject* res = PyObject_Call(detail::_interpreter::get().python_functions["semilogx"], plot_args, kwargs); Py_DECREF(kwargs); Py_DECREF(plot_args); - if (res) Py_DECREF(res); + if(res) Py_DECREF(res); return res; } @@ -1064,11 +1064,11 @@ bool named_semilogy(const std::string& name, const std::vector& x, cons PyTuple_SetItem(plot_args, 1, yarray); PyTuple_SetItem(plot_args, 2, pystring); - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_semilogy, plot_args, kwargs); + PyObject* res = PyObject_Call(detail::_interpreter::get().python_functions["semilogy"], plot_args, kwargs); Py_DECREF(kwargs); Py_DECREF(plot_args); - if (res) Py_DECREF(res); + if(res) Py_DECREF(res); return res; } @@ -1088,11 +1088,41 @@ bool named_loglog(const std::string& name, const std::vector& x, const PyTuple_SetItem(plot_args, 0, xarray); PyTuple_SetItem(plot_args, 1, yarray); PyTuple_SetItem(plot_args, 2, pystring); - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_loglog, plot_args, kwargs); + + PyObject* res = PyObject_Call(detail::_interpreter::get().python_functions["loglog"], plot_args, kwargs); Py_DECREF(kwargs); Py_DECREF(plot_args); - if (res) Py_DECREF(res); + if(res) Py_DECREF(res); + + return res; +} + +template +bool named_scatter(const std::string& name, const std::vector& x, const std::vector& y, const std::vector& s, const std::string& color = "C0") +{ + PyObject* kwargs = PyDict_New(); + PyDict_SetItemString(kwargs, "label", PyString_FromString(name.c_str())); + + PyObject* xarray = get_array(x); + PyObject* yarray = get_array(y); + PyObject* sarray = get_array(s); + + PyObject* colorstring = PyString_FromString(color.c_str()); + + PyObject* plot_args = PyTuple_New(4); + PyTuple_SetItem(plot_args, 0, xarray); + PyTuple_SetItem(plot_args, 1, yarray); + PyTuple_SetItem(plot_args, 2, sarray); + PyTuple_SetItem(plot_args, 3, colorstring); + + PyObject* res = PyObject_Call(detail::_interpreter::get().python_functions["scatter"], plot_args, kwargs); + + Py_DECREF(kwargs); + Py_DECREF(plot_args); + if(res) Py_DECREF(res); + else + throw std::runtime_error("Call to named_scatter() failed."); return res; } @@ -1101,7 +1131,7 @@ template bool plot(const std::vector& y, const std::string& format = "") { std::vector x(y.size()); - for(size_t i=0; i(i); return plot(x,y,format); } @@ -1117,7 +1147,7 @@ template bool stem(const std::vector& y, const std::string& format = "") { std::vector x(y.size()); - for (size_t i = 0; i < x.size(); ++i) x.at(i) = i; + for (size_t i = 0; i < x.size(); ++i) x.at(i) = static_cast(i); return stem(x, y, format); } @@ -1129,7 +1159,7 @@ void text(Numeric x, Numeric y, const std::string& s = "") PyTuple_SetItem(args, 1, PyFloat_FromDouble(y)); PyTuple_SetItem(args, 2, PyString_FromString(s.c_str())); - PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_text, args); + PyObject* res = PyObject_CallObject(detail::_interpreter::get().python_functions["text"], args); if(!res) throw std::runtime_error("Call to text() failed."); Py_DECREF(args); @@ -1141,7 +1171,7 @@ inline long figure(long number = -1) { PyObject *res; if (number == -1) - res = PyObject_CallObject(detail::_interpreter::get().s_python_function_figure, detail::_interpreter::get().s_python_empty_tuple); + res = PyObject_CallObject(detail::_interpreter::get().python_functions["figure"], detail::_interpreter::get().s_python_empty_tuple); else { assert(number > 0); @@ -1150,7 +1180,7 @@ inline long figure(long number = -1) PyObject *args = PyTuple_New(1); PyTuple_SetItem(args, 0, PyLong_FromLong(number)); - res = PyObject_CallObject(detail::_interpreter::get().s_python_function_figure, args); + res = PyObject_CallObject(detail::_interpreter::get().python_functions["figure"], args); Py_DECREF(args); } @@ -1173,7 +1203,7 @@ inline bool fignum_exists(long number) PyObject *args = PyTuple_New(1); PyTuple_SetItem(args, 0, PyLong_FromLong(number)); - PyObject *res = PyObject_CallObject(detail::_interpreter::get().s_python_function_fignum_exists, args); + PyObject *res = PyObject_CallObject(detail::_interpreter::get().python_functions["fignum_exists"], args); if(!res) throw std::runtime_error("Call to fignum_exists() failed."); bool ret = PyObject_IsTrue(res); @@ -1197,8 +1227,7 @@ inline void figure_size(size_t w, size_t h) PyDict_SetItemString(kwargs, "figsize", size); PyDict_SetItemString(kwargs, "dpi", PyLong_FromSize_t(dpi)); - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_figure, - detail::_interpreter::get().s_python_empty_tuple, kwargs); + PyObject* res = PyObject_Call(detail::_interpreter::get().python_functions["figure"], detail::_interpreter::get().s_python_empty_tuple, kwargs); Py_DECREF(kwargs); @@ -1208,7 +1237,7 @@ inline void figure_size(size_t w, size_t h) inline void legend() { - PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_legend, detail::_interpreter::get().s_python_empty_tuple); + PyObject* res = PyObject_CallObject(detail::_interpreter::get().python_functions["legend"], detail::_interpreter::get().s_python_empty_tuple); if(!res) throw std::runtime_error("Call to legend() failed."); Py_DECREF(res); @@ -1224,7 +1253,7 @@ void ylim(Numeric left, Numeric right) PyObject* args = PyTuple_New(1); PyTuple_SetItem(args, 0, list); - PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_ylim, args); + PyObject* res = PyObject_CallObject(detail::_interpreter::get().python_functions["ylim"], args); if(!res) throw std::runtime_error("Call to ylim() failed."); Py_DECREF(args); @@ -1241,7 +1270,7 @@ void xlim(Numeric left, Numeric right) PyObject* args = PyTuple_New(1); PyTuple_SetItem(args, 0, list); - PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_xlim, args); + PyObject* res = PyObject_CallObject(detail::_interpreter::get().python_functions["xlim"], args); if(!res) throw std::runtime_error("Call to xlim() failed."); Py_DECREF(args); @@ -1252,7 +1281,10 @@ void xlim(Numeric left, Numeric right) inline double* xlim() { PyObject* args = PyTuple_New(0); - PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_xlim, args); + + PyObject* res = PyObject_CallObject(detail::_interpreter::get().python_functions["xlim"], args); + if(!res) throw std::runtime_error("Call to xlim() failed."); + PyObject* left = PyTuple_GetItem(res,0); PyObject* right = PyTuple_GetItem(res,1); @@ -1260,8 +1292,6 @@ inline double* xlim() arr[0] = PyFloat_AsDouble(left); arr[1] = PyFloat_AsDouble(right); - if(!res) throw std::runtime_error("Call to xlim() failed."); - Py_DECREF(res); return arr; } @@ -1270,7 +1300,10 @@ inline double* xlim() inline double* ylim() { PyObject* args = PyTuple_New(0); - PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_ylim, args); + + PyObject* res = PyObject_CallObject(detail::_interpreter::get().python_functions["ylim"], args); + if(!res) throw std::runtime_error("Call to ylim() failed."); + PyObject* left = PyTuple_GetItem(res,0); PyObject* right = PyTuple_GetItem(res,1); @@ -1278,8 +1311,6 @@ inline double* ylim() arr[0] = PyFloat_AsDouble(left); arr[1] = PyFloat_AsDouble(right); - if(!res) throw std::runtime_error("Call to ylim() failed."); - Py_DECREF(res); return arr; } @@ -1316,7 +1347,7 @@ inline void xticks(const std::vector &ticks, const std::vectorfirst.c_str(), PyString_FromString(it->second.c_str())); } - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_xticks, args, kwargs); + PyObject* res = PyObject_Call(detail::_interpreter::get().python_functions["xticks"], args, kwargs); Py_DECREF(args); Py_DECREF(kwargs); @@ -1363,7 +1394,7 @@ inline void yticks(const std::vector &ticks, const std::vectorfirst.c_str(), PyString_FromString(it->second.c_str())); } - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_yticks, args, kwargs); + PyObject* res = PyObject_Call(detail::_interpreter::get().python_functions["yticks"], args, kwargs); Py_DECREF(args); Py_DECREF(kwargs); @@ -1384,21 +1415,21 @@ inline void tick_params(const std::map& keywords, cons PyObject* args; args = PyTuple_New(1); PyTuple_SetItem(args, 0, PyString_FromString(axis.c_str())); - + // construct keyword args PyObject* kwargs = PyDict_New(); for (std::map::const_iterator it = keywords.begin(); it != keywords.end(); ++it) { PyDict_SetItemString(kwargs, it->first.c_str(), PyString_FromString(it->second.c_str())); } - - - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_tick_params, args, kwargs); - + + + PyObject* res = PyObject_Call(detail::_interpreter::get().python_functions["tick_params"], args, kwargs); + Py_DECREF(args); Py_DECREF(kwargs); if (!res) throw std::runtime_error("Call to tick_params() failed"); - + Py_DECREF(res); } @@ -1406,11 +1437,11 @@ inline void subplot(long nrows, long ncols, long plot_number) { // construct positional args PyObject* args = PyTuple_New(3); - PyTuple_SetItem(args, 0, PyFloat_FromDouble(nrows)); - PyTuple_SetItem(args, 1, PyFloat_FromDouble(ncols)); - PyTuple_SetItem(args, 2, PyFloat_FromDouble(plot_number)); + PyTuple_SetItem(args, 0, PyLong_FromLong(nrows)); + PyTuple_SetItem(args, 1, PyLong_FromLong(ncols)); + PyTuple_SetItem(args, 2, PyLong_FromLong(plot_number)); - PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_subplot, args); + PyObject* res = PyObject_CallObject(detail::_interpreter::get().python_functions["subplot"], args); if(!res) throw std::runtime_error("Call to subplot() failed."); Py_DECREF(args); @@ -1433,7 +1464,7 @@ inline void subplot2grid(long nrows, long ncols, long rowid=0, long colid=0, lon PyTuple_SetItem(args, 2, PyLong_FromLong(rowspan)); PyTuple_SetItem(args, 3, PyLong_FromLong(colspan)); - PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_subplot2grid, args); + PyObject* res = PyObject_CallObject(detail::_interpreter::get().python_functions["subplot2grid"], args); if(!res) throw std::runtime_error("Call to subplot2grid() failed."); Py_DECREF(shape); @@ -1453,7 +1484,7 @@ inline void title(const std::string &titlestr, const std::mapfirst.c_str(), PyUnicode_FromString(it->second.c_str())); } - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_title, args, kwargs); + PyObject* res = PyObject_Call(detail::_interpreter::get().python_functions["title"], args, kwargs); if(!res) throw std::runtime_error("Call to title() failed."); Py_DECREF(args); @@ -1472,7 +1503,7 @@ inline void suptitle(const std::string &suptitlestr, const std::mapfirst.c_str(), PyUnicode_FromString(it->second.c_str())); } - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_suptitle, args, kwargs); + PyObject* res = PyObject_Call(detail::_interpreter::get().python_functions["suptitle"], args, kwargs); if(!res) throw std::runtime_error("Call to suptitle() failed."); Py_DECREF(args); @@ -1486,7 +1517,7 @@ inline void axis(const std::string &axisstr) PyObject* args = PyTuple_New(1); PyTuple_SetItem(args, 0, str); - PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_axis, args); + PyObject* res = PyObject_CallObject(detail::_interpreter::get().python_functions["axis"], args); if(!res) throw std::runtime_error("Call to title() failed."); Py_DECREF(args); @@ -1504,7 +1535,7 @@ inline void xlabel(const std::string &str, const std::mapfirst.c_str(), PyUnicode_FromString(it->second.c_str())); } - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_xlabel, args, kwargs); + PyObject* res = PyObject_Call(detail::_interpreter::get().python_functions["xlabel"], args, kwargs); if(!res) throw std::runtime_error("Call to xlabel() failed."); Py_DECREF(args); @@ -1523,7 +1554,7 @@ inline void ylabel(const std::string &str, const std::mapfirst.c_str(), PyUnicode_FromString(it->second.c_str())); } - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_ylabel, args, kwargs); + PyObject* res = PyObject_Call(detail::_interpreter::get().python_functions["ylabel"], args, kwargs); if(!res) throw std::runtime_error("Call to ylabel() failed."); Py_DECREF(args); @@ -1539,7 +1570,7 @@ inline void grid(bool flag) PyObject* args = PyTuple_New(1); PyTuple_SetItem(args, 0, pyflag); - PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_grid, args); + PyObject* res = PyObject_CallObject(detail::_interpreter::get().python_functions["grid"], args); if(!res) throw std::runtime_error("Call to grid() failed."); Py_DECREF(args); @@ -1552,15 +1583,15 @@ inline void show(const bool block = true) if(block) { res = PyObject_CallObject( - detail::_interpreter::get().s_python_function_show, - detail::_interpreter::get().s_python_empty_tuple); + detail::_interpreter::get().python_functions["show"], + detail::_interpreter::get().s_python_empty_tuple); } else { PyObject *kwargs = PyDict_New(); PyDict_SetItemString(kwargs, "block", Py_False); - res = PyObject_Call( detail::_interpreter::get().s_python_function_show, detail::_interpreter::get().s_python_empty_tuple, kwargs); - Py_DECREF(kwargs); + res = PyObject_Call( detail::_interpreter::get().python_functions["show"], detail::_interpreter::get().s_python_empty_tuple, kwargs); + Py_DECREF(kwargs); } @@ -1572,8 +1603,8 @@ inline void show(const bool block = true) inline void close() { PyObject* res = PyObject_CallObject( - detail::_interpreter::get().s_python_function_close, - detail::_interpreter::get().s_python_empty_tuple); + detail::_interpreter::get().python_functions["close"], + detail::_interpreter::get().s_python_empty_tuple); if (!res) throw std::runtime_error("Call to close() failed."); @@ -1584,9 +1615,8 @@ inline void xkcd() { PyObject* res; PyObject *kwargs = PyDict_New(); - res = PyObject_Call(detail::_interpreter::get().s_python_function_xkcd, - detail::_interpreter::get().s_python_empty_tuple, kwargs); - + res = PyObject_Call(detail::_interpreter::get().python_functions["xkcd"], + detail::_interpreter::get().s_python_empty_tuple, kwargs); Py_DECREF(kwargs); if (!res) @@ -1598,7 +1628,7 @@ inline void xkcd() { inline void draw() { PyObject* res = PyObject_CallObject( - detail::_interpreter::get().s_python_function_draw, + detail::_interpreter::get().python_functions["draw"], detail::_interpreter::get().s_python_empty_tuple); if (!res) throw std::runtime_error("Call to draw() failed."); @@ -1607,12 +1637,12 @@ inline void draw() } template -inline void pause(Numeric interval) +void pause(Numeric interval) { PyObject* args = PyTuple_New(1); PyTuple_SetItem(args, 0, PyFloat_FromDouble(interval)); - PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_pause, args); + PyObject* res = PyObject_CallObject(detail::_interpreter::get().python_functions["pause"], args); if(!res) throw std::runtime_error("Call to pause() failed."); Py_DECREF(args); @@ -1626,7 +1656,7 @@ inline void save(const std::string& filename) PyObject* args = PyTuple_New(1); PyTuple_SetItem(args, 0, pyfilename); - PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_save, args); + PyObject* res = PyObject_CallObject(detail::_interpreter::get().python_functions["savefig"], args); if (!res) throw std::runtime_error("Call to save() failed."); Py_DECREF(args); @@ -1635,7 +1665,7 @@ inline void save(const std::string& filename) inline void clf() { PyObject *res = PyObject_CallObject( - detail::_interpreter::get().s_python_function_clf, + detail::_interpreter::get().python_functions["clf"], detail::_interpreter::get().s_python_empty_tuple); if (!res) throw std::runtime_error("Call to clf() failed."); @@ -1643,9 +1673,9 @@ inline void clf() { Py_DECREF(res); } - inline void ion() { +inline void ion() { PyObject *res = PyObject_CallObject( - detail::_interpreter::get().s_python_function_ion, + detail::_interpreter::get().python_functions["ion"], detail::_interpreter::get().s_python_empty_tuple); if (!res) throw std::runtime_error("Call to ion() failed."); @@ -1666,7 +1696,7 @@ inline std::vector> ginput(const int numClicks = 1, const } PyObject* res = PyObject_Call( - detail::_interpreter::get().s_python_function_ginput, args, kwargs); + detail::_interpreter::get().python_functions["ginput"], args, kwargs); Py_DECREF(kwargs); Py_DECREF(args); @@ -1690,7 +1720,7 @@ inline std::vector> ginput(const int numClicks = 1, const // Actually, is there any reason not to call this automatically for every plot? inline void tight_layout() { PyObject *res = PyObject_CallObject( - detail::_interpreter::get().s_python_function_tight_layout, + detail::_interpreter::get().python_functions["tight_layout"], detail::_interpreter::get().s_python_empty_tuple); if (!res) throw std::runtime_error("Call to tight_layout() failed."); @@ -1774,7 +1804,7 @@ struct plot_impl PyTuple_SetItem(plot_args, 1, ylist); PyTuple_SetItem(plot_args, 2, pystring); - PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_plot, plot_args); + PyObject* res = PyObject_CallObject(detail::_interpreter::get().python_functions["plot"], plot_args); Py_DECREF(plot_args); if(res) Py_DECREF(res); @@ -1815,15 +1845,15 @@ bool plot(const A& a, const B& b, const std::string& format, Args... args) * This group of plot() functions is needed to support initializer lists, i.e. calling * plot( {1,2,3,4} ) */ -inline bool plot(const std::vector& x, const std::vector& y, const std::string& format = "") { +bool plot(const std::vector& x, const std::vector& y, const std::string& format = "") { return plot(x,y,format); } -inline bool plot(const std::vector& y, const std::string& format = "") { +bool plot(const std::vector& y, const std::string& format = "") { return plot(y,format); } -inline bool plot(const std::vector& x, const std::vector& y, const std::map& keywords) { +bool plot(const std::vector& x, const std::vector& y, const std::map& keywords) { return plot(x,y,keywords); } @@ -1854,7 +1884,7 @@ class Plot PyTuple_SetItem(plot_args, 1, yarray); PyTuple_SetItem(plot_args, 2, pystring); - PyObject* res = PyObject_Call(detail::_interpreter::get().s_python_function_plot, plot_args, kwargs); + PyObject* res = PyObject_Call(detail::_interpreter::get().python_functions["plot"], plot_args, kwargs); Py_DECREF(kwargs); Py_DECREF(plot_args); diff --git a/numpy_flags.py b/numpy_flags.py deleted file mode 100644 index 56fd95cc..00000000 --- a/numpy_flags.py +++ /dev/null @@ -1,12 +0,0 @@ -from os import path - -try: - from numpy import __file__ as numpyloc - - # Get numpy directory - numpy_dir = path.dirname(numpyloc) - - # Print the result of joining this to core and include - print("-I" + path.join(numpy_dir, "core", "include")) -except: - print("-DWITHOUT_NUMPY") diff --git a/package.xml b/package.xml new file mode 100644 index 00000000..65932beb --- /dev/null +++ b/package.xml @@ -0,0 +1,19 @@ + + + matplotlibcpp + 0.1.0 + The matplotlibcpp package + + Kartik Mohta + + Benno Evers + + MIT + + catkin + + + cmake + + +