| #ifndef AOS_ANALYSIS_IN_PROCESS_PLOTTER_H_ |
| #define AOS_ANALYSIS_IN_PROCESS_PLOTTER_H_ |
| |
| #include <stddef.h> |
| |
| #include <memory> |
| #include <string> |
| #include <string_view> |
| #include <vector> |
| |
| #include "flatbuffers/buffer.h" |
| #include "flatbuffers/string.h" |
| |
| #include "aos/analysis/plot_data_generated.h" |
| #include "aos/configuration_generated.h" |
| #include "aos/events/event_loop.h" |
| #include "aos/events/simulated_event_loop.h" |
| #include "aos/flatbuffers.h" |
| #include "aos/network/web_proxy.h" |
| |
| namespace aos::analysis { |
| |
| // This class wraps the WebProxy class to provide a convenient C++ interface to |
| // dynamically generate plots. |
| // Currently, the main useful interface that this provides is a matplotlib-like |
| // interface--see in_process_plotter_demo.cc for sample usage. It doesn't |
| // precisely follow matplotlib's conventions, but the basic style does mimic |
| // matplotlib. Future iterations may ditch this in favor of a more modern |
| // interface where we actually return handles for plots and lines and the such. |
| // |
| // Note that currently the port for the seb server is hard-coded to 8080, so |
| // only one instance of the Plotter can be present at once. |
| // |
| // You must call Spin() for the web server to actually do anything helpful. |
| class Plotter { |
| public: |
| Plotter(); |
| |
| // matplotlib-like interface |
| // The basic pattern is: |
| // 1) Call Figure() |
| // 2) Set up the lines, labels, etc. for the figure. |
| // 3) Repeat 1-2 however many times. |
| // 4) Call Publish(). |
| // 5) Repeat 1-5 however many times. |
| // |
| // Publish() actually pushes the figures that you setup to the web-page, |
| // either with an autogenerated title or the title set by Title(). All state |
| // is cleared (or should be cleared) by the call to Publish(). |
| |
| // Sets the title for the current set of plots; if you |
| void Title(std::string_view title); |
| void AddFigure(std::string_view title = "", double width = 0, |
| double height = 0); |
| struct LineOptions { |
| std::string_view label = ""; |
| std::string_view line_style = "*-"; |
| std::string_view color = ""; |
| double point_size = 3.0; |
| }; |
| |
| void AddLine(const std::vector<double> &x, const std::vector<double> &y, |
| std::string_view label) { |
| AddLine(x, y, LineOptions{.label = label}); |
| } |
| void AddLine(const std::vector<double> &x, const std::vector<double> &y, |
| std::string_view label, std::string_view line_style) { |
| AddLine(x, y, LineOptions{.label = label, .line_style = line_style}); |
| } |
| void AddLine(const std::vector<double> &x, const std::vector<double> &y, |
| LineOptions options); |
| |
| void ShareXAxis(bool share) { share_x_axis_ = share; } |
| void XLabel(std::string_view label); |
| void YLabel(std::string_view label); |
| void Publish(); |
| |
| void Spin(); |
| |
| private: |
| void MaybeFinishFigure(); |
| |
| aos::FlatbufferDetachedBuffer<aos::Configuration> config_; |
| aos::SimulatedEventLoopFactory event_loop_factory_; |
| std::unique_ptr<aos::EventLoop> event_loop_; |
| aos::Sender<Plot> plot_sender_; |
| aos::web_proxy::WebProxy web_proxy_; |
| |
| aos::Sender<Plot>::Builder builder_; |
| flatbuffers::Offset<flatbuffers::String> title_; |
| flatbuffers::Offset<flatbuffers::String> figure_title_; |
| flatbuffers::Offset<flatbuffers::String> xlabel_; |
| flatbuffers::Offset<flatbuffers::String> ylabel_; |
| bool share_x_axis_ = false; |
| float next_top_ = 0; |
| flatbuffers::Offset<Position> position_; |
| std::vector<flatbuffers::Offset<Figure>> figures_; |
| std::vector<flatbuffers::Offset<Line>> lines_; |
| |
| struct ColorWheelColor { |
| std::string name; |
| Color color; |
| }; |
| |
| size_t color_wheel_position_ = 0; |
| std::vector<ColorWheelColor> color_wheel_; |
| }; |
| |
| } // namespace aos::analysis |
| #endif // AOS_ANALYSIS_IN_PROCESS_PLOTTER_H_ |