1 /*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10 #ifndef RTC_TOOLS_RTC_EVENT_LOG_VISUALIZER_PLOT_BASE_H_
11 #define RTC_TOOLS_RTC_EVENT_LOG_VISUALIZER_PLOT_BASE_H_
12
13 #include <memory>
14 #include <string>
15 #include <utility>
16 #include <vector>
17
18 #include "rtc_base/deprecation.h"
19 #include "rtc_base/ignore_wundef.h"
20
21 RTC_PUSH_IGNORING_WUNDEF()
22 #include "rtc_tools/rtc_event_log_visualizer/proto/chart.pb.h"
RTC_POP_IGNORING_WUNDEF()23 RTC_POP_IGNORING_WUNDEF()
24
25 namespace webrtc {
26
27 enum class LineStyle {
28 kNone, // No line connecting the points. Used to create scatter plots.
29 kLine, // Straight line between consecutive points.
30 kStep, // Horizontal line until the next value. Used for state changes.
31 kBar // Vertical bars from the x-axis to the point.
32 };
33
34 enum class PointStyle {
35 kNone, // Don't draw the points.
36 kHighlight // Draw circles or dots to highlight the points.
37 };
38
39 struct TimeSeriesPoint {
40 TimeSeriesPoint(float x, float y) : x(x), y(y) {}
41 float x;
42 float y;
43 };
44
45 struct TimeSeries {
46 TimeSeries() = default; // TODO(terelius): Remove the default constructor.
47 TimeSeries(const char* label,
48 LineStyle line_style,
49 PointStyle point_style = PointStyle::kNone)
50 : label(label), line_style(line_style), point_style(point_style) {}
51 TimeSeries(const std::string& label,
52 LineStyle line_style,
53 PointStyle point_style = PointStyle::kNone)
54 : label(label), line_style(line_style), point_style(point_style) {}
55 TimeSeries(TimeSeries&& other)
56 : label(std::move(other.label)),
57 line_style(other.line_style),
58 point_style(other.point_style),
59 points(std::move(other.points)) {}
60 TimeSeries& operator=(TimeSeries&& other) {
61 label = std::move(other.label);
62 line_style = other.line_style;
63 point_style = other.point_style;
64 points = std::move(other.points);
65 return *this;
66 }
67
68 std::string label;
69 LineStyle line_style = LineStyle::kLine;
70 PointStyle point_style = PointStyle::kNone;
71 std::vector<TimeSeriesPoint> points;
72 };
73
74 struct Interval {
75 Interval() = default;
76 Interval(double begin, double end) : begin(begin), end(end) {}
77
78 double begin;
79 double end;
80 };
81
82 struct IntervalSeries {
83 enum Orientation { kHorizontal, kVertical };
84
85 IntervalSeries() = default;
86 IntervalSeries(const std::string& label,
87 const std::string& color,
88 IntervalSeries::Orientation orientation)
89 : label(label), color(color), orientation(orientation) {}
90
91 std::string label;
92 std::string color;
93 Orientation orientation;
94 std::vector<Interval> intervals;
95 };
96
97 // A container that represents a general graph, with axes, title and one or
98 // more data series. A subclass should define the output format by overriding
99 // the Draw() method.
100 class Plot {
101 public:
102 virtual ~Plot() {}
103
104 // Deprecated. Use PrintPythonCode() or ExportProtobuf() instead.
105 RTC_DEPRECATED virtual void Draw() {}
106
107 // Sets the lower x-axis limit to min_value (if left_margin == 0).
108 // Sets the upper x-axis limit to max_value (if right_margin == 0).
109 // The margins are measured as fractions of the interval
110 // (max_value - min_value) and are added to either side of the plot.
111 void SetXAxis(float min_value,
112 float max_value,
113 std::string label,
114 float left_margin = 0,
115 float right_margin = 0);
116
117 // Sets the lower and upper x-axis limits based on min_value and max_value,
118 // but modified such that all points in the data series can be represented
119 // on the x-axis. The margins are measured as fractions of the range of
120 // x-values and are added to either side of the plot.
121 void SetSuggestedXAxis(float min_value,
122 float max_value,
123 std::string label,
124 float left_margin = 0,
125 float right_margin = 0);
126
127 // Sets the lower y-axis limit to min_value (if bottom_margin == 0).
128 // Sets the upper y-axis limit to max_value (if top_margin == 0).
129 // The margins are measured as fractions of the interval
130 // (max_value - min_value) and are added to either side of the plot.
131 void SetYAxis(float min_value,
132 float max_value,
133 std::string label,
134 float bottom_margin = 0,
135 float top_margin = 0);
136
137 // Sets the lower and upper y-axis limits based on min_value and max_value,
138 // but modified such that all points in the data series can be represented
139 // on the y-axis. The margins are measured as fractions of the range of
140 // y-values and are added to either side of the plot.
141 void SetSuggestedYAxis(float min_value,
142 float max_value,
143 std::string label,
144 float bottom_margin = 0,
145 float top_margin = 0);
146
147 void SetYAxisTickLabels(
148 const std::vector<std::pair<float, std::string>>& labels);
149
150 // Sets the title of the plot.
151 void SetTitle(const std::string& title);
152
153 // Sets an unique ID for the plot. The ID is similar to the title except that
154 // the title might change in future releases whereas the ID should be stable
155 // over time.
156 void SetId(const std::string& id);
157
158 // Add a new TimeSeries to the plot.
159 void AppendTimeSeries(TimeSeries&& time_series);
160
161 // Add a new IntervalSeries to the plot.
162 void AppendIntervalSeries(IntervalSeries&& interval_series);
163
164 // Add a new TimeSeries to the plot if the series contains contains data.
165 // Otherwise, the call has no effect and the timeseries is destroyed.
166 void AppendTimeSeriesIfNotEmpty(TimeSeries&& time_series);
167
168 // Replaces PythonPlot::Draw()
169 void PrintPythonCode() const;
170
171 // Replaces ProtobufPlot::Draw()
172 void ExportProtobuf(webrtc::analytics::Chart* chart) const;
173
174 protected:
175 float xaxis_min_;
176 float xaxis_max_;
177 std::string xaxis_label_;
178 float yaxis_min_;
179 float yaxis_max_;
180 std::string yaxis_label_;
181 std::vector<std::pair<float, std::string>> yaxis_tick_labels_;
182 std::string title_;
183 std::string id_;
184 std::vector<TimeSeries> series_list_;
185 std::vector<IntervalSeries> interval_list_;
186 };
187
188 class PlotCollection {
189 public:
190 virtual ~PlotCollection() {}
191
192 // Deprecated. Use PrintPythonCode() or ExportProtobuf() instead.
193 RTC_DEPRECATED virtual void Draw() {}
194
195 virtual Plot* AppendNewPlot();
196
197 // Replaces PythonPlotCollection::Draw()
198 void PrintPythonCode(bool shared_xaxis) const;
199
200 // Replaces ProtobufPlotCollections::Draw()
201 void ExportProtobuf(webrtc::analytics::ChartCollection* collection) const;
202
203 protected:
204 std::vector<std::unique_ptr<Plot>> plots_;
205 };
206
207 } // namespace webrtc
208
209 #endif // RTC_TOOLS_RTC_EVENT_LOG_VISUALIZER_PLOT_BASE_H_
210