Chromium Code Reviews| Index: webrtc/modules/remote_bitrate_estimator/test/plot_dynamics.py |
| diff --git a/webrtc/modules/remote_bitrate_estimator/test/plot_dynamics.py b/webrtc/modules/remote_bitrate_estimator/test/plot_dynamics.py |
| index 164300141d3917be1482d40f4c0af4dfa43b9adf..4208ef00e81569bcd70ff823886f2a2f1721ef03 100755 |
| --- a/webrtc/modules/remote_bitrate_estimator/test/plot_dynamics.py |
| +++ b/webrtc/modules/remote_bitrate_estimator/test/plot_dynamics.py |
| @@ -11,7 +11,6 @@ |
| # Able to plot each flow separately. Other plot boxes can be added, |
| # currently one for Throughput, one for Latency and one for Packet Loss. |
| -import matplotlib |
| import matplotlib.pyplot as plt |
| import numpy |
| import re |
| @@ -20,144 +19,129 @@ import sys |
| # Change this to True to save the figure to a file. Look below for details. |
| save_figure = False |
| -class Variable(object): |
| - def __init__(self, variable): |
| - self._ID = variable[0] |
| - self._xlabel = variable[1] |
| - self._ylabel = variable[2] |
| - self._subplot = variable[3] |
| - self._y_max = variable[4] |
| +class ParsePlotLineException(Exception): |
| + def __init__(self, reason, line): |
| + super(ParsePlotLineException, self).__init__() |
| + self.reason = reason |
| + self.line = line |
| + |
| +def parse_plot_line(line): |
| + split_line = line.split() |
| + if len(split_line) != 5: |
| + raise ParsePlotLineException("Expected 5 aegumesnts on line", line) |
|
Gaetano Carlucci
2016/10/31 12:10:58
aegumesnts -> arguments
terelius
2016/11/02 09:37:16
Done.
|
| + (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 == 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) |
| + |
| + |
| +class Figure(object): |
| + def __init__(self, name): |
| + self.name = name |
| + self.subplots = [] |
| + |
| + def addSubplot(self, xlabel, ylabel, var_names): |
| + self.subplots.append(Subplot(xlabel, ylabel, var_names)) |
| + |
| + 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): |
| + ax = fig.add_subplot(n, 1, i+1) |
| + self.subplots[i].plotSubplot(ax) |
| + |
| + |
| +class Subplot(object): |
| + def __init__(self, xlabel, ylabel, var_names): |
| + self.xlabel = xlabel |
| + self.ylabel = ylabel |
| + self.var_names = var_names |
| self.samples = dict() |
| - def getID(self): |
| - return self._ID |
| - |
| - def getXLabel(self): |
| - return self._xlabel |
| - |
| - def getYLabel(self): |
| - return self._ylabel |
| - |
| - def getSubplot(self): |
| - return self._subplot |
| - |
| - def getYMax(self): |
| - return self._y_max |
| - |
| - def getNumberOfFlows(self): |
| - return len(self.samples) |
| - |
| - |
| - def addSample(self, line): |
| - groups = re.search(r'_(((\d)+((,(\d)+)*))_(\D+))#\d:(\d)@(\S+)', line) |
| - |
| - # Each variable will be plotted in a separated box. |
| - var_name = groups.group(1) |
| - alg_name = groups.group(9) |
| - |
| - alg_name = alg_name.replace('_', ' ') |
| + 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 var_name not in self.samples[alg_name].keys(): |
| - self.samples[alg_name][var_name] = [] |
| + if ssrc not in self.samples[alg_name].keys(): |
| + self.samples[alg_name][ssrc] = {} |
| - sample = re.search(r'(\d+\.\d+)\t([-]?\d+\.\d+)', line) |
| + if var_name not in self.samples[alg_name][ssrc].keys(): |
| + self.samples[alg_name][ssrc][var_name] = [] |
| - s = (sample.group(1), sample.group(2)) |
| - self.samples[alg_name][var_name].append(s) |
| + self.samples[alg_name][ssrc][var_name].append((time, value)) |
| -def plotVar(v, ax, show_legend, show_x_label): |
| - if show_x_label: |
| - ax.set_xlabel(v.getXLabel(), fontsize='large') |
| - ax.set_ylabel(v.getYLabel(), fontsize='large') |
| + def plotSubplot(self, ax): |
| + ax.set_xlabel(self.xlabel) |
| + ax.set_ylabel(self.ylabel) |
| - for alg in v.samples.keys(): |
| + 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) |
| - for series in v.samples[alg].keys(): |
| + plt.plot(x, y, label=var_name, linewidth=2.0) |
| + plt.grid(True) |
| - x = [sample[0] for sample in v.samples[alg][series]] |
| - y = [sample[1] for sample in v.samples[alg][series]] |
| - x = numpy.array(x) |
| - y = numpy.array(y) |
| + plt.legend(loc='best', shadow=True, ncol=len(self.samples)) |
| - line = plt.plot(x, y, label=alg, linewidth=4.0) |
| - |
| - colormap = {'Available0':'#AAAAAA', |
| - 'Available1':'#AAAAAA', |
| - 'GCC0':'#80D000', |
| - 'GCC1':'#008000', |
| - 'GCC2':'#00F000', |
| - 'GCC3':'#00B000', |
| - 'GCC4':'#70B020', |
| - 'NADA0':'#0000AA', |
| - 'NADA1':'#A0A0FF', |
| - 'NADA2':'#0000FF', |
| - 'NADA3':'#C0A0FF', |
| - 'NADA4':'#9060B0',} |
| - |
| - flow_id = re.search(r'(\d+(,\d+)*)', series) # One or multiple ids. |
| - key = alg + flow_id.group(1) |
| - |
| - if key in colormap: |
| - plt.setp(line, color=colormap[key]) |
| - elif alg == 'TCP': |
| - plt.setp(line, color='#AAAAAA') |
| - else: |
| - plt.setp(line, color='#654321') |
| - |
| - if alg.startswith('Available'): |
| - plt.setp(line, linestyle='--') |
| - plt.grid(True) |
| - |
| - # x1, x2, y1, y2 |
| - _, x2, _, y2 = plt.axis() |
| - if v.getYMax() >= 0: |
| - y2 = v.getYMax() |
| - plt.axis((0, x2, 0, y2)) |
| - |
| - if show_legend: |
| - plt.legend(loc='upper center', bbox_to_anchor=(0.5, 1.40), |
| - shadow=True, fontsize='large', ncol=len(v.samples)) |
| def main(): |
| - variables = [ |
| - ('Throughput_kbps', "Time (s)", "Throughput (kbps)", 1, 4000), |
| - ('Delay_ms', "Time (s)", "One-way Delay (ms)", 2, 500), |
| - ('Packet_Loss', "Time (s)", "Packet Loss Ratio", 3, 1.0), |
| - ] |
| + receiver = Figure("PacketReceiver") |
| + receiver.addSubplot("Time (s)", "Throughput (kbps)", ['Throughput_kbps']) |
| + receiver.addSubplot("Time (s)", "One-way Delay (ms)", ['Delay_ms']) |
|
Gaetano Carlucci
2016/10/31 12:10:58
Delay_ms -> Delay_ms_
It seems that an extra _ is
terelius
2016/11/02 09:37:16
There are actually two variables, one with undersc
|
| + receiver.addSubplot("Time (s)", "Packet Loss Ratio", ['Packet_Loss']) |
|
Gaetano Carlucci
2016/10/31 12:10:58
Packet_Loss -> Packet_Loss_
terelius
2016/11/02 09:37:16
Done.
|
| - var = [] |
| + kalman_state = Figure("KalmanState") |
| + kalman_state.addSubplot("Time (s)", "", ['kc', 'km']) |
| + kalman_state.addSubplot("Time (s)", "Slope", ['slope_1/bps']) |
| + kalman_state.addSubplot("Time (s)", "Var noise", ['var_noise']) |
| - # Create objects. |
| - for variable in variables: |
| - var.append(Variable(variable)) |
| + detector_state = Figure("DetectorState") |
| + detector_state.addSubplot("Time (s)", "Offset", ['offset_ms']) |
| + detector_state.addSubplot("Time (s)", "Gamma", ['gamma_ms']) |
| - # Add samples to the objects. |
| + # Select which figures to plot here. |
| + figures = [receiver, detector_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"): |
| - for v in var: |
| - if v.getID() in line: |
| - v.addSample(line) |
| - |
| - matplotlib.rcParams.update({'font.size': 48/len(variables)}) |
| + try: |
| + (var_name, ssrc, alg_name, time, value) = parse_plot_line(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 variables. |
| - fig = plt.figure() |
| - |
| - # Offest and threshold on the same plot. |
| - n = var[-1].getSubplot() |
| - i = 0 |
| - for v in var: |
| - ax = fig.add_subplot(n, 1, v.getSubplot()) |
| - plotVar(v, ax, i == 0, i == n - 1) |
| - i += 1 |
| - |
| - if save_figure: |
| - fig.savefig(test_name + ".png") |
| + 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__': |