Update BWE_TEST_LOGGING_PLOT output format, and fix plot_dynamics.py script.
The new format for plot lines is PLOT <plot_no> <var_name>:<ssrc>@<alg_name> <time> <value>. The var_name is no longer prefixed by the context/tag (which most of the time was just the same as the test name.) Update plot_dynamics.py script (which didn't work) to visualize the new BWE_TEST_LOGGING_PLOT lines. BUG=webrtc:6621 Review-Url: https://codereview.webrtc.org/2456373002 Cr-Commit-Position: refs/heads/master@{#14983}
This commit is contained in:
parent
579729dd9e
commit
f94ba462bc
@ -217,42 +217,47 @@ uint32_t PacketProcessor::bits_per_second() const {
|
||||
RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener,
|
||||
int flow_id,
|
||||
const char* name,
|
||||
const std::string& plot_name)
|
||||
const std::string& algorithm_name)
|
||||
: PacketProcessor(listener, flow_id, kRegular),
|
||||
packets_per_second_stats_(),
|
||||
kbps_stats_(),
|
||||
start_plotting_time_ms_(0),
|
||||
plot_name_(plot_name) {
|
||||
std::stringstream ss;
|
||||
ss << name << "_" << flow_id;
|
||||
name_ = ss.str();
|
||||
}
|
||||
flow_id_(flow_id),
|
||||
name_(name),
|
||||
algorithm_name_(algorithm_name) {
|
||||
// Only used when compiling with BWE test logging enabled.
|
||||
RTC_UNUSED(flow_id_);
|
||||
}
|
||||
|
||||
RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener,
|
||||
const FlowIds& flow_ids,
|
||||
const char* name,
|
||||
const std::string& plot_name)
|
||||
const std::string& algorithm_name)
|
||||
: PacketProcessor(listener, flow_ids, kRegular),
|
||||
packets_per_second_stats_(),
|
||||
kbps_stats_(),
|
||||
start_plotting_time_ms_(0),
|
||||
plot_name_(plot_name) {
|
||||
flow_id_(0),
|
||||
name_(name),
|
||||
algorithm_name_(algorithm_name) {
|
||||
// TODO(terelius): Appending the flow IDs to the algorithm name is a hack to
|
||||
// keep the current plot functionality without having to print the full
|
||||
// context for each PLOT line. It is unclear whether multiple flow IDs are
|
||||
// needed at all in the long term.
|
||||
std::stringstream ss;
|
||||
ss << name;
|
||||
char delimiter = '_';
|
||||
ss << algorithm_name_;
|
||||
for (int flow_id : flow_ids) {
|
||||
ss << delimiter << flow_id;
|
||||
delimiter = ',';
|
||||
ss << ',' << flow_id;
|
||||
}
|
||||
name_ = ss.str();
|
||||
algorithm_name_ = ss.str();
|
||||
}
|
||||
|
||||
RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener,
|
||||
const FlowIds& flow_ids,
|
||||
const char* name,
|
||||
int64_t start_plotting_time_ms,
|
||||
const std::string& plot_name)
|
||||
: RateCounterFilter(listener, flow_ids, name, plot_name) {
|
||||
const std::string& algorithm_name)
|
||||
: RateCounterFilter(listener, flow_ids, name, algorithm_name) {
|
||||
start_plotting_time_ms_ = start_plotting_time_ms;
|
||||
}
|
||||
|
||||
@ -277,11 +282,13 @@ void RateCounterFilter::Plot(int64_t timestamp_ms) {
|
||||
plot_kbps = rate_counter_.bits_per_second() / 1000.0;
|
||||
}
|
||||
BWE_TEST_LOGGING_CONTEXT(name_.c_str());
|
||||
if (plot_name_.empty()) {
|
||||
BWE_TEST_LOGGING_PLOT(0, "Throughput_kbps#1", timestamp_ms, plot_kbps);
|
||||
if (algorithm_name_.empty()) {
|
||||
BWE_TEST_LOGGING_PLOT_WITH_SSRC(0, "Throughput_kbps#1", timestamp_ms,
|
||||
plot_kbps, flow_id_);
|
||||
} else {
|
||||
BWE_TEST_LOGGING_PLOT_WITH_NAME(0, "Throughput_kbps#1", timestamp_ms,
|
||||
plot_kbps, plot_name_);
|
||||
BWE_TEST_LOGGING_PLOT_WITH_NAME_AND_SSRC(0, "Throughput_kbps#1",
|
||||
timestamp_ms, plot_kbps, flow_id_,
|
||||
algorithm_name_);
|
||||
}
|
||||
|
||||
RTC_UNUSED(plot_kbps);
|
||||
|
||||
@ -230,16 +230,16 @@ class RateCounterFilter : public PacketProcessor {
|
||||
RateCounterFilter(PacketProcessorListener* listener,
|
||||
int flow_id,
|
||||
const char* name,
|
||||
const std::string& plot_name);
|
||||
const std::string& algorithm_name);
|
||||
RateCounterFilter(PacketProcessorListener* listener,
|
||||
const FlowIds& flow_ids,
|
||||
const char* name,
|
||||
const std::string& plot_name);
|
||||
const std::string& algorithm_name);
|
||||
RateCounterFilter(PacketProcessorListener* listener,
|
||||
const FlowIds& flow_ids,
|
||||
const char* name,
|
||||
int64_t start_plotting_time_ms,
|
||||
const std::string& plot_name);
|
||||
const std::string& algorithm_name);
|
||||
virtual ~RateCounterFilter();
|
||||
|
||||
void LogStats();
|
||||
@ -250,10 +250,11 @@ class RateCounterFilter : public PacketProcessor {
|
||||
private:
|
||||
Stats<double> packets_per_second_stats_;
|
||||
Stats<double> kbps_stats_;
|
||||
std::string name_;
|
||||
int64_t start_plotting_time_ms_;
|
||||
int flow_id_;
|
||||
std::string name_;
|
||||
// Algorithm name if single flow, Total link utilization if all flows.
|
||||
std::string plot_name_;
|
||||
std::string algorithm_name_;
|
||||
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RateCounterFilter);
|
||||
};
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
#include "webrtc/base/format_macros.h"
|
||||
#include "webrtc/base/platform_thread.h"
|
||||
#include "webrtc/system_wrappers/include/critical_section_wrapper.h"
|
||||
|
||||
@ -90,19 +91,26 @@ void Logging::Log(const char format[], ...) {
|
||||
}
|
||||
}
|
||||
|
||||
void Logging::Plot(int figure, double value) {
|
||||
Plot(figure, value, 0, "-");
|
||||
}
|
||||
|
||||
void Logging::Plot(int figure, double value, uint32_t ssrc) {
|
||||
Plot(figure, value, ssrc, "-");
|
||||
}
|
||||
|
||||
void Logging::Plot(int figure, double value, const std::string& alg_name) {
|
||||
Plot(figure, value, 0, alg_name);
|
||||
void Logging::Plot(int figure, const std::string& name, double value) {
|
||||
Plot(figure, name, value, 0, "-");
|
||||
}
|
||||
|
||||
void Logging::Plot(int figure,
|
||||
const std::string& name,
|
||||
double value,
|
||||
uint32_t ssrc) {
|
||||
Plot(figure, name, value, ssrc, "-");
|
||||
}
|
||||
|
||||
void Logging::Plot(int figure,
|
||||
const std::string& name,
|
||||
double value,
|
||||
const std::string& alg_name) {
|
||||
Plot(figure, name, value, 0, alg_name);
|
||||
}
|
||||
|
||||
void Logging::Plot(int figure,
|
||||
const std::string& name,
|
||||
double value,
|
||||
uint32_t ssrc,
|
||||
const std::string& alg_name) {
|
||||
@ -110,20 +118,9 @@ void Logging::Plot(int figure,
|
||||
ThreadMap::iterator it = thread_map_.find(rtc::CurrentThreadId());
|
||||
assert(it != thread_map_.end());
|
||||
const State& state = it->second.stack.top();
|
||||
std::stringstream ss;
|
||||
ss << ssrc;
|
||||
std::string label = state.tag + ':' + ss.str() + '@' + alg_name;
|
||||
std::string prefix("Available");
|
||||
if (alg_name.compare(0, prefix.length(), prefix) == 0) {
|
||||
std::string receiver("Receiver");
|
||||
size_t start_pos = label.find(receiver);
|
||||
if (start_pos != std::string::npos) {
|
||||
label.replace(start_pos, receiver.length(), "Sender");
|
||||
}
|
||||
}
|
||||
if (state.enabled) {
|
||||
printf("PLOT\t%d\t%s\t%f\t%f\n", figure, label.c_str(),
|
||||
state.timestamp_ms * 0.001, value);
|
||||
printf("PLOT\t%d\t%s:%" PRIu32 "@%s\t%f\t%f\n", figure, name.c_str(), ssrc,
|
||||
alg_name.c_str(), state.timestamp_ms * 0.001, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -183,26 +183,27 @@
|
||||
_4, _5); \
|
||||
} while (0)
|
||||
|
||||
#define BWE_TEST_LOGGING_PLOT(figure, name, time, value) \
|
||||
do { \
|
||||
__BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __PLOT__, name, \
|
||||
static_cast<int64_t>(time), true); \
|
||||
webrtc::testing::bwe::Logging::GetInstance()->Plot(figure, value); \
|
||||
#define BWE_TEST_LOGGING_PLOT(figure, name, time, value) \
|
||||
do { \
|
||||
__BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __PLOT__, name, \
|
||||
static_cast<int64_t>(time), true); \
|
||||
webrtc::testing::bwe::Logging::GetInstance()->Plot(figure, name, value); \
|
||||
} while (0)
|
||||
|
||||
#define BWE_TEST_LOGGING_PLOT_WITH_NAME(figure, name, time, value, alg_name) \
|
||||
do { \
|
||||
__BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __PLOT__, name, \
|
||||
static_cast<int64_t>(time), true); \
|
||||
webrtc::testing::bwe::Logging::GetInstance()->Plot(figure, value, \
|
||||
webrtc::testing::bwe::Logging::GetInstance()->Plot(figure, name, value, \
|
||||
alg_name); \
|
||||
} while (0)
|
||||
|
||||
#define BWE_TEST_LOGGING_PLOT_WITH_SSRC(figure, name, time, value, ssrc) \
|
||||
do { \
|
||||
__BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __PLOT__, name, \
|
||||
static_cast<int64_t>(time), true); \
|
||||
webrtc::testing::bwe::Logging::GetInstance()->Plot(figure, value, ssrc); \
|
||||
#define BWE_TEST_LOGGING_PLOT_WITH_SSRC(figure, name, time, value, ssrc) \
|
||||
do { \
|
||||
__BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __PLOT__, name, \
|
||||
static_cast<int64_t>(time), true); \
|
||||
webrtc::testing::bwe::Logging::GetInstance()->Plot(figure, name, value, \
|
||||
ssrc); \
|
||||
} while (0)
|
||||
|
||||
#define BWE_TEST_LOGGING_PLOT_WITH_NAME_AND_SSRC(figure, name, time, value, \
|
||||
@ -210,8 +211,8 @@
|
||||
do { \
|
||||
__BWE_TEST_LOGGING_CONTEXT_DECLARE(__bwe_log_, __PLOT__, name, \
|
||||
static_cast<int64_t>(time), true); \
|
||||
webrtc::testing::bwe::Logging::GetInstance()->Plot(figure, value, ssrc, \
|
||||
alg_name); \
|
||||
webrtc::testing::bwe::Logging::GetInstance()->Plot(figure, name, value, \
|
||||
ssrc, alg_name); \
|
||||
} while (0)
|
||||
|
||||
#define BWE_TEST_LOGGING_BAR(figure, name, value, flow_id) \
|
||||
@ -279,10 +280,14 @@ class Logging {
|
||||
void SetGlobalEnable(bool enabled);
|
||||
|
||||
void Log(const char format[], ...);
|
||||
void Plot(int figure, double value);
|
||||
void Plot(int figure, double value, const std::string& alg_name);
|
||||
void Plot(int figure, double value, uint32_t ssrc);
|
||||
void Plot(int figure, const std::string& name, double value);
|
||||
void Plot(int figure,
|
||||
const std::string& name,
|
||||
double value,
|
||||
const std::string& alg_name);
|
||||
void Plot(int figure, const std::string& name, double value, uint32_t ssrc);
|
||||
void Plot(int figure,
|
||||
const std::string& name,
|
||||
double value,
|
||||
uint32_t ssrc,
|
||||
const std::string& alg_name);
|
||||
|
||||
@ -124,13 +124,13 @@ void MetricRecorder::PlotAllDynamics() {
|
||||
|
||||
void MetricRecorder::PlotDynamics(int metric) {
|
||||
if (metric == kTotalAvailable) {
|
||||
BWE_TEST_LOGGING_PLOT_WITH_NAME(
|
||||
BWE_TEST_LOGGING_PLOT_WITH_NAME_AND_SSRC(
|
||||
0, plot_information_[kTotalAvailable].prefix, now_ms_,
|
||||
GetTotalAvailableKbps(), "Available");
|
||||
GetTotalAvailableKbps(), flow_id_, "Available");
|
||||
} else if (metric == kAvailablePerFlow) {
|
||||
BWE_TEST_LOGGING_PLOT_WITH_NAME(
|
||||
BWE_TEST_LOGGING_PLOT_WITH_NAME_AND_SSRC(
|
||||
0, plot_information_[kAvailablePerFlow].prefix, now_ms_,
|
||||
GetAvailablePerFlowKbps(), "Available_per_flow");
|
||||
GetAvailablePerFlowKbps(), flow_id_, "Available_per_flow");
|
||||
} else {
|
||||
PlotLine(metric, plot_information_[metric].prefix,
|
||||
plot_information_[metric].time_ms,
|
||||
@ -144,8 +144,9 @@ void MetricRecorder::PlotLine(int windows_id,
|
||||
const std::string& prefix,
|
||||
int64_t time_ms,
|
||||
T y) {
|
||||
BWE_TEST_LOGGING_PLOT_WITH_NAME(windows_id, prefix, time_ms,
|
||||
static_cast<double>(y), algorithm_name_);
|
||||
BWE_TEST_LOGGING_PLOT_WITH_NAME_AND_SSRC(windows_id, prefix, time_ms,
|
||||
static_cast<double>(y), flow_id_,
|
||||
algorithm_name_);
|
||||
}
|
||||
|
||||
void MetricRecorder::UpdateTimeMs(int64_t time_ms) {
|
||||
@ -355,6 +356,8 @@ void MetricRecorder::PlotZero() {
|
||||
for (int i = kThroughput; i <= kLoss; ++i) {
|
||||
if (plot_information_[i].plot) {
|
||||
std::stringstream prefix;
|
||||
// TODO(terelius): Since this does not use the BWE_TEST_LOGGING macros,
|
||||
// it hasn't been kept up to date with the plot format. Remove or fix?
|
||||
prefix << "Receiver_" << flow_id_ << "_" + plot_information_[i].prefix;
|
||||
PlotLine(i, prefix.str(), now_ms_, 0);
|
||||
plot_information_[i].last_plot_ms = now_ms_;
|
||||
|
||||
@ -44,15 +44,15 @@ PacketReceiver::PacketReceiver(PacketProcessorListener* listener,
|
||||
|
||||
// Metric recorder plots them in separated figures,
|
||||
// alignment will take place with the #1 left axis.
|
||||
prefixes.push_back("Throughput_kbps#1");
|
||||
prefixes.push_back("MetricRecorderThroughput_kbps#1");
|
||||
prefixes.push_back("Sending_Estimate_kbps#1");
|
||||
prefixes.push_back("Delay_ms_#1");
|
||||
prefixes.push_back("Packet_Loss_#1");
|
||||
prefixes.push_back("Objective_function_#1");
|
||||
|
||||
// Plot Total/PerFlow Available capacity together with throughputs.
|
||||
prefixes.push_back("Throughput_kbps#1"); // Total Available.
|
||||
prefixes.push_back("Throughput_kbps#1"); // Available per flow.
|
||||
prefixes.push_back("Capacity_kbps#1"); // Total Available.
|
||||
prefixes.push_back("PerFlowCapacity_kbps#1"); // Available per flow.
|
||||
|
||||
bool plot_loss = plot_delay; // Plot loss if delay is plotted.
|
||||
metric_recorder_->SetPlotInformation(prefixes, plot_delay, plot_loss);
|
||||
|
||||
@ -7,11 +7,15 @@
|
||||
# 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.
|
||||
# Able to plot each flow separately. Other plot boxes can be added,
|
||||
# currently one for Throughput, one for Latency and one for Packet Loss.
|
||||
# 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
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy
|
||||
import re
|
||||
@ -20,144 +24,145 @@ 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 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 == 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 generate_label(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):
|
||||
ax = fig.add_subplot(n, 1, i+1)
|
||||
self.subplots[i].plotSubplot(ax)
|
||||
|
||||
|
||||
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 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 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] = []
|
||||
|
||||
if var_name not in self.samples[alg_name].keys():
|
||||
self.samples[alg_name][var_name] = []
|
||||
self.samples[alg_name][ssrc][var_name].append((time, value))
|
||||
|
||||
sample = re.search(r'(\d+\.\d+)\t([-]?\d+\.\d+)', line)
|
||||
def plotSubplot(self, ax):
|
||||
ax.set_xlabel(self.xlabel)
|
||||
ax.set_ylabel(self.ylabel)
|
||||
|
||||
s = (sample.group(1), sample.group(2))
|
||||
self.samples[alg_name][var_name].append(s)
|
||||
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)
|
||||
|
||||
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')
|
||||
ssrc_count = len(self.samples[alg_name].keys())
|
||||
l = generate_label(var_name, ssrc, ssrc_count, alg_name)
|
||||
plt.plot(x, y, label=l, linewidth=2.0)
|
||||
count += 1
|
||||
|
||||
for alg in v.samples.keys():
|
||||
plt.grid(True)
|
||||
if count > 1:
|
||||
plt.legend(loc='best')
|
||||
|
||||
for series in v.samples[alg].keys():
|
||||
|
||||
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)
|
||||
|
||||
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(['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")
|
||||
|
||||
var = []
|
||||
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")
|
||||
|
||||
# Create objects.
|
||||
for variable in variables:
|
||||
var.append(Variable(variable))
|
||||
detector_state = Figure("DetectorState")
|
||||
detector_state.addSubplot(['offset_ms'], "Time (s)", "Offset")
|
||||
detector_state.addSubplot(['gamma_ms'], "Time (s)", "Gamma")
|
||||
|
||||
# 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)
|
||||
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
|
||||
|
||||
matplotlib.rcParams.update({'font.size': 48/len(variables)})
|
||||
|
||||
# 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")
|
||||
# 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__':
|
||||
|
||||
@ -1,87 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2013 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.
|
||||
|
||||
# To set up in e.g. Eclipse, run a separate shell and pipe the output from the
|
||||
# test into this script.
|
||||
#
|
||||
# In Eclipse, that amounts to creating a Run Configuration which starts
|
||||
# "/bin/bash" with the arguments "-c [trunk_path]/out/Debug/modules_unittests
|
||||
# --gtest_filter=*BweTest* | [trunk_path]/webrtc/modules/
|
||||
# remote_bitrate_estimator/test/plot_dynamics.sh
|
||||
|
||||
# This script supports multiple figures (windows), the figure is specified as an
|
||||
# identifier at the first argument after the PLOT command. Each figure has a
|
||||
# single y axis and a dual y axis mode. If any line specifies an axis by ending
|
||||
# with "#<axis number (1 or 2)>" two y axis will be used, the first will be
|
||||
# assumed to represent bitrate (in kbps) and the second will be assumed to
|
||||
# represent time deltas (in ms).
|
||||
|
||||
log=$(</dev/stdin)
|
||||
|
||||
# Plot dynamics.
|
||||
function gen_gnuplot_input {
|
||||
colors=(a7001f 0a60c2 b2582b 21a66c d6604d 4393c3 f4a582 92c5de edcbb7 b1c5d0)
|
||||
plots=$(echo "$log" | grep "^PLOT" | grep "#")
|
||||
# Each figure corresponds to a separate plot window.
|
||||
figures=($(echo "$plots" | cut -f 2 | sort | uniq))
|
||||
|
||||
for figure in "${figures[@]}" ; do
|
||||
# Each data set corresponds to a plot line.
|
||||
data_sets=$(echo "$plots" | grep "^PLOT.$figure" | cut -f 3 | sort | uniq)
|
||||
# Lines can be scaled on the left (1) or right (2) axis.
|
||||
linetypes=($(echo "$data_sets" | grep "#" | cut -d '#' -f 2 | \
|
||||
cut -d '@' -f 1 | uniq))
|
||||
|
||||
# Set plot configurations.
|
||||
echo "reset; "
|
||||
echo "set terminal wxt $figure size 1440,900 font \"Arial,9\"; "
|
||||
echo "set xlabel \"Seconds\"; "
|
||||
if (( "${#linetypes[@]}" > "1" )); then
|
||||
echo "set ylabel 'Bitrate (kbps)';" # Left side.
|
||||
echo "set ytics nomirror;"
|
||||
echo "set y2label 'Time delta (ms)';" # Right side.
|
||||
echo "set y2tics nomirror;"
|
||||
else
|
||||
# Single axis (left side), set its label according to data.
|
||||
y_label=$(echo "$data_sets" | grep "#" | cut -d '#' -f 1 | \
|
||||
cut -d ' ' -f 1 | cut -d '/' -f 3 | sed 's/[0-9]/#/g' | \
|
||||
cut -d '#' -f 3 | head -n 1 | sed 's/_/ /g')
|
||||
echo "set ylabel \"$y_label\";"
|
||||
fi
|
||||
|
||||
i=0
|
||||
echo -n "plot "
|
||||
for set in $data_sets ; do
|
||||
(( i++ )) && echo -n ","
|
||||
echo -n "'-' with "
|
||||
echo -n "linespoints "
|
||||
echo -n "ps 0.5 "
|
||||
echo -n "lc rgbcolor \"#${colors[$(($i % 10))]}\" "
|
||||
if (( "${#linetypes[@]}" > "1" )); then
|
||||
# Multiple sets can have a same line plot.
|
||||
linetype=$(echo "$set" | grep "#" | cut -d '#' -f 2 | cut -d '@' -f 1)
|
||||
if (( "${#linetype}" > "0")); then
|
||||
echo -n "axes x1y$linetype "
|
||||
else
|
||||
# If no line type is specified, but line types are used, we will
|
||||
# default to scale on the left axis.
|
||||
echo -n "axes x1y1 "
|
||||
fi
|
||||
fi
|
||||
echo -n "title \"$set\" "
|
||||
done
|
||||
echo
|
||||
for set in $data_sets ; do
|
||||
echo "$log" | grep "^PLOT.$figure.$set" | cut -f 4,5
|
||||
echo "e"
|
||||
done
|
||||
done
|
||||
}
|
||||
gen_gnuplot_input | gnuplot -persist
|
||||
Loading…
x
Reference in New Issue
Block a user