mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-15 14:50:39 +01:00

Bug: webrtc:9548 Change-Id: I0daf8dc06fdaac1637c32994ef6ad542ed52202a Reviewed-on: https://webrtc-review.googlesource.com/90045 Reviewed-by: Oleh Prypin <oprypin@webrtc.org> Reviewed-by: Niklas Enbom <niklas.enbom@webrtc.org> Commit-Queue: Artem Titov <titovartem@webrtc.org> Cr-Commit-Position: refs/heads/master@{#24068}
182 lines
6.3 KiB
Python
Executable file
182 lines
6.3 KiB
Python
Executable file
#!/usr/bin/env python
|
|
# Copyright (c) 2015 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.
|
|
|
|
# This script is used to plot simulation dynamics. The expected format is
|
|
# PLOT <plot_number> <var_name>:<ssrc>@<alg_name> <time> <value>
|
|
# <var_name> may optionally be followed by #<axis_alignment> but it is
|
|
# deprecated. <plot_number> is also deprecated.
|
|
# Each combination <var_name>:<ssrc>@<alg_name> is stored in it's own time
|
|
# series. The main function defines which time series should be displayed and
|
|
# whether they should should be displayed in the same or separate windows.
|
|
|
|
|
|
import matplotlib.pyplot as plt
|
|
import numpy
|
|
import re
|
|
import sys
|
|
|
|
# Change this to True to save the figure to a file. Look below for details.
|
|
SAVE_FIGURE = False
|
|
|
|
class ParsePlotLineException(Exception):
|
|
def __init__(self, reason, line):
|
|
super(ParsePlotLineException, self).__init__()
|
|
self.reason = reason
|
|
self.line = line
|
|
|
|
|
|
def ParsePlotLine(line):
|
|
split_line = line.split()
|
|
if len(split_line) != 5:
|
|
raise ParsePlotLineException("Expected 5 arguments on line", line)
|
|
(plot, _, annotated_var, time, value) = split_line
|
|
if plot != "PLOT":
|
|
raise ParsePlotLineException("Line does not begin with \"PLOT\\t\"", line)
|
|
# The variable name can contain any non-whitespace character except "#:@"
|
|
match = re.match(r'([^\s#:@]+)(?:#\d)?:(\d+)@(\S+)', annotated_var)
|
|
|
|
if match is None:
|
|
raise ParsePlotLineException("Could not parse variable name, ssrc and \
|
|
algorithm name", annotated_var)
|
|
var_name = match.group(1)
|
|
ssrc = match.group(2)
|
|
alg_name = match.group(3).replace('_', ' ')
|
|
|
|
return (var_name, ssrc, alg_name, time, value)
|
|
|
|
|
|
def GenerateLabel(var_name, ssrc, ssrc_count, alg_name):
|
|
label = var_name
|
|
if ssrc_count > 1 or ssrc != "0":
|
|
label = label + " flow " + ssrc
|
|
if alg_name != "-":
|
|
label = label + " " + alg_name
|
|
return label
|
|
|
|
|
|
class Figure(object):
|
|
def __init__(self, name):
|
|
self.name = name
|
|
self.subplots = []
|
|
|
|
def AddSubplot(self, var_names, xlabel, ylabel):
|
|
self.subplots.append(Subplot(var_names, xlabel, ylabel))
|
|
|
|
def AddSample(self, var_name, ssrc, alg_name, time, value):
|
|
for s in self.subplots:
|
|
s.AddSample(var_name, ssrc, alg_name, time, value)
|
|
|
|
def PlotFigure(self, fig):
|
|
n = len(self.subplots)
|
|
for i in range(n):
|
|
axis = fig.add_subplot(n, 1, i+1)
|
|
self.subplots[i].PlotSubplot(axis)
|
|
|
|
class Subplot(object):
|
|
def __init__(self, var_names, xlabel, ylabel):
|
|
self.xlabel = xlabel
|
|
self.ylabel = ylabel
|
|
self.var_names = var_names
|
|
self.samples = dict()
|
|
|
|
def AddSample(self, var_name, ssrc, alg_name, time, value):
|
|
if var_name not in self.var_names:
|
|
return
|
|
|
|
if alg_name not in self.samples.keys():
|
|
self.samples[alg_name] = {}
|
|
if ssrc not in self.samples[alg_name].keys():
|
|
self.samples[alg_name][ssrc] = {}
|
|
if var_name not in self.samples[alg_name][ssrc].keys():
|
|
self.samples[alg_name][ssrc][var_name] = []
|
|
|
|
self.samples[alg_name][ssrc][var_name].append((time, value))
|
|
|
|
def PlotSubplot(self, axis):
|
|
axis.set_xlabel(self.xlabel)
|
|
axis.set_ylabel(self.ylabel)
|
|
|
|
count = 0
|
|
for alg_name in self.samples.keys():
|
|
for ssrc in self.samples[alg_name].keys():
|
|
for var_name in self.samples[alg_name][ssrc].keys():
|
|
x = [sample[0] for sample in self.samples[alg_name][ssrc][var_name]]
|
|
y = [sample[1] for sample in self.samples[alg_name][ssrc][var_name]]
|
|
x = numpy.array(x)
|
|
y = numpy.array(y)
|
|
ssrc_count = len(self.samples[alg_name].keys())
|
|
l = GenerateLabel(var_name, ssrc, ssrc_count, alg_name)
|
|
if l == 'MaxThroughput_':
|
|
plt.plot(x, y, label=l, linewidth=4.0)
|
|
else:
|
|
plt.plot(x, y, label=l, linewidth=2.0)
|
|
count += 1
|
|
|
|
plt.grid(True)
|
|
if count > 1:
|
|
plt.legend(loc='best')
|
|
|
|
|
|
def main():
|
|
receiver = Figure("PacketReceiver")
|
|
receiver.AddSubplot(['Throughput_kbps', 'MaxThroughput_', 'Capacity_kbps',
|
|
'PerFlowCapacity_kbps', 'MetricRecorderThroughput_kbps'],
|
|
"Time (s)", "Throughput (kbps)")
|
|
receiver.AddSubplot(['Delay_ms_', 'Delay_ms'], "Time (s)",
|
|
"One-way delay (ms)")
|
|
receiver.AddSubplot(['Packet_Loss_'], "Time (s)", "Packet Loss Ratio")
|
|
|
|
kalman_state = Figure("KalmanState")
|
|
kalman_state.AddSubplot(['kc', 'km'], "Time (s)", "Kalman gain")
|
|
kalman_state.AddSubplot(['slope_1/bps'], "Time (s)", "Slope")
|
|
kalman_state.AddSubplot(['var_noise'], "Time (s)", "Var noise")
|
|
|
|
detector_state = Figure("DetectorState")
|
|
detector_state.AddSubplot(['T', 'threshold'], "Time (s)", "Offset")
|
|
|
|
trendline_state = Figure("TrendlineState")
|
|
trendline_state.AddSubplot(["accumulated_delay_ms", "smoothed_delay_ms"],
|
|
"Time (s)", "Delay (ms)")
|
|
trendline_state.AddSubplot(["trendline_slope"], "Time (s)", "Slope")
|
|
|
|
target_bitrate = Figure("TargetBitrate")
|
|
target_bitrate.AddSubplot(['target_bitrate_bps', 'acknowledged_bitrate'],
|
|
"Time (s)", "Bitrate (bps)")
|
|
|
|
min_rtt_state = Figure("MinRttState")
|
|
min_rtt_state.AddSubplot(['MinRtt'], "Time (s)", "Time (ms)")
|
|
|
|
# Select which figures to plot here.
|
|
figures = [receiver, detector_state, trendline_state, target_bitrate,
|
|
min_rtt_state]
|
|
|
|
# Add samples to the figures.
|
|
for line in sys.stdin:
|
|
if line.startswith("[ RUN ]"):
|
|
test_name = re.search(r'\.(\w+)', line).group(1)
|
|
if line.startswith("PLOT"):
|
|
try:
|
|
(var_name, ssrc, alg_name, time, value) = ParsePlotLine(line)
|
|
for f in figures:
|
|
# The sample will be ignored bv the figures that don't need it.
|
|
f.AddSample(var_name, ssrc, alg_name, time, value)
|
|
except ParsePlotLineException as e:
|
|
print e.reason
|
|
print e.line
|
|
|
|
# Plot figures.
|
|
for f in figures:
|
|
fig = plt.figure(f.name)
|
|
f.PlotFigure(fig)
|
|
if SAVE_FIGURE:
|
|
fig.savefig(test_name + f.name + ".png")
|
|
plt.show()
|
|
|
|
if __name__ == '__main__':
|
|
main()
|