blob: 2def0c3a6eba0b5c3017ada5d2e1b4473768c15a [file] [log] [blame]
terelius54ce6802016-07-13 06:44:41 -07001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "rtc_tools/event_log_visualizer/plot_python.h"
terelius54ce6802016-07-13 06:44:41 -070012
13#include <stdio.h>
Stefan Holmer13181032016-07-29 14:48:54 +020014#include <memory>
Yves Gerey3e707812018-11-28 16:47:49 +010015#include <string>
16#include <vector>
terelius54ce6802016-07-13 06:44:41 -070017
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "rtc_base/checks.h"
philipel23c7f252017-07-14 06:30:03 -070019
terelius54ce6802016-07-13 06:44:41 -070020namespace webrtc {
terelius54ce6802016-07-13 06:44:41 -070021
22PythonPlot::PythonPlot() {}
23
24PythonPlot::~PythonPlot() {}
25
tereliusdc35dcd2016-08-01 12:03:27 -070026void PythonPlot::Draw() {
terelius54ce6802016-07-13 06:44:41 -070027 // Write python commands to stdout. Intended program usage is
28 // ./event_log_visualizer event_log160330.dump | python
29
tereliusdc35dcd2016-08-01 12:03:27 -070030 if (!series_list_.empty()) {
31 printf("color_count = %zu\n", series_list_.size());
terelius54ce6802016-07-13 06:44:41 -070032 printf(
33 "hls_colors = [(i*1.0/color_count, 0.25+i*0.5/color_count, 0.8) for i "
34 "in range(color_count)]\n");
Bjorn Tereliusb577d5e2017-11-10 16:21:34 +010035 printf("colors = [colorsys.hls_to_rgb(*hls) for hls in hls_colors]\n");
terelius54ce6802016-07-13 06:44:41 -070036
tereliusdc35dcd2016-08-01 12:03:27 -070037 for (size_t i = 0; i < series_list_.size(); i++) {
philipel35ba9bd2017-04-19 05:58:51 -070038 printf("\n# === Series: %s ===\n", series_list_[i].label.c_str());
terelius54ce6802016-07-13 06:44:41 -070039 // List x coordinates
40 printf("x%zu = [", i);
tereliusdc35dcd2016-08-01 12:03:27 -070041 if (series_list_[i].points.size() > 0)
Stefan Holmer1d4a2272018-05-24 13:48:09 +020042 printf("%.3f", series_list_[i].points[0].x);
tereliusdc35dcd2016-08-01 12:03:27 -070043 for (size_t j = 1; j < series_list_[i].points.size(); j++)
Stefan Holmer1d4a2272018-05-24 13:48:09 +020044 printf(", %.3f", series_list_[i].points[j].x);
terelius54ce6802016-07-13 06:44:41 -070045 printf("]\n");
46
47 // List y coordinates
48 printf("y%zu = [", i);
tereliusdc35dcd2016-08-01 12:03:27 -070049 if (series_list_[i].points.size() > 0)
50 printf("%G", series_list_[i].points[0].y);
51 for (size_t j = 1; j < series_list_[i].points.size(); j++)
52 printf(", %G", series_list_[i].points[j].y);
terelius54ce6802016-07-13 06:44:41 -070053 printf("]\n");
54
Bjorn Tereliusb577d5e2017-11-10 16:21:34 +010055 if (series_list_[i].line_style == LineStyle::kBar) {
terelius54ce6802016-07-13 06:44:41 -070056 // There is a plt.bar function that draws bar plots,
57 // but it is *way* too slow to be useful.
58 printf(
59 "plt.vlines(x%zu, map(lambda t: min(t,0), y%zu), map(lambda t: "
Bjorn Tereliusb577d5e2017-11-10 16:21:34 +010060 "max(t,0), y%zu), color=colors[%zu], "
terelius54ce6802016-07-13 06:44:41 -070061 "label=\'%s\')\n",
tereliusdc35dcd2016-08-01 12:03:27 -070062 i, i, i, i, series_list_[i].label.c_str());
Bjorn Tereliusb577d5e2017-11-10 16:21:34 +010063 if (series_list_[i].point_style == PointStyle::kHighlight) {
64 printf(
65 "plt.plot(x%zu, y%zu, color=colors[%zu], "
66 "marker='.', ls=' ')\n",
67 i, i, i);
68 }
69 } else if (series_list_[i].line_style == LineStyle::kLine) {
70 if (series_list_[i].point_style == PointStyle::kHighlight) {
71 printf(
72 "plt.plot(x%zu, y%zu, color=colors[%zu], label=\'%s\', "
73 "marker='.')\n",
74 i, i, i, series_list_[i].label.c_str());
75 } else {
76 printf("plt.plot(x%zu, y%zu, color=colors[%zu], label=\'%s\')\n", i,
77 i, i, series_list_[i].label.c_str());
78 }
79 } else if (series_list_[i].line_style == LineStyle::kStep) {
terelius77f05802017-02-01 06:34:53 -080080 // Draw lines from (x[0],y[0]) to (x[1],y[0]) to (x[1],y[1]) and so on
81 // to illustrate the "steps". This can be expressed by duplicating all
82 // elements except the first in x and the last in y.
Bjorn Tereliusb577d5e2017-11-10 16:21:34 +010083 printf("xd%zu = [dup for v in x%zu for dup in [v, v]]\n", i, i);
84 printf("yd%zu = [dup for v in y%zu for dup in [v, v]]\n", i, i);
terelius77f05802017-02-01 06:34:53 -080085 printf(
Bjorn Tereliusb577d5e2017-11-10 16:21:34 +010086 "plt.plot(xd%zu[1:], yd%zu[:-1], color=colors[%zu], "
terelius77f05802017-02-01 06:34:53 -080087 "label=\'%s\')\n",
88 i, i, i, series_list_[i].label.c_str());
Bjorn Tereliusb577d5e2017-11-10 16:21:34 +010089 if (series_list_[i].point_style == PointStyle::kHighlight) {
90 printf(
91 "plt.plot(x%zu, y%zu, color=colors[%zu], "
92 "marker='.', ls=' ')\n",
93 i, i, i);
94 }
95 } else if (series_list_[i].line_style == LineStyle::kNone) {
philipele127e7a2017-03-29 16:28:53 +020096 printf(
Bjorn Tereliusb577d5e2017-11-10 16:21:34 +010097 "plt.plot(x%zu, y%zu, color=colors[%zu], label=\'%s\', "
philipel10fc0e62017-04-11 01:50:23 -070098 "marker='o', ls=' ')\n",
philipele127e7a2017-03-29 16:28:53 +020099 i, i, i, series_list_[i].label.c_str());
terelius54ce6802016-07-13 06:44:41 -0700100 } else {
101 printf("raise Exception(\"Unknown graph type\")\n");
102 }
103 }
philipel23c7f252017-07-14 06:30:03 -0700104
105 // IntervalSeries
Ilya Nikolaevskiya4259f62017-12-05 13:19:45 +0100106 printf("interval_colors = ['#ff8e82','#5092fc','#c4ffc4','#aaaaaa']\n");
107 RTC_CHECK_LE(interval_list_.size(), 4);
Bjorn Tereliusb577d5e2017-11-10 16:21:34 +0100108 // To get the intervals to show up in the legend we have to create patches
philipel23c7f252017-07-14 06:30:03 -0700109 // for them.
110 printf("legend_patches = []\n");
111 for (size_t i = 0; i < interval_list_.size(); i++) {
112 // List intervals
113 printf("\n# === IntervalSeries: %s ===\n",
114 interval_list_[i].label.c_str());
115 printf("ival%zu = [", i);
116 if (interval_list_[i].intervals.size() > 0) {
117 printf("(%G, %G)", interval_list_[i].intervals[0].begin,
118 interval_list_[i].intervals[0].end);
119 }
120 for (size_t j = 1; j < interval_list_[i].intervals.size(); j++) {
121 printf(", (%G, %G)", interval_list_[i].intervals[j].begin,
122 interval_list_[i].intervals[j].end);
123 }
124 printf("]\n");
125
126 printf("for i in range(0, %zu):\n", interval_list_[i].intervals.size());
127 if (interval_list_[i].orientation == IntervalSeries::kVertical) {
128 printf(
129 " plt.axhspan(ival%zu[i][0], ival%zu[i][1], "
130 "facecolor=interval_colors[%zu], "
131 "alpha=0.3)\n",
132 i, i, i);
133 } else {
134 printf(
135 " plt.axvspan(ival%zu[i][0], ival%zu[i][1], "
136 "facecolor=interval_colors[%zu], "
137 "alpha=0.3)\n",
138 i, i, i);
139 }
140 printf(
141 "legend_patches.append(mpatches.Patch(ec=\'black\', "
142 "fc=interval_colors[%zu], label='%s'))\n",
143 i, interval_list_[i].label.c_str());
144 }
terelius54ce6802016-07-13 06:44:41 -0700145 }
146
tereliusdc35dcd2016-08-01 12:03:27 -0700147 printf("plt.xlim(%f, %f)\n", xaxis_min_, xaxis_max_);
148 printf("plt.ylim(%f, %f)\n", yaxis_min_, yaxis_max_);
149 printf("plt.xlabel(\'%s\')\n", xaxis_label_.c_str());
150 printf("plt.ylabel(\'%s\')\n", yaxis_label_.c_str());
151 printf("plt.title(\'%s\')\n", title_.c_str());
philipel23c7f252017-07-14 06:30:03 -0700152 if (!series_list_.empty() || !interval_list_.empty()) {
153 printf("handles, labels = plt.gca().get_legend_handles_labels()\n");
154 printf("for lp in legend_patches:\n");
155 printf(" handles.append(lp)\n");
156 printf(" labels.append(lp.get_label())\n");
157 printf("plt.legend(handles, labels, loc=\'best\', fontsize=\'small\')\n");
terelius54ce6802016-07-13 06:44:41 -0700158 }
159}
160
161PythonPlotCollection::PythonPlotCollection() {}
162
163PythonPlotCollection::~PythonPlotCollection() {}
164
tereliusdc35dcd2016-08-01 12:03:27 -0700165void PythonPlotCollection::Draw() {
terelius54ce6802016-07-13 06:44:41 -0700166 printf("import matplotlib.pyplot as plt\n");
philipel23c7f252017-07-14 06:30:03 -0700167 printf("import matplotlib.patches as mpatches\n");
168 printf("import matplotlib.patheffects as pe\n");
terelius54ce6802016-07-13 06:44:41 -0700169 printf("import colorsys\n");
tereliusdc35dcd2016-08-01 12:03:27 -0700170 for (size_t i = 0; i < plots_.size(); i++) {
terelius54ce6802016-07-13 06:44:41 -0700171 printf("plt.figure(%zu)\n", i);
tereliusdc35dcd2016-08-01 12:03:27 -0700172 plots_[i]->Draw();
terelius54ce6802016-07-13 06:44:41 -0700173 }
174 printf("plt.show()\n");
175}
176
tereliusdc35dcd2016-08-01 12:03:27 -0700177Plot* PythonPlotCollection::AppendNewPlot() {
terelius54ce6802016-07-13 06:44:41 -0700178 Plot* plot = new PythonPlot();
tereliusdc35dcd2016-08-01 12:03:27 -0700179 plots_.push_back(std::unique_ptr<Plot>(plot));
terelius54ce6802016-07-13 06:44:41 -0700180 return plot;
181}
182
terelius54ce6802016-07-13 06:44:41 -0700183} // namespace webrtc