blob: 4b0889c4fcecb85fe12cff78614dda46b9f5b7ea [file] [log] [blame]
# Copyright 2015-2017 ARM Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""Parse the results from a Workload Automation run and show it in a
"pretty" table
"""
import os
import collections, csv, re
import pandas as pd
from matplotlib import pyplot as plt
class Result(pd.DataFrame):
"""A DataFrame-like class for storing benchmark results"""
def __init__(self, *args, **kwargs):
super(Result, self).__init__(*args, **kwargs)
self.ax = None
def init_fig(self):
_, self.ax = plt.subplots()
def enlarge_axis(self, data):
"""Make sure that the axis don't clobber some of the data"""
(_, _, plot_y_min, plot_y_max) = plt.axis()
concat_data = pd.concat(data[s] for s in data)
data_min = min(concat_data)
data_max = max(concat_data)
# A good margin can be 10% of the data range
margin = (data_max - data_min) / 10
if margin < 1:
margin = 1
update_axis = False
if data_min <= plot_y_min:
plot_y_min = data_min - margin
update_axis = True
if data_max >= plot_y_max:
plot_y_max = data_max + margin
update_axis = True
if update_axis:
self.ax.set_ylim(plot_y_min, plot_y_max)
def plot_results_benchmark(self, benchmark, title=None):
"""Plot the results of the execution of a given benchmark
A title is added to the plot if title is not supplied
"""
if title is None:
title = benchmark.replace('_', ' ')
title = title.title()
self[benchmark].plot(ax=self.ax, kind="bar", title=title)
plt.legend(bbox_to_anchor=(1.05, .5), loc=6)
def plot_results(self):
for bench in self.columns.levels[0]:
self.plot_results_benchmark(bench)
def get_run_number(metric):
found = False
run_number = None
if re.match("Overall_Score|score|FPS", metric):
found = True
match = re.search(r"(.+)[ _](\d+)", metric)
if match:
run_number = int(match.group(2))
if match.group(1) == "Overall_Score":
run_number -= 1
else:
run_number = 0
return (found, run_number)
def get_results(path=".", name=None):
"""Return a pd.DataFrame with the results
The DataFrame's rows are the scores. The first column is the
benchmark name and the second the id within it. For benchmarks
that have a score result, that's what's used. For benchmarks with
FPS_* result, that's the score. E.g. glbenchmarks "score" is it's
fps.
An optional name argument can be passed. If supplied, it overrides
the name in the results file.
"""
bench_dict = collections.OrderedDict()
if os.path.isdir(path):
path = os.path.join(path, "results.csv")
with open(path) as fin:
results = csv.reader(fin)
for row in results:
(is_result, run_number) = get_run_number(row[3])
if is_result:
if name:
run_id = name
else:
run_id = re.sub(r"_\d+", r"", row[0])
bench = row[1]
try:
result = int(row[4])
except ValueError:
result = float(row[4])
if bench in bench_dict:
if run_id in bench_dict[bench]:
if run_number not in bench_dict[bench][run_id]:
bench_dict[bench][run_id][run_number] = result
else:
bench_dict[bench][run_id] = {run_number: result}
else:
bench_dict[bench] = {run_id: {run_number: result}}
bench_dfrs = {}
for bench, run_id_dict in bench_dict.iteritems():
bench_dfrs[bench] = pd.DataFrame(run_id_dict)
return Result(pd.concat(bench_dfrs.values(), axis=1,
keys=bench_dfrs.keys()))
def combine_results(data):
"""Combine two DataFrame results into one
The data should be an array of results like the ones returned by
get_results() or have the same structure. The returned DataFrame
has two column indexes. The first one is the benchmark and the
second one is the key for the result.
"""
res_dict = {}
for benchmark in data[0].columns.levels[0]:
concat_objs = [d[benchmark] for d in data]
res_dict[benchmark] = pd.concat(concat_objs, axis=1)
combined = pd.concat(res_dict.values(), axis=1, keys=res_dict.keys())
return Result(combined)