Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(262)

Side by Side Diff: webrtc/modules/remote_bitrate_estimator/test/plot_dynamics.py

Issue 2456373002: Update BWE_TEST_LOGGING_PLOT output format, and fix plot_dynamics.py script. (Closed)
Patch Set: Suppress warnings about unused variable. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 2 # Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
3 # 3 #
4 # Use of this source code is governed by a BSD-style license 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 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 6 # tree. An additional intellectual property rights grant can be found
7 # in the file PATENTS. All contributing project authors may 7 # in the file PATENTS. All contributing project authors may
8 # be found in the AUTHORS file in the root of the source tree. 8 # be found in the AUTHORS file in the root of the source tree.
9 9
10 # This script is used to plot simulation dynamics. 10 # This script is used to plot simulation dynamics. The expected format is
11 # Able to plot each flow separately. Other plot boxes can be added, 11 # PLOT <plot_number> <var_name>:<ssrc>@<alg_name> <time> <value>
12 # currently one for Throughput, one for Latency and one for Packet Loss. 12 # <var_name> may optionally be followed by #<axis_alignment> but it is
13 # deprecated. <plot_number> is also deprecated.
14 # Each combination <var_name>:<ssrc>@<alg_name> is stored in it's own time
15 # series. The main function defines which time series should be displayed and
16 # whether they should should be displayed in the same or separate windows.
13 17
14 import matplotlib 18
15 import matplotlib.pyplot as plt 19 import matplotlib.pyplot as plt
16 import numpy 20 import numpy
17 import re 21 import re
18 import sys 22 import sys
19 23
20 # Change this to True to save the figure to a file. Look below for details. 24 # Change this to True to save the figure to a file. Look below for details.
21 save_figure = False 25 save_figure = False
22 26
23 class Variable(object): 27 class ParsePlotLineException(Exception):
24 def __init__(self, variable): 28 def __init__(self, reason, line):
25 self._ID = variable[0] 29 super(ParsePlotLineException, self).__init__()
26 self._xlabel = variable[1] 30 self.reason = reason
27 self._ylabel = variable[2] 31 self.line = line
28 self._subplot = variable[3] 32
29 self._y_max = variable[4] 33
34 def parse_plot_line(line):
35 split_line = line.split()
36 if len(split_line) != 5:
37 raise ParsePlotLineException("Expected 5 arguments on line", line)
38 (plot, _, annotated_var, time, value) = split_line
39 if plot != "PLOT":
40 raise ParsePlotLineException("Line does not begin with \"PLOT\\t\"", line)
41 # The variable name can contain any non-whitespace character except "#:@"
42 match = re.match(r'([^\s#:@]+)(?:#\d)?:(\d+)@(\S+)', annotated_var)
43
44 if match == None:
45 raise ParsePlotLineException("Could not parse variable name, ssrc and \
46 algorithm name", annotated_var)
47 var_name = match.group(1)
48 ssrc = match.group(2)
49 alg_name = match.group(3).replace('_', ' ')
50
51 return (var_name, ssrc, alg_name, time, value)
52
53
54 def generate_label(var_name, ssrc, ssrc_count, alg_name):
55 label = var_name
56 if ssrc_count > 1 or ssrc != "0":
57 label = label + " flow " + ssrc
58 if alg_name != "-":
59 label = label + " " + alg_name
60 return label
61
62
63 class Figure(object):
64 def __init__(self, name):
65 self.name = name
66 self.subplots = []
67
68 def addSubplot(self, var_names, xlabel, ylabel):
69 self.subplots.append(Subplot(var_names, xlabel, ylabel))
70
71 def addSample(self, var_name, ssrc, alg_name, time, value):
72 for s in self.subplots:
73 s.addSample(var_name, ssrc, alg_name, time, value)
74
75 def plotFigure(self, fig):
76 n = len(self.subplots)
77 for i in range(n):
78 ax = fig.add_subplot(n, 1, i+1)
79 self.subplots[i].plotSubplot(ax)
80
81
82 class Subplot(object):
83 def __init__(self, var_names, xlabel, ylabel):
84 self.xlabel = xlabel
85 self.ylabel = ylabel
86 self.var_names = var_names
30 self.samples = dict() 87 self.samples = dict()
31 88
32 def getID(self): 89 def addSample(self, var_name, ssrc, alg_name, time, value):
33 return self._ID 90 if var_name not in self.var_names:
34 91 return
35 def getXLabel(self):
36 return self._xlabel
37
38 def getYLabel(self):
39 return self._ylabel
40
41 def getSubplot(self):
42 return self._subplot
43
44 def getYMax(self):
45 return self._y_max
46
47 def getNumberOfFlows(self):
48 return len(self.samples)
49
50
51 def addSample(self, line):
52 groups = re.search(r'_(((\d)+((,(\d)+)*))_(\D+))#\d:(\d)@(\S+)', line)
53
54 # Each variable will be plotted in a separated box.
55 var_name = groups.group(1)
56 alg_name = groups.group(9)
57
58 alg_name = alg_name.replace('_', ' ')
59 92
60 if alg_name not in self.samples.keys(): 93 if alg_name not in self.samples.keys():
61 self.samples[alg_name] = {} 94 self.samples[alg_name] = {}
95 if ssrc not in self.samples[alg_name].keys():
96 self.samples[alg_name][ssrc] = {}
97 if var_name not in self.samples[alg_name][ssrc].keys():
98 self.samples[alg_name][ssrc][var_name] = []
62 99
63 if var_name not in self.samples[alg_name].keys(): 100 self.samples[alg_name][ssrc][var_name].append((time, value))
64 self.samples[alg_name][var_name] = []
65 101
66 sample = re.search(r'(\d+\.\d+)\t([-]?\d+\.\d+)', line) 102 def plotSubplot(self, ax):
103 ax.set_xlabel(self.xlabel)
104 ax.set_ylabel(self.ylabel)
67 105
68 s = (sample.group(1), sample.group(2)) 106 count = 0
69 self.samples[alg_name][var_name].append(s) 107 for alg_name in self.samples.keys():
108 for ssrc in self.samples[alg_name].keys():
109 for var_name in self.samples[alg_name][ssrc].keys():
110 x = [sample[0] for sample in self.samples[alg_name][ssrc][var_name]]
111 y = [sample[1] for sample in self.samples[alg_name][ssrc][var_name]]
112 x = numpy.array(x)
113 y = numpy.array(y)
70 114
71 def plotVar(v, ax, show_legend, show_x_label): 115 ssrc_count = len(self.samples[alg_name].keys())
72 if show_x_label: 116 l = generate_label(var_name, ssrc, ssrc_count, alg_name)
73 ax.set_xlabel(v.getXLabel(), fontsize='large') 117 plt.plot(x, y, label=l, linewidth=2.0)
74 ax.set_ylabel(v.getYLabel(), fontsize='large') 118 count += 1
75 119
76 for alg in v.samples.keys(): 120 plt.grid(True)
121 if count > 1:
122 plt.legend(loc='best')
77 123
78 for series in v.samples[alg].keys():
79
80 x = [sample[0] for sample in v.samples[alg][series]]
81 y = [sample[1] for sample in v.samples[alg][series]]
82 x = numpy.array(x)
83 y = numpy.array(y)
84
85 line = plt.plot(x, y, label=alg, linewidth=4.0)
86
87 colormap = {'Available0':'#AAAAAA',
88 'Available1':'#AAAAAA',
89 'GCC0':'#80D000',
90 'GCC1':'#008000',
91 'GCC2':'#00F000',
92 'GCC3':'#00B000',
93 'GCC4':'#70B020',
94 'NADA0':'#0000AA',
95 'NADA1':'#A0A0FF',
96 'NADA2':'#0000FF',
97 'NADA3':'#C0A0FF',
98 'NADA4':'#9060B0',}
99
100 flow_id = re.search(r'(\d+(,\d+)*)', series) # One or multiple ids.
101 key = alg + flow_id.group(1)
102
103 if key in colormap:
104 plt.setp(line, color=colormap[key])
105 elif alg == 'TCP':
106 plt.setp(line, color='#AAAAAA')
107 else:
108 plt.setp(line, color='#654321')
109
110 if alg.startswith('Available'):
111 plt.setp(line, linestyle='--')
112 plt.grid(True)
113
114 # x1, x2, y1, y2
115 _, x2, _, y2 = plt.axis()
116 if v.getYMax() >= 0:
117 y2 = v.getYMax()
118 plt.axis((0, x2, 0, y2))
119
120 if show_legend:
121 plt.legend(loc='upper center', bbox_to_anchor=(0.5, 1.40),
122 shadow=True, fontsize='large', ncol=len(v.samples))
123 124
124 def main(): 125 def main():
125 variables = [ 126 receiver = Figure("PacketReceiver")
126 ('Throughput_kbps', "Time (s)", "Throughput (kbps)", 1, 4000), 127 receiver.addSubplot(['Throughput_kbps', 'MaxThroughput_', 'Capacity_kbps',
127 ('Delay_ms', "Time (s)", "One-way Delay (ms)", 2, 500), 128 'PerFlowCapacity_kbps', 'MetricRecorderThroughput_kbps'],
128 ('Packet_Loss', "Time (s)", "Packet Loss Ratio", 3, 1.0), 129 "Time (s)", "Throughput (kbps)")
129 ] 130 receiver.addSubplot(['Delay_ms_', 'Delay_ms'], "Time (s)",
131 "One-way delay (ms)")
132 receiver.addSubplot(['Packet_Loss_'], "Time (s)", "Packet Loss Ratio")
130 133
131 var = [] 134 kalman_state = Figure("KalmanState")
135 kalman_state.addSubplot(['kc', 'km'], "Time (s)", "Kalman gain")
136 kalman_state.addSubplot(['slope_1/bps'], "Time (s)", "Slope")
137 kalman_state.addSubplot(['var_noise'], "Time (s)", "Var noise")
132 138
133 # Create objects. 139 detector_state = Figure("DetectorState")
134 for variable in variables: 140 detector_state.addSubplot(['offset_ms'], "Time (s)", "Offset")
135 var.append(Variable(variable)) 141 detector_state.addSubplot(['gamma_ms'], "Time (s)", "Gamma")
136 142
137 # Add samples to the objects. 143 # Select which figures to plot here.
144 figures = [receiver, detector_state]
145
146 # Add samples to the figures.
138 for line in sys.stdin: 147 for line in sys.stdin:
139 if line.startswith("[ RUN ]"): 148 if line.startswith("[ RUN ]"):
140 test_name = re.search(r'\.(\w+)', line).group(1) 149 test_name = re.search(r'\.(\w+)', line).group(1)
141 if line.startswith("PLOT"): 150 if line.startswith("PLOT"):
142 for v in var: 151 try:
143 if v.getID() in line: 152 (var_name, ssrc, alg_name, time, value) = parse_plot_line(line)
144 v.addSample(line) 153 for f in figures:
154 # The sample will be ignored bv the figures that don't need it.
155 f.addSample(var_name, ssrc, alg_name, time, value)
156 except ParsePlotLineException as e:
157 print e.reason
158 print e.line
145 159
146 matplotlib.rcParams.update({'font.size': 48/len(variables)}) 160 # Plot figures.
147 161 for f in figures:
148 # Plot variables. 162 fig = plt.figure(f.name)
149 fig = plt.figure() 163 f.plotFigure(fig)
150 164 if save_figure:
151 # Offest and threshold on the same plot. 165 fig.savefig(test_name + f.name + ".png")
152 n = var[-1].getSubplot()
153 i = 0
154 for v in var:
155 ax = fig.add_subplot(n, 1, v.getSubplot())
156 plotVar(v, ax, i == 0, i == n - 1)
157 i += 1
158
159 if save_figure:
160 fig.savefig(test_name + ".png")
161 plt.show() 166 plt.show()
162 167
163 if __name__ == '__main__': 168 if __name__ == '__main__':
164 main() 169 main()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698