blob: b8e25d5fd8adc59ada7ea18f72d3af0e49c7be17 [file] [log] [blame]
import numpy
import re
def IsFloat(text):
if text is None:
return False
try:
float(text)
return True
except ValueError:
return False
def RemoveTrailingZeros(x):
ret = x
ret = re.sub('\.0*$', '', ret)
ret = re.sub('(\.[1-9]*)0+$', '\\1', ret)
return ret
def HumanizeFloat(x, n=2):
if not IsFloat(x):
return x
digits = re.findall('[0-9.]', str(x))
decimal_found = False
ret = ''
sig_figs = 0
for digit in digits:
if digit == '.':
decimal_found = True
elif sig_figs != 0 or digit != '0':
sig_figs += 1
if decimal_found and sig_figs >= n:
break
ret += digit
return ret
def GetNSigFigs(x, n=2):
if not IsFloat(x):
return x
my_fmt = '%.' + str(n - 1) + 'e'
x_string = my_fmt % x
f = float(x_string)
return f
def GetFormattedPercent(baseline, other, bad_result='--'):
result = '%8s' % GetPercent(baseline, other, bad_result)
return result
def GetPercent(baseline, other, bad_result='--'):
result = bad_result
if IsFloat(baseline) and IsFloat(other):
try:
pct = (float(other) / float(baseline) - 1) * 100
result = '%+1.1f' % pct
except ZeroDivisionError:
pass
return result
def FitString(text, length):
if len(text) == length:
return text
elif len(text) > length:
return text[-length:]
else:
fmt = '%%%ds' % length
return fmt % text
class TableFormatter(object):
def __init__(self):
self.d = '\t'
self.bad_result = 'x'
def GetTablePercents(self, table):
# Assumes table is not transposed.
pct_table = []
pct_table.append(table[0])
for i in range(1, len(table)):
row = []
row.append(table[i][0])
for j in range(1, len(table[0])):
c = table[i][j]
b = table[i][1]
p = GetPercent(b, c, self.bad_result)
row.append(p)
pct_table.append(row)
return pct_table
def FormatFloat(self, c, max_length=8):
if not IsFloat(c):
return c
f = float(c)
ret = HumanizeFloat(f, 4)
ret = RemoveTrailingZeros(ret)
if len(ret) > max_length:
ret = '%1.1ef' % f
return ret
def TransposeTable(self, table):
transposed_table = []
for i in range(len(table[0])):
row = []
for j in range(len(table)):
row.append(table[j][i])
transposed_table.append(row)
return transposed_table
def GetTableLabels(self, table):
ret = ''
header = table[0]
for i in range(1, len(header)):
ret += '%d: %s\n' % (i, header[i])
return ret
def GetFormattedTable(self,
table,
transposed=False,
first_column_width=30,
column_width=14,
percents_only=True,
fit_string=True):
o = ''
pct_table = self.GetTablePercents(table)
if transposed == True:
table = self.TransposeTable(table)
pct_table = self.TransposeTable(table)
for i in range(0, len(table)):
for j in range(len(table[0])):
if j == 0:
width = first_column_width
else:
width = column_width
c = table[i][j]
p = pct_table[i][j]
# Replace labels with numbers: 0... n
if IsFloat(c):
c = self.FormatFloat(c)
if IsFloat(p) and not percents_only:
p = '%s%%' % p
# Print percent values side by side.
if j != 0:
if percents_only:
c = '%s' % p
else:
c = '%s (%s)' % (c, p)
if i == 0 and j != 0:
c = str(j)
if fit_string:
o += FitString(c, width) + self.d
else:
o += c + self.d
o += '\n'
return o
def GetGroups(self, table):
labels = table[0]
groups = []
group_dict = {}
for i in range(1, len(labels)):
label = labels[i]
stripped_label = self.GetStrippedLabel(label)
if stripped_label not in group_dict:
group_dict[stripped_label] = len(groups)
groups.append([])
groups[group_dict[stripped_label]].append(i)
return groups
def GetSummaryTableValues(self, table):
# First get the groups
groups = self.GetGroups(table)
summary_table = []
labels = table[0]
summary_labels = ['Summary Table']
for group in groups:
label = labels[group[0]]
stripped_label = self.GetStrippedLabel(label)
group_label = '%s (%d runs)' % (stripped_label, len(group))
summary_labels.append(group_label)
summary_table.append(summary_labels)
for i in range(1, len(table)):
row = table[i]
summary_row = [row[0]]
for group in groups:
group_runs = []
for index in group:
group_runs.append(row[index])
group_run = self.AggregateResults(group_runs)
summary_row.append(group_run)
summary_table.append(summary_row)
return summary_table
# Drop N% slowest and M% fastest numbers, and return arithmean of
# the remaining.
@staticmethod
def AverageWithDrops(numbers, slow_percent=20, fast_percent=20):
sorted_numbers = list(numbers)
sorted_numbers.sort()
num_slow = int(slow_percent / 100.0 * len(sorted_numbers))
num_fast = int(fast_percent / 100.0 * len(sorted_numbers))
sorted_numbers = sorted_numbers[num_slow:]
if num_fast:
sorted_numbers = sorted_numbers[:-num_fast]
return numpy.average(sorted_numbers)
@staticmethod
def AggregateResults(group_results):
ret = ''
if not group_results:
return ret
all_floats = True
all_passes = True
all_fails = True
for group_result in group_results:
if not IsFloat(group_result):
all_floats = False
if group_result != 'PASSED':
all_passes = False
if group_result != 'FAILED':
all_fails = False
if all_floats == True:
float_results = [float(v) for v in group_results]
ret = '%f' % TableFormatter.AverageWithDrops(float_results)
# Add this line for standard deviation.
### ret += " %f" % numpy.std(float_results)
elif all_passes == True:
ret = 'ALL_PASS'
elif all_fails == True:
ret = 'ALL_FAILS'
return ret
@staticmethod
def GetStrippedLabel(label):
return re.sub('\s*\S+:\S+\s*', '', label)
### return re.sub("\s*remote:\S*\s*i:\d+$", "", label)
@staticmethod
def GetLabelWithIteration(label, iteration):
return '%s i:%d' % (label, iteration)