blob: 7882ba8092b2e2f4f65e92b34cc28eaf390a54ed [file] [log] [blame]
/*
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef RTC_TOOLS_RTC_EVENT_LOG_VISUALIZER_PLOT_BASE_H_
#define RTC_TOOLS_RTC_EVENT_LOG_VISUALIZER_PLOT_BASE_H_
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "absl/base/attributes.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "rtc_base/ignore_wundef.h"
RTC_PUSH_IGNORING_WUNDEF()
#include "rtc_tools/rtc_event_log_visualizer/proto/chart.pb.h"
RTC_POP_IGNORING_WUNDEF()
namespace webrtc {
enum class LineStyle {
kNone, // No line connecting the points. Used to create scatter plots.
kLine, // Straight line between consecutive points.
kStep, // Horizontal line until the next value. Used for state changes.
kBar // Vertical bars from the x-axis to the point.
};
enum class PointStyle {
kNone, // Don't draw the points.
kHighlight // Draw circles or dots to highlight the points.
};
struct TimeSeriesPoint {
TimeSeriesPoint(float x, float y) : x(x), y(y) {}
float x;
float y;
};
struct TimeSeries {
TimeSeries() = default; // TODO(terelius): Remove the default constructor.
TimeSeries(const char* label,
LineStyle line_style,
PointStyle point_style = PointStyle::kNone)
: label(label), line_style(line_style), point_style(point_style) {}
TimeSeries(const std::string& label,
LineStyle line_style,
PointStyle point_style = PointStyle::kNone)
: label(label), line_style(line_style), point_style(point_style) {}
TimeSeries(TimeSeries&& other)
: label(std::move(other.label)),
line_style(other.line_style),
point_style(other.point_style),
points(std::move(other.points)) {}
TimeSeries& operator=(TimeSeries&& other) {
label = std::move(other.label);
line_style = other.line_style;
point_style = other.point_style;
points = std::move(other.points);
return *this;
}
std::string label;
LineStyle line_style = LineStyle::kLine;
PointStyle point_style = PointStyle::kNone;
std::vector<TimeSeriesPoint> points;
};
struct Interval {
Interval() = default;
Interval(double begin, double end) : begin(begin), end(end) {}
double begin;
double end;
};
struct IntervalSeries {
enum Orientation { kHorizontal, kVertical };
IntervalSeries() = default;
IntervalSeries(const std::string& label,
const std::string& color,
IntervalSeries::Orientation orientation)
: label(label), color(color), orientation(orientation) {}
std::string label;
std::string color;
Orientation orientation;
std::vector<Interval> intervals;
};
// A container that represents a general graph, with axes, title and one or
// more data series. A subclass should define the output format by overriding
// the Draw() method.
class Plot {
public:
virtual ~Plot() {}
ABSL_DEPRECATED("Use PrintPythonCode() or ExportProtobuf() instead.")
virtual void Draw() {}
// Sets the lower x-axis limit to min_value (if left_margin == 0).
// Sets the upper x-axis limit to max_value (if right_margin == 0).
// The margins are measured as fractions of the interval
// (max_value - min_value) and are added to either side of the plot.
void SetXAxis(float min_value,
float max_value,
std::string label,
float left_margin = 0,
float right_margin = 0);
// Sets the lower and upper x-axis limits based on min_value and max_value,
// but modified such that all points in the data series can be represented
// on the x-axis. The margins are measured as fractions of the range of
// x-values and are added to either side of the plot.
void SetSuggestedXAxis(float min_value,
float max_value,
std::string label,
float left_margin = 0,
float right_margin = 0);
// Sets the lower y-axis limit to min_value (if bottom_margin == 0).
// Sets the upper y-axis limit to max_value (if top_margin == 0).
// The margins are measured as fractions of the interval
// (max_value - min_value) and are added to either side of the plot.
void SetYAxis(float min_value,
float max_value,
std::string label,
float bottom_margin = 0,
float top_margin = 0);
// Sets the lower and upper y-axis limits based on min_value and max_value,
// but modified such that all points in the data series can be represented
// on the y-axis. The margins are measured as fractions of the range of
// y-values and are added to either side of the plot.
void SetSuggestedYAxis(float min_value,
float max_value,
std::string label,
float bottom_margin = 0,
float top_margin = 0);
void SetYAxisTickLabels(
const std::vector<std::pair<float, std::string>>& labels);
// Sets the title of the plot.
void SetTitle(const std::string& title);
// Sets an unique ID for the plot. The ID is similar to the title except that
// the title might change in future releases whereas the ID should be stable
// over time.
void SetId(const std::string& id);
void SetId(absl::string_view id);
// Add a new TimeSeries to the plot.
void AppendTimeSeries(TimeSeries&& time_series);
// Add a new IntervalSeries to the plot.
void AppendIntervalSeries(IntervalSeries&& interval_series);
// Add a new TimeSeries to the plot if the series contains contains data.
// Otherwise, the call has no effect and the timeseries is destroyed.
void AppendTimeSeriesIfNotEmpty(TimeSeries&& time_series);
// Replaces PythonPlot::Draw()
void PrintPythonCode(
absl::string_view figure_output_path = absl::string_view()) const;
// Replaces ProtobufPlot::Draw()
void ExportProtobuf(webrtc::analytics::Chart* chart) const;
protected:
float xaxis_min_;
float xaxis_max_;
std::string xaxis_label_;
float yaxis_min_;
float yaxis_max_;
std::string yaxis_label_;
std::vector<std::pair<float, std::string>> yaxis_tick_labels_;
std::string title_;
std::string id_;
std::vector<TimeSeries> series_list_;
std::vector<IntervalSeries> interval_list_;
};
class PlotCollection {
public:
virtual ~PlotCollection() {}
ABSL_DEPRECATED("Use PrintPythonCode() or ExportProtobuf() instead.")
virtual void Draw() {}
virtual Plot* AppendNewPlot();
virtual Plot* AppendNewPlot(absl::string_view);
void SetCallTimeToUtcOffsetMs(int64_t calltime_to_utc_ms) {
calltime_to_utc_ms_ = calltime_to_utc_ms;
}
// Replaces PythonPlotCollection::Draw()
void PrintPythonCode(
bool shared_xaxis,
absl::string_view figure_output_path = absl::string_view()) const;
// Replaces ProtobufPlotCollections::Draw()
void ExportProtobuf(webrtc::analytics::ChartCollection* collection) const;
protected:
std::vector<std::unique_ptr<Plot>> plots_;
absl::optional<int64_t> calltime_to_utc_ms_;
};
} // namespace webrtc
#endif // RTC_TOOLS_RTC_EVENT_LOG_VISUALIZER_PLOT_BASE_H_