1#!/usr/bin/env python
2# Copyright (c) 2015 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# This script is used to plot simulation dynamics.
11# Able to plot each flow separately. Other plot boxes can be added,
12# currently one for Throughput, one for Latency and one for Packet Loss.
13
14import matplotlib
15import matplotlib.pyplot as plt
16import numpy
17import re
18import sys
19
20# Change this to True to save the figure to a file. Look below for details.
21save_figure = False
22
23class Variable(object):
24  def __init__(self, variable):
25    self._ID = variable[0]
26    self._xlabel = variable[1]
27    self._ylabel = variable[2]
28    self._subplot = variable[3]
29    self._y_max = variable[4]
30    self.samples = dict()
31
32  def getID(self):
33    return self._ID
34
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@(\S+)', line)
53
54    # Each variable will be plotted in a separated box.
55    var_name = groups.group(1)
56    alg_name = groups.group(8)
57
58    alg_name = alg_name.replace('_', ' ')
59
60    if alg_name not in self.samples.keys():
61      self.samples[alg_name] = {}
62
63    if var_name not in self.samples[alg_name].keys():
64      self.samples[alg_name][var_name] = []
65
66    sample = re.search(r'(\d+\.\d+)\t([-]?\d+\.\d+)', line)
67
68    s = (sample.group(1), sample.group(2))
69    self.samples[alg_name][var_name].append(s)
70
71def plotVar(v, ax, show_legend, show_x_label):
72  if show_x_label:
73    ax.set_xlabel(v.getXLabel(), fontsize='large')
74  ax.set_ylabel(v.getYLabel(), fontsize='large')
75
76  for alg in v.samples.keys():
77
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
124def main():
125  variables = [
126          ('Throughput_kbps', "Time (s)", "Throughput (kbps)", 1, 4000),
127          ('Delay_ms', "Time (s)", "One-way Delay (ms)", 2, 500),
128          ('Packet_Loss', "Time (s)", "Packet Loss Ratio", 3, 1.0),
129          # ('Sending_Estimate_kbps', "Time (s)", "Sending Estimate (kbps)",
130          #                                                        4, 4000),
131          ]
132
133  var = []
134
135  # Create objects.
136  for variable in variables:
137    var.append(Variable(variable))
138
139  # Add samples to the objects.
140  for line in sys.stdin:
141    if line.startswith("[ RUN      ]"):
142      test_name = re.search(r'\.(\w+)', line).group(1)
143    if line.startswith("PLOT"):
144      for v in var:
145        if v.getID() in line:
146          v.addSample(line)
147
148  matplotlib.rcParams.update({'font.size': 48/len(variables)})
149
150  # Plot variables.
151  fig = plt.figure()
152
153  # Offest and threshold on the same plot.
154  n = var[-1].getSubplot()
155  i = 0
156  for v in var:
157    ax = fig.add_subplot(n, 1, v.getSubplot())
158    plotVar(v, ax, i == 0, i == n - 1)
159    i += 1
160
161  if save_figure:
162    fig.savefig(test_name + ".png")
163  plt.show()
164
165if __name__ == '__main__':
166  main()
167