diff --git a/CMakeLists.txt b/CMakeLists.txt index 38c9ae0..71ce42b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,12 +18,12 @@ set (CMAKE_EXPORT_COMPILE_COMMANDS 1) ## Compile and create a library. STATIC is default unless BUILD_SHARED_LIBS ## is on. -add_library (cpp_plot - src/cpp_plot.cc +add_library (cpp_mpl + src/cpp_mpl.cc src/RequestSink.cc src/ipython_protocol.cc) -set (EXTRA_LIBS ${EXTRA_LIBS} cpp_plot) +set (EXTRA_LIBS ${EXTRA_LIBS} cpp_mpl) ## Libraries to link with target_link_libraries (${EXAMPLE_BIN} diff --git a/README.md b/README.md index e307881..973b6f9 100644 --- a/README.md +++ b/README.md @@ -4,13 +4,13 @@ * [Usage](#usage) * [Prereqs](#prereqs) * [Building](#building) -* [Example](#example) +* [Running the Example](#running-the-example) # About -An easy-to-use library for simple plotting from C++ via a ZeroMQ bridge to -an [IPython](http://ipython.org/) kernel. +An easy-to-use **C++11** library for simple plotting from C++ via a ZeroMQ +bridge to an [IPython](http://ipython.org/) kernel. It provides the ability to send [NumPy](http://www.numpy.org/) array compatible data to an IPython kernel session as well as execute arbitrary @@ -43,29 +43,39 @@ Here we create some 1D data and plot it. The numpy.array "MyData" will be available for working with in the IPython session, even after the C++ program finishes. +All library code lives in the cppmpl namespace. + ```c++ -CppMatplotlib mpl{"/path/to/kernel-NNN.json"}; -mpl.Connect(); - -// Create a nice curve -std::vector raw_data; -double x = 0.0; -while (x < 3.14159 * 4) { - raw_data.push_back(std::sin(x)); - x += 0.05; +#include "cpp_mpl.hpp" + +int main() { + // ... + + cppmpl::CppMatplotlib mpl{"/path/to/kernel-NNN.json"}; + mpl.Connect(); + + // Create a nice curve + std::vector raw_data; + double x = 0.0; + while (x < 3.14159 * 4) { + raw_data.push_back(std::sin(x)); + x += 0.05; + } + + // Send it to IPython for plotting + cppmpl::NumpyArray data("MyData", raw_data); + mpl.SendData(data); + mpl.RunCode("plot(MyData)\n" + "title('f(x) = sin(x)')\n" + "xlabel('x')\n" + "ylabel('f(x)')\n"); + + // NOTE: if you want to store the python in an external file, use the + // convenience function LoadFile("my_code.py"), as in, + // mpl.RunCode(cppmpl::LoadFile("plotting_code.py")); + + // ... } - -// Send it to IPython for plotting -NumpyArray data("MyData", raw_data); -mpl.SendData(data); -mpl.RunCode("plot(MyData)\n" - "title('f(x) = sin(x)')\n" - "xlabel('x')\n" - "ylabel('f(x)')\n"); - -// NOTE: if you want to store the python in an external file, use the -// convenience function LoadFile("my_code.py"), as in, -// mpl.RunCode(LoadFile("plotting_code.py")); ``` And the result is ![Screenshot](screenshot.png?raw=true) @@ -92,6 +102,17 @@ In [84]: print MyData[9] [ 1.73986214] ``` +## Compiling / Linking + +When linking against cpp_plot.{a,so}, you also need to link against +libzmq, libjsoncpp, libuuid, and libcripto: + +``` +$ g++ my_prog.cc -std=c++11 /path/to/libcpp_plot.a -ljsoncpp -lzmq -luuid -lcrypto +``` + +Or just modify CMakeFiles.txt... + # Prereqs diff --git a/src/RequestSink.cc b/src/RequestSink.cc index d3f343a..17b4fbc 100644 --- a/src/RequestSink.cc +++ b/src/RequestSink.cc @@ -8,6 +8,8 @@ #include "RequestSink.hpp" +namespace cppmpl { + RequestSink::RequestSink(const std::string &url) : context_{1}, socket_{context_, ZMQ_REQ}, @@ -42,3 +44,4 @@ bool RequestSink::Connect(void) { return true; } +} diff --git a/src/RequestSink.hpp b/src/RequestSink.hpp index 4d20ba7..ad53f65 100644 --- a/src/RequestSink.hpp +++ b/src/RequestSink.hpp @@ -11,6 +11,8 @@ #include +namespace cppmpl { + //====================================================================== /** \brief This class wraps a ZeroMQ request-response socket connection. * @@ -63,3 +65,5 @@ class RequestSink { const std::string url_; bool connected_; }; + +} diff --git a/src/cpp_plot.cc b/src/cpp_mpl.cc similarity index 98% rename from src/cpp_plot.cc rename to src/cpp_mpl.cc index 3940d8a..9778395 100644 --- a/src/cpp_plot.cc +++ b/src/cpp_mpl.cc @@ -13,11 +13,13 @@ #include -#include "cpp_plot.hpp" +#include "cpp_mpl.hpp" #include "ipython_protocol.hpp" #include "RequestSink.hpp" +namespace cppmpl { + // Names of the python variables static const std::string THREAD_VAR_NAME{"cpp_ipython_listener_thread"}; static const std::string PORT_VAR_NAME{"cpp_ipython_listener_thread_port"}; @@ -118,3 +120,5 @@ bool CppMatplotlib::SendData(const NumpyArray &data) { void CppMatplotlib::RunCode(const std::string &code) { upSession_->Shell().RunCode(code); } + +} // namespace diff --git a/src/cpp_plot.hpp b/src/cpp_mpl.hpp similarity index 99% rename from src/cpp_plot.hpp rename to src/cpp_mpl.hpp index e61ed6a..7fbb248 100644 --- a/src/cpp_plot.hpp +++ b/src/cpp_mpl.hpp @@ -12,12 +12,13 @@ #include #include +namespace cppmpl { + // Forward declarations struct IPyKernelConfig; class IPythonSession; class RequestSink; - // Reads an entire file into a string //-------------------------------------------------- /** \brief Reads an entire file into a string. Make sure you have enough @@ -238,3 +239,5 @@ class CppMatplotlib { std::unique_ptr upData_conn_; std::unique_ptr upSession_; }; + +} // namespace diff --git a/src/ipython_protocol.cc b/src/ipython_protocol.cc index 15665cd..5ed6f38 100644 --- a/src/ipython_protocol.cc +++ b/src/ipython_protocol.cc @@ -11,6 +11,8 @@ #include "ipython_protocol.hpp" +namespace cppmpl { + /// Delimeter used by the iPython messaging protocol to separate ZMQ /// identities from message data. static const std::string DELIM{""}; @@ -288,4 +290,4 @@ void IPythonSession::Connect (void) { shell_connection_.Connect(); } - +} // namespace diff --git a/src/ipython_protocol.hpp b/src/ipython_protocol.hpp index 2bda5b1..d7debc9 100644 --- a/src/ipython_protocol.hpp +++ b/src/ipython_protocol.hpp @@ -24,6 +24,8 @@ extern "C" { #include #include +namespace cppmpl { + // forward declarations struct IPyKernelConfig; struct IPythonMessage; @@ -358,3 +360,5 @@ class IPythonSession { zmq::context_t zmq_context_; ShellConnection shell_connection_; }; + +} // namespace diff --git a/src/main.cc b/src/main.cc index a15984b..62640f6 100644 --- a/src/main.cc +++ b/src/main.cc @@ -11,7 +11,7 @@ #include #include -#include "cpp_plot.hpp" +#include "cpp_mpl.hpp" int main(int argc, char **argv) { if (argc < 2) { @@ -20,10 +20,10 @@ int main(int argc, char **argv) { exit(-1); } - CppMatplotlib mpl{argv[1]}; + cppmpl::CppMatplotlib mpl{argv[1]}; mpl.Connect(); - std::vector raw_data; + std::vector raw_data; double x = 0.0; while (x < 3.14159 * 4) { @@ -31,7 +31,7 @@ int main(int argc, char **argv) { x += 0.05; } - NumpyArray data("A", raw_data); + cppmpl::NumpyArray data("A", raw_data); mpl.SendData(data); mpl.RunCode("plot(A)\n" "title('f(x) = sin(x)')\n"