diff --git a/CMakeLists.txt b/CMakeLists.txt index 555a967..9794674 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,27 +3,25 @@ cmake_minimum_required(VERSION 3.12) project( "matplotlibcpp17" VERSION 0.0.0 - DESCRIPTION "A C++ header-only plotting library based on pybind11 and matplotlib, featuring more flexibility than matplotlibcpp" - HOMEPAGE_URL "https://soblin.github.io/matplotlibcpp17/" - ) + DESCRIPTION + "A C++ header-only plotting library based on pybind11 and matplotlib, featuring more flexibility than matplotlibcpp" + HOMEPAGE_URL "https://soblin.github.io/matplotlibcpp17/") -find_package(Python3 COMPONENTS Interpreter Development REQUIRED) +find_package( + Python3 + COMPONENTS Interpreter Development + REQUIRED) find_package(pybind11 2.4.3 REQUIRED) - # check matplotlib minor version execute_process( - COMMAND - ${Python3_EXECUTABLE} "-c" - "import matplotlib; + COMMAND ${Python3_EXECUTABLE} "-c" "import matplotlib; print(str(matplotlib.__version__), end='')" RESULT_VARIABLE MATPLOTLIB_VERSION_CHECKING - OUTPUT_VARIABLE MATPLOTLIB_VERSION - ) + OUTPUT_VARIABLE MATPLOTLIB_VERSION) if(NOT MATPLOTLIB_VERSION_CHECKING MATCHES 0) - message(FATAL_ERROR - "Could not check matplotlib.__version__") + message(FATAL_ERROR "Could not check matplotlib.__version__") endif() message(STATUS "Detected matplotlib version is ${MATPLOTLIB_VERSION}") if(${MATPLOTLIB_VERSION} VERSION_LESS 3.4) @@ -34,7 +32,6 @@ else() set(MATPLOTLIB_MINOR_VER_GTE_4 1) endif() - # gallery if(NOT DEFINED USE_GUI) set(USE_GUI 1) @@ -58,18 +55,21 @@ set(matplotlibcpp17_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/include") function(add_demo name path) add_executable(${name} ${path}) - target_include_directories(${name} PUBLIC - ${Python3_INCLUDE_DIRS} - ${matplotlibcpp17_INCLUDE_DIRS} - ) + target_include_directories(${name} PUBLIC ${Python3_INCLUDE_DIRS} + ${matplotlibcpp17_INCLUDE_DIRS}) target_link_libraries(${name} ${Python3_LIBRARIES} pybind11::embed xtensor) endfunction() if(${ADD_DEMO}) - find_package(Python3 COMPONENTS NumPy REQUIRED) + find_package( + Python3 + COMPONENTS NumPy + REQUIRED) find_package(xtensor 0.24.0 REQUIRED) set(CMAKE_CXX_STANDARD 17) - set(CMAKE_CXX_FLAGS "-Wall -g -DUSE_GUI=${USE_GUI} -DMATPLOTLIB_MINOR_VER_GTE_4=${MATPLOTLIB_MINOR_VER_GTE_4}") + set(CMAKE_CXX_FLAGS + "-Wall -g -DUSE_GUI=${USE_GUI} -DMATPLOTLIB_MINOR_VER_GTE_4=${MATPLOTLIB_MINOR_VER_GTE_4}" + ) add_subdirectory(gallery/lines_bars_and_markers) add_subdirectory(gallery/subplots_axes_and_figures) add_subdirectory(gallery/statistics) @@ -79,7 +79,6 @@ if(${ADD_DEMO}) add_subdirectory(gallery/mplot3d) endif() - # test enable_testing() if(NOT DEFINED DO_TEST) @@ -89,63 +88,51 @@ if(${DO_TEST}) add_subdirectory(tests) endif() - -# install -## https://dominikberner.ch/cmake-interface-lib/ +# install https://dominikberner.ch/cmake-interface-lib/ include(GNUInstallDirs) add_library(${PROJECT_NAME} INTERFACE) -target_include_directories(${PROJECT_NAME} - INTERFACE - $ - $ - ) +target_include_directories( + ${PROJECT_NAME} + INTERFACE $ + $) target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_17) -install(TARGETS ${PROJECT_NAME} +install( + TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}_Targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ) + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) include(CMakePackageConfigHelpers) -write_basic_package_version_file("${PROJECT_NAME}ConfigVersion.cmake" +write_basic_package_version_file( + "${PROJECT_NAME}ConfigVersion.cmake" VERSION ${PROJECT_VERSION} - COMPATIBILITY SameMajorVersion - ) + COMPATIBILITY SameMajorVersion) configure_package_config_file( "${PROJECT_SOURCE_DIR}/cmake/${PROJECT_NAME}Config.cmake.in" "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" - INSTALL_DESTINATION - ${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME} - ) + INSTALL_DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}) # to /share/cmake/matplotlibcpp17 -install(FILES - "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" - "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME} - ) +install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" + "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}) # to /share/cmake/matplotlibcpp17 -install(EXPORT ${PROJECT_NAME}_Targets +install( + EXPORT ${PROJECT_NAME}_Targets FILE ${PROJECT_NAME}Targets.cmake NAMESPACE ${PROJECT_NAME}:: - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME} - ) + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}) # to /include/matplotlibcpp17 install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/${PROJECT_NAME} - DESTINATION include - ) + DESTINATION include) set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE") # create .deb include("${PROJECT_SOURCE_DIR}/cmake/package.cmake") -# uninstall target -## actually it's just `xargs rm < install_manifest.txt` -## https://gitlab.kitware.com/cmake/community/-/wikis/FAQ#can-i-do-make-uninstall-with-cmake +# uninstall target. actually it's just `xargs rm < install_manifest.txt` +# https://gitlab.kitware.com/cmake/community/-/wikis/FAQ#can-i-do-make-uninstall-with-cmake if(NOT TARGET uninstall) - configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/uninstall.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake" - IMMEDIATE @ONLY - ) - add_custom_target(uninstall - COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake - ) + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake" IMMEDIATE @ONLY) + add_custom_target( + uninstall COMMAND ${CMAKE_COMMAND} -P + ${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake) endif() diff --git a/gallery/mplot3d/CMakeLists.txt b/gallery/mplot3d/CMakeLists.txt index c2cc39f..c9583c4 100644 --- a/gallery/mplot3d/CMakeLists.txt +++ b/gallery/mplot3d/CMakeLists.txt @@ -3,14 +3,16 @@ add_demo(lorenz_attractor lorenz_attractor.cpp) add_demo(contour3d contour3d.cpp) add_demo(subplot3d subplot3d.cpp) add_demo(errorbar3d errorbar3d.cpp) +add_demo(surface3d surface3d) add_custom_target(mplot3d - DEPENDS lines3d lorenz_attractor contour3d subplot3d errorbar3d + DEPENDS lines3d lorenz_attractor contour3d subplot3d errorbar3d surface3d COMMAND lines3d COMMAND lorenz_attractor COMMAND contour3d COMMAND subplot3d COMMAND errorbar3d + COMMAND surface3d COMMENT "running mplot3d" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/../images" ) diff --git a/gallery/mplot3d/subplot3d.cpp b/gallery/mplot3d/subplot3d.cpp index a7587dd..93d6d76 100644 --- a/gallery/mplot3d/subplot3d.cpp +++ b/gallery/mplot3d/subplot3d.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -79,8 +80,11 @@ int main() { auto Y_ = py::array(py::cast(std::move(Y))); auto Z_ = py::array(py::cast(std::move(Z))); auto surf = ax.plot_surface( - Args(X_, Y_, Z_), Kwargs("rstride"_a = 1, "cstride"_a = 1, - "linewidth"_a = 0, "antialiased"_a = false)); + Args(X_, Y_, Z_), + Kwargs("rstride"_a = 1, "cstride"_a = 1, "linewidth"_a = 0, + "antialiased"_a = false, "cmap"_a = cm::coolwarm())); + ax.set_zlim(Args(-1.01, 1.01)); + fig.colorbar(Args(surf), Kwargs("shrink"_a = 0.5, "aspect"_a = 10)); } { auto ax = fig.add_subplot(Args(1, 2, 2), Kwargs("projection"_a = "3d")); diff --git a/gallery/mplot3d/surface3d.cpp b/gallery/mplot3d/surface3d.cpp new file mode 100644 index 0000000..1454f2e --- /dev/null +++ b/gallery/mplot3d/surface3d.cpp @@ -0,0 +1,56 @@ +// example from https://matplotlib.org/stable/gallery/mplot3d/surface3d.html + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +namespace py = pybind11; +using namespace py::literals; +using namespace std; +using namespace matplotlibcpp17; + +using mesh2D = vector>; + +int main() { + py::scoped_interpreter guard{}; + auto plt = matplotlibcpp17::pyplot::import(); + auto [fig, ax] = + plt.subplots(Kwargs("subplot_kw"_a = py::dict("projection"_a = "3d"))); + + auto xs = xt::arange(-5.0, 5.0, 0.25); + auto [X0, Y0] = xt::meshgrid(xs, xs); + auto R0 = xt::sqrt(xt::pow(X0, 2) + xt::pow(Y0, 2)); + auto Z0 = xt::sin(R0); + // to vector + const int sz = xs.shape()[0]; + mesh2D X(sz), Y(sz), Z(sz); + for (int i = 0; i < sz; ++i) { + X[i].resize(sz); + Y[i].resize(sz); + Z[i].resize(sz); + for (int j = 0; j < sz; ++j) { + X[i][j] = X0(i, j); + Y[i][j] = Y0(i, j); + Z[i][j] = Z0(i, j); + } + } + // to numpy array (vector is converted to list of list) + auto X_ = py::array(py::cast(std::move(X))); + auto Y_ = py::array(py::cast(std::move(Y))); + auto Z_ = py::array(py::cast(std::move(Z))); + auto surf = ax.plot_surface(Args(X_, Y_, Z_), + Kwargs("rstride"_a = 1, "cstride"_a = 1, + "linewidth"_a = 0, "antialiased"_a = false, + "cmap"_a = cm::coolwarm())); + ax.set_zlim(Args(-1.01, 1.01)); + fig.colorbar(Args(surf), Kwargs("shrink"_a = 0.5, "aspect"_a = 5)); + plt.show(); +} diff --git a/include/matplotlibcpp17/axes.h b/include/matplotlibcpp17/axes.h index df89efe..024e869 100644 --- a/include/matplotlibcpp17/axes.h +++ b/include/matplotlibcpp17/axes.h @@ -195,6 +195,10 @@ struct DECL_STRUCT_ATTR Axes : public BaseWrapper { pybind11::object set_zlabel(const pybind11::tuple &args = pybind11::tuple(), const pybind11::dict &kwargs = pybind11::dict()); + // set_zlim + pybind11::object set_zlim(const pybind11::tuple &args = pybind11::tuple(), + const pybind11::dict &kwargs = pybind11::dict()); + // text pybind11::object text(const pybind11::tuple &args = pybind11::tuple(), const pybind11::dict &kwargs = pybind11::dict()); @@ -254,6 +258,7 @@ struct DECL_STRUCT_ATTR Axes : public BaseWrapper { LOAD_FUNC_ATTR(set_ylabel, self); LOAD_FUNC_ATTR(set_ylim, self); LOAD_FUNC_ATTR(set_yticks, self); + LOAD_FUNC_ATTR(set_zlim, self); LOAD_FUNC_ATTR(text, self); LOAD_FUNC_ATTR(tick_params, self); } @@ -295,6 +300,7 @@ struct DECL_STRUCT_ATTR Axes : public BaseWrapper { pybind11::object set_ylim_attr; pybind11::object set_yticks_attr; pybind11::object set_zlabel_attr; + pybind11::object set_zlim_attr; pybind11::object text_attr; pybind11::object tick_params_attr; bool projection_3d; @@ -597,6 +603,13 @@ pybind11::object Axes::set_zlabel(const pybind11::tuple &args, return ret; } +// set_zlim +pybind11::object Axes::set_zlim(const pybind11::tuple &args, + const pybind11::dict &kwargs) { + pybind11::object ret = set_zlim_attr(*args, **kwargs); + return ret; +} + // text pybind11::object Axes::text(const pybind11::tuple &args, const pybind11::dict &kwargs) { diff --git a/include/matplotlibcpp17/cm.h b/include/matplotlibcpp17/cm.h new file mode 100644 index 0000000..02e6e61 --- /dev/null +++ b/include/matplotlibcpp17/cm.h @@ -0,0 +1,21 @@ +/** + * @file cm.h + * @brief corresponding header for matplotlib.cm + **/ + +#ifndef MATPLOTLIBCPP17_CM_H +#define MATPLOTLIBCPP17_CM_H + +#include + +namespace matplotlibcpp17::cm { + +pybind11::object coolwarm() { + pybind11::object ret = + pybind11::module::import("matplotlib.cm").attr("coolwarm"); + return ret; +} + +} // namespace matplotlibcpp17::cm + +#endif /* MATPLOTLIBCPP17_CM_H */