Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/ts/misc/table_formatter.py
16339 views
1
#!/usr/bin/env python
2
3
from __future__ import print_function
4
import sys, re, os.path, cgi, stat, math
5
from optparse import OptionParser
6
from color import getColorizer, dummyColorizer
7
8
class tblCell(object):
9
def __init__(self, text, value = None, props = None):
10
self.text = text
11
self.value = value
12
self.props = props
13
14
class tblColumn(object):
15
def __init__(self, caption, title = None, props = None):
16
self.text = caption
17
self.title = title
18
self.props = props
19
20
class tblRow(object):
21
def __init__(self, colsNum, props = None):
22
self.cells = [None] * colsNum
23
self.props = props
24
25
def htmlEncode(str):
26
return '<br/>'.join([cgi.escape(s) for s in str])
27
28
class table(object):
29
def_align = "left"
30
def_valign = "middle"
31
def_color = None
32
def_colspan = 1
33
def_rowspan = 1
34
def_bold = False
35
def_italic = False
36
def_text="-"
37
38
def __init__(self, caption = None, format=None):
39
self.format = format
40
self.is_markdown = self.format == 'markdown'
41
self.columns = {}
42
self.rows = []
43
self.ridx = -1;
44
self.caption = caption
45
pass
46
47
def newRow(self, **properties):
48
if len(self.rows) - 1 == self.ridx:
49
self.rows.append(tblRow(len(self.columns), properties))
50
else:
51
self.rows[self.ridx + 1].props = properties
52
self.ridx += 1
53
return self.rows[self.ridx]
54
55
def trimLastRow(self):
56
if self.rows:
57
self.rows.pop()
58
if self.ridx >= len(self.rows):
59
self.ridx = len(self.rows) - 1
60
61
def newColumn(self, name, caption, title = None, **properties):
62
if name in self.columns:
63
index = self.columns[name].index
64
else:
65
index = len(self.columns)
66
if isinstance(caption, tblColumn):
67
caption.index = index
68
self.columns[name] = caption
69
return caption
70
else:
71
col = tblColumn(caption, title, properties)
72
col.index = index
73
self.columns[name] = col
74
return col
75
76
def getColumn(self, name):
77
if isinstance(name, str):
78
return self.columns.get(name, None)
79
else:
80
vals = [v for v in self.columns.values() if v.index == name]
81
if vals:
82
return vals[0]
83
return None
84
85
def newCell(self, col_name, text, value = None, **properties):
86
if self.ridx < 0:
87
self.newRow()
88
col = self.getColumn(col_name)
89
row = self.rows[self.ridx]
90
if not col:
91
return None
92
if isinstance(text, tblCell):
93
cl = text
94
else:
95
cl = tblCell(text, value, properties)
96
row.cells[col.index] = cl
97
return cl
98
99
def layoutTable(self):
100
columns = self.columns.values()
101
columns = sorted(columns, key=lambda c: c.index)
102
103
colspanned = []
104
rowspanned = []
105
106
self.headerHeight = 1
107
rowsToAppend = 0
108
109
for col in columns:
110
self.measureCell(col)
111
if col.height > self.headerHeight:
112
self.headerHeight = col.height
113
col.minwidth = col.width
114
col.line = None
115
116
for r in range(len(self.rows)):
117
row = self.rows[r]
118
row.minheight = 1
119
for i in range(len(row.cells)):
120
cell = row.cells[i]
121
if row.cells[i] is None:
122
continue
123
cell.line = None
124
self.measureCell(cell)
125
colspan = int(self.getValue("colspan", cell))
126
rowspan = int(self.getValue("rowspan", cell))
127
if colspan > 1:
128
colspanned.append((r,i))
129
if i + colspan > len(columns):
130
colspan = len(columns) - i
131
cell.colspan = colspan
132
#clear spanned cells
133
for j in range(i+1, min(len(row.cells), i + colspan)):
134
row.cells[j] = None
135
elif columns[i].minwidth < cell.width:
136
columns[i].minwidth = cell.width
137
if rowspan > 1:
138
rowspanned.append((r,i))
139
rowsToAppend2 = r + colspan - len(self.rows)
140
if rowsToAppend2 > rowsToAppend:
141
rowsToAppend = rowsToAppend2
142
cell.rowspan = rowspan
143
#clear spanned cells
144
for j in range(r+1, min(len(self.rows), r + rowspan)):
145
if len(self.rows[j].cells) > i:
146
self.rows[j].cells[i] = None
147
elif row.minheight < cell.height:
148
row.minheight = cell.height
149
150
self.ridx = len(self.rows) - 1
151
for r in range(rowsToAppend):
152
self.newRow()
153
self.rows[len(self.rows) - 1].minheight = 1
154
155
while colspanned:
156
colspanned_new = []
157
for r, c in colspanned:
158
cell = self.rows[r].cells[c]
159
sum([col.minwidth for col in columns[c:c + cell.colspan]])
160
cell.awailable = sum([col.minwidth for col in columns[c:c + cell.colspan]]) + cell.colspan - 1
161
if cell.awailable < cell.width:
162
colspanned_new.append((r,c))
163
colspanned = colspanned_new
164
if colspanned:
165
r,c = colspanned[0]
166
cell = self.rows[r].cells[c]
167
cols = columns[c:c + cell.colspan]
168
total = cell.awailable - cell.colspan + 1
169
budget = cell.width - cell.awailable
170
spent = 0
171
s = 0
172
for col in cols:
173
s += col.minwidth
174
addition = s * budget / total - spent
175
spent += addition
176
col.minwidth += addition
177
178
while rowspanned:
179
rowspanned_new = []
180
for r, c in rowspanned:
181
cell = self.rows[r].cells[c]
182
cell.awailable = sum([row.minheight for row in self.rows[r:r + cell.rowspan]])
183
if cell.awailable < cell.height:
184
rowspanned_new.append((r,c))
185
rowspanned = rowspanned_new
186
if rowspanned:
187
r,c = rowspanned[0]
188
cell = self.rows[r].cells[c]
189
rows = self.rows[r:r + cell.rowspan]
190
total = cell.awailable
191
budget = cell.height - cell.awailable
192
spent = 0
193
s = 0
194
for row in rows:
195
s += row.minheight
196
addition = s * budget / total - spent
197
spent += addition
198
row.minheight += addition
199
200
return columns
201
202
def measureCell(self, cell):
203
text = self.getValue("text", cell)
204
cell.text = self.reformatTextValue(text)
205
cell.height = len(cell.text)
206
cell.width = len(max(cell.text, key = lambda line: len(line)))
207
208
def reformatTextValue(self, value):
209
if sys.version_info >= (2,7):
210
unicode = str
211
if isinstance(value, str):
212
vstr = value
213
elif isinstance(value, unicode):
214
vstr = str(value)
215
else:
216
try:
217
vstr = '\n'.join([str(v) for v in value])
218
except TypeError:
219
vstr = str(value)
220
return vstr.splitlines()
221
222
def adjustColWidth(self, cols, width):
223
total = sum([c.minWidth for c in cols])
224
if total + len(cols) - 1 >= width:
225
return
226
budget = width - len(cols) + 1 - total
227
spent = 0
228
s = 0
229
for col in cols:
230
s += col.minWidth
231
addition = s * budget / total - spent
232
spent += addition
233
col.minWidth += addition
234
235
def getValue(self, name, *elements):
236
for el in elements:
237
try:
238
return getattr(el, name)
239
except AttributeError:
240
pass
241
try:
242
val = el.props[name]
243
if val:
244
return val
245
except AttributeError:
246
pass
247
except KeyError:
248
pass
249
try:
250
return getattr(self.__class__, "def_" + name)
251
except AttributeError:
252
return None
253
254
def consolePrintTable(self, out):
255
columns = self.layoutTable()
256
colrizer = getColorizer(out) if not self.is_markdown else dummyColorizer(out)
257
258
if self.caption:
259
out.write("%s%s%s" % ( os.linesep, os.linesep.join(self.reformatTextValue(self.caption)), os.linesep * 2))
260
261
headerRow = tblRow(len(columns), {"align": "center", "valign": "top", "bold": True, "header": True})
262
headerRow.cells = columns
263
headerRow.minheight = self.headerHeight
264
265
self.consolePrintRow2(colrizer, headerRow, columns)
266
267
for i in range(0, len(self.rows)):
268
self.consolePrintRow2(colrizer, i, columns)
269
270
def consolePrintRow2(self, out, r, columns):
271
if isinstance(r, tblRow):
272
row = r
273
r = -1
274
else:
275
row = self.rows[r]
276
277
#evaluate initial values for line numbers
278
i = 0
279
while i < len(row.cells):
280
cell = row.cells[i]
281
colspan = self.getValue("colspan", cell)
282
if cell is not None:
283
cell.wspace = sum([col.minwidth for col in columns[i:i + colspan]]) + colspan - 1
284
if cell.line is None:
285
if r < 0:
286
rows = [row]
287
else:
288
rows = self.rows[r:r + self.getValue("rowspan", cell)]
289
cell.line = self.evalLine(cell, rows, columns[i])
290
if len(rows) > 1:
291
for rw in rows:
292
rw.cells[i] = cell
293
i += colspan
294
295
#print content
296
if self.is_markdown:
297
out.write("|")
298
for c in row.cells:
299
text = ' '.join(self.getValue('text', c) or [])
300
out.write(text + "|")
301
out.write(os.linesep)
302
else:
303
for ln in range(row.minheight):
304
i = 0
305
while i < len(row.cells):
306
if i > 0:
307
out.write(" ")
308
cell = row.cells[i]
309
column = columns[i]
310
if cell is None:
311
out.write(" " * column.minwidth)
312
i += 1
313
else:
314
self.consolePrintLine(cell, row, column, out)
315
i += self.getValue("colspan", cell)
316
if self.is_markdown:
317
out.write("|")
318
out.write(os.linesep)
319
320
if self.is_markdown and row.props.get('header', False):
321
out.write("|")
322
for th in row.cells:
323
align = self.getValue("align", th)
324
if align == 'center':
325
out.write(":-:|")
326
elif align == 'right':
327
out.write("--:|")
328
else:
329
out.write("---|")
330
out.write(os.linesep)
331
332
def consolePrintLine(self, cell, row, column, out):
333
if cell.line < 0 or cell.line >= cell.height:
334
line = ""
335
else:
336
line = cell.text[cell.line]
337
width = cell.wspace
338
align = self.getValue("align", ((None, cell)[isinstance(cell, tblCell)]), row, column)
339
340
if align == "right":
341
pattern = "%" + str(width) + "s"
342
elif align == "center":
343
pattern = "%" + str((width - len(line)) // 2 + len(line)) + "s" + " " * (width - len(line) - (width - len(line)) // 2)
344
else:
345
pattern = "%-" + str(width) + "s"
346
347
out.write(pattern % line, color = self.getValue("color", cell, row, column))
348
cell.line += 1
349
350
def evalLine(self, cell, rows, column):
351
height = cell.height
352
valign = self.getValue("valign", cell, rows[0], column)
353
space = sum([row.minheight for row in rows])
354
if valign == "bottom":
355
return height - space
356
if valign == "middle":
357
return (height - space + 1) // 2
358
return 0
359
360
def htmlPrintTable(self, out, embeedcss = False):
361
columns = self.layoutTable()
362
363
if embeedcss:
364
out.write("<div style=\"font-family: Lucida Console, Courier New, Courier;font-size: 16px;color:#3e4758;\">\n<table style=\"background:none repeat scroll 0 0 #FFFFFF;border-collapse:collapse;font-family:'Lucida Sans Unicode','Lucida Grande',Sans-Serif;font-size:14px;margin:20px;text-align:left;width:480px;margin-left: auto;margin-right: auto;white-space:nowrap;\">\n")
365
else:
366
out.write("<div class=\"tableFormatter\">\n<table class=\"tbl\">\n")
367
if self.caption:
368
if embeedcss:
369
out.write(" <caption style=\"font:italic 16px 'Trebuchet MS',Verdana,Arial,Helvetica,sans-serif;padding:0 0 5px;text-align:right;white-space:normal;\">%s</caption>\n" % htmlEncode(self.reformatTextValue(self.caption)))
370
else:
371
out.write(" <caption>%s</caption>\n" % htmlEncode(self.reformatTextValue(self.caption)))
372
out.write(" <thead>\n")
373
374
headerRow = tblRow(len(columns), {"align": "center", "valign": "top", "bold": True, "header": True})
375
headerRow.cells = columns
376
377
header_rows = [headerRow]
378
header_rows.extend([row for row in self.rows if self.getValue("header")])
379
last_row = header_rows[len(header_rows) - 1]
380
381
for row in header_rows:
382
out.write(" <tr>\n")
383
for th in row.cells:
384
align = self.getValue("align", ((None, th)[isinstance(th, tblCell)]), row, row)
385
valign = self.getValue("valign", th, row)
386
cssclass = self.getValue("cssclass", th)
387
attr = ""
388
if align:
389
attr += " align=\"%s\"" % align
390
if valign:
391
attr += " valign=\"%s\"" % valign
392
if cssclass:
393
attr += " class=\"%s\"" % cssclass
394
css = ""
395
if embeedcss:
396
css = " style=\"border:none;color:#003399;font-size:16px;font-weight:normal;white-space:nowrap;padding:3px 10px;\""
397
if row == last_row:
398
css = css[:-1] + "padding-bottom:5px;\""
399
out.write(" <th%s%s>\n" % (attr, css))
400
if th is not None:
401
out.write(" %s\n" % htmlEncode(th.text))
402
out.write(" </th>\n")
403
out.write(" </tr>\n")
404
405
out.write(" </thead>\n <tbody>\n")
406
407
rows = [row for row in self.rows if not self.getValue("header")]
408
for r in range(len(rows)):
409
row = rows[r]
410
rowattr = ""
411
cssclass = self.getValue("cssclass", row)
412
if cssclass:
413
rowattr += " class=\"%s\"" % cssclass
414
out.write(" <tr%s>\n" % (rowattr))
415
i = 0
416
while i < len(row.cells):
417
column = columns[i]
418
td = row.cells[i]
419
if isinstance(td, int):
420
i += td
421
continue
422
colspan = self.getValue("colspan", td)
423
rowspan = self.getValue("rowspan", td)
424
align = self.getValue("align", td, row, column)
425
valign = self.getValue("valign", td, row, column)
426
color = self.getValue("color", td, row, column)
427
bold = self.getValue("bold", td, row, column)
428
italic = self.getValue("italic", td, row, column)
429
style = ""
430
attr = ""
431
if color:
432
style += "color:%s;" % color
433
if bold:
434
style += "font-weight: bold;"
435
if italic:
436
style += "font-style: italic;"
437
if align and align != "left":
438
attr += " align=\"%s\"" % align
439
if valign and valign != "middle":
440
attr += " valign=\"%s\"" % valign
441
if colspan > 1:
442
attr += " colspan=\"%s\"" % colspan
443
if rowspan > 1:
444
attr += " rowspan=\"%s\"" % rowspan
445
for q in range(r+1, min(r+rowspan, len(rows))):
446
rows[q].cells[i] = colspan
447
if style:
448
attr += " style=\"%s\"" % style
449
css = ""
450
if embeedcss:
451
css = " style=\"border:none;border-bottom:1px solid #CCCCCC;color:#666699;padding:6px 8px;white-space:nowrap;\""
452
if r == 0:
453
css = css[:-1] + "border-top:2px solid #6678B1;\""
454
out.write(" <td%s%s>\n" % (attr, css))
455
if td is not None:
456
out.write(" %s\n" % htmlEncode(td.text))
457
out.write(" </td>\n")
458
i += colspan
459
out.write(" </tr>\n")
460
461
out.write(" </tbody>\n</table>\n</div>\n")
462
463
def htmlPrintHeader(out, title = None):
464
if title:
465
titletag = "<title>%s</title>\n" % htmlEncode([str(title)])
466
else:
467
titletag = ""
468
out.write("""<!DOCTYPE HTML>
469
<html>
470
<head>
471
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
472
%s<style type="text/css">
473
html, body {font-family: Lucida Console, Courier New, Courier;font-size: 16px;color:#3e4758;}
474
.tbl{background:none repeat scroll 0 0 #FFFFFF;border-collapse:collapse;font-family:"Lucida Sans Unicode","Lucida Grande",Sans-Serif;font-size:14px;margin:20px;text-align:left;width:480px;margin-left: auto;margin-right: auto;white-space:nowrap;}
475
.tbl span{display:block;white-space:nowrap;}
476
.tbl thead tr:last-child th {padding-bottom:5px;}
477
.tbl tbody tr:first-child td {border-top:3px solid #6678B1;}
478
.tbl th{border:none;color:#003399;font-size:16px;font-weight:normal;white-space:nowrap;padding:3px 10px;}
479
.tbl td{border:none;border-bottom:1px solid #CCCCCC;color:#666699;padding:6px 8px;white-space:nowrap;}
480
.tbl tbody tr:hover td{color:#000099;}
481
.tbl caption{font:italic 16px "Trebuchet MS",Verdana,Arial,Helvetica,sans-serif;padding:0 0 5px;text-align:right;white-space:normal;}
482
.firstingroup {border-top:2px solid #6678B1;}
483
</style>
484
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
485
<script type="text/javascript">
486
function abs(val) { return val < 0 ? -val : val }
487
$(function(){
488
//generate filter rows
489
$("div.tableFormatter table.tbl").each(function(tblIdx, tbl) {
490
var head = $("thead", tbl)
491
var filters = $("<tr></tr>")
492
var hasAny = false
493
$("tr:first th", head).each(function(colIdx, col) {
494
col = $(col)
495
var cell
496
var id = "t" + tblIdx + "r" + colIdx
497
if (col.hasClass("col_name")){
498
cell = $("<th><input id='" + id + "' name='" + id + "' type='text' style='width:100%%' class='filter_col_name' title='Regular expression for name filtering (&quot;resize.*640x480&quot; - resize tests on VGA resolution)'></input></th>")
499
hasAny = true
500
}
501
else if (col.hasClass("col_rel")){
502
cell = $("<th><input id='" + id + "' name='" + id + "' type='text' style='width:100%%' class='filter_col_rel' title='Filter out lines with a x-factor of acceleration less than Nx'></input></th>")
503
hasAny = true
504
}
505
else if (col.hasClass("col_cr")){
506
cell = $("<th><input id='" + id + "' name='" + id + "' type='text' style='width:100%%' class='filter_col_cr' title='Filter out lines with a percentage of acceleration less than N%%'></input></th>")
507
hasAny = true
508
}
509
else
510
cell = $("<th></th>")
511
cell.appendTo(filters)
512
})
513
514
if (hasAny){
515
$(tbl).wrap("<form id='form_t" + tblIdx + "' method='get' action=''></form>")
516
$("<input it='test' type='submit' value='Apply Filters' style='margin-left:10px;'></input>")
517
.appendTo($("th:last", filters.appendTo(head)))
518
}
519
})
520
521
//get filter values
522
var vars = []
523
var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&')
524
for(var i = 0; i < hashes.length; ++i)
525
{
526
hash = hashes[i].split('=')
527
vars.push(decodeURIComponent(hash[0]))
528
vars[decodeURIComponent(hash[0])] = decodeURIComponent(hash[1]);
529
}
530
531
//set filter values
532
for(var i = 0; i < vars.length; ++i)
533
$("#" + vars[i]).val(vars[vars[i]])
534
535
//apply filters
536
$("div.tableFormatter table.tbl").each(function(tblIdx, tbl) {
537
filters = $("input:text", tbl)
538
var predicate = function(row) {return true;}
539
var empty = true
540
$.each($("input:text", tbl), function(i, flt) {
541
flt = $(flt)
542
var val = flt.val()
543
var pred = predicate;
544
if(val) {
545
empty = false
546
var colIdx = parseInt(flt.attr("id").slice(flt.attr("id").indexOf('r') + 1))
547
if(flt.hasClass("filter_col_name")) {
548
var re = new RegExp(val);
549
predicate = function(row) {
550
if (re.exec($(row.get(colIdx)).text()) == null)
551
return false
552
return pred(row)
553
}
554
} else if(flt.hasClass("filter_col_rel")) {
555
var percent = parseFloat(val)
556
if (percent < 0) {
557
predicate = function(row) {
558
var val = parseFloat($(row.get(colIdx)).text())
559
if (!val || val >= 1 || val > 1+percent)
560
return false
561
return pred(row)
562
}
563
} else {
564
predicate = function(row) {
565
var val = parseFloat($(row.get(colIdx)).text())
566
if (!val || val < percent)
567
return false
568
return pred(row)
569
}
570
}
571
} else if(flt.hasClass("filter_col_cr")) {
572
var percent = parseFloat(val)
573
predicate = function(row) {
574
var val = parseFloat($(row.get(colIdx)).text())
575
if (!val || val < percent)
576
return false
577
return pred(row)
578
}
579
}
580
}
581
});
582
if (!empty){
583
$("tbody tr", tbl).each(function (i, tbl_row) {
584
if(!predicate($("td", tbl_row)))
585
$(tbl_row).remove()
586
})
587
if($("tbody tr", tbl).length == 0) {
588
$("<tr><td colspan='"+$("thead tr:first th", tbl).length+"'>No results mathing your search criteria</td></tr>")
589
.appendTo($("tbody", tbl))
590
}
591
}
592
})
593
})
594
</script>
595
</head>
596
<body>
597
""" % titletag)
598
599
def htmlPrintFooter(out):
600
out.write("</body>\n</html>")
601
602
def getStdoutFilename():
603
try:
604
if os.name == "nt":
605
import msvcrt, ctypes
606
handle = msvcrt.get_osfhandle(sys.stdout.fileno())
607
size = ctypes.c_ulong(1024)
608
nameBuffer = ctypes.create_string_buffer(size.value)
609
ctypes.windll.kernel32.GetFinalPathNameByHandleA(handle, nameBuffer, size, 4)
610
return nameBuffer.value
611
else:
612
return os.readlink('/proc/self/fd/1')
613
except:
614
return ""
615
616
def detectHtmlOutputType(requestedType):
617
if requestedType in ['txt', 'markdown']:
618
return False
619
elif requestedType in ["html", "moinwiki"]:
620
return True
621
else:
622
if sys.stdout.isatty():
623
return False
624
else:
625
outname = getStdoutFilename()
626
if outname:
627
if outname.endswith(".htm") or outname.endswith(".html"):
628
return True
629
else:
630
return False
631
else:
632
return False
633
634
def getRelativeVal(test, test0, metric):
635
if not test or not test0:
636
return None
637
val0 = test0.get(metric, "s")
638
if not val0:
639
return None
640
val = test.get(metric, "s")
641
if not val or val == 0:
642
return None
643
return float(val0)/val
644
645
def getCycleReduction(test, test0, metric):
646
if not test or not test0:
647
return None
648
val0 = test0.get(metric, "s")
649
if not val0 or val0 == 0:
650
return None
651
val = test.get(metric, "s")
652
if not val:
653
return None
654
return (1.0-float(val)/val0)*100
655
656
def getScore(test, test0, metric):
657
if not test or not test0:
658
return None
659
m0 = float(test.get("gmean", None))
660
m1 = float(test0.get("gmean", None))
661
if m0 == 0 or m1 == 0:
662
return None
663
s0 = float(test.get("gstddev", None))
664
s1 = float(test0.get("gstddev", None))
665
s = math.sqrt(s0*s0 + s1*s1)
666
m0 = math.log(m0)
667
m1 = math.log(m1)
668
if s == 0:
669
return None
670
return (m0-m1)/s
671
672
metrix_table = \
673
{
674
"name": ("Name of Test", lambda test,test0,units: str(test)),
675
676
"samples": ("Number of\ncollected samples", lambda test,test0,units: test.get("samples", units)),
677
"outliers": ("Number of\noutliers", lambda test,test0,units: test.get("outliers", units)),
678
679
"gmean": ("Geometric mean", lambda test,test0,units: test.get("gmean", units)),
680
"mean": ("Mean", lambda test,test0,units: test.get("mean", units)),
681
"min": ("Min", lambda test,test0,units: test.get("min", units)),
682
"median": ("Median", lambda test,test0,units: test.get("median", units)),
683
"stddev": ("Standard deviation", lambda test,test0,units: test.get("stddev", units)),
684
"gstddev": ("Standard deviation of Ln(time)", lambda test,test0,units: test.get("gstddev")),
685
686
"gmean%": ("Geometric mean (relative)", lambda test,test0,units: getRelativeVal(test, test0, "gmean")),
687
"mean%": ("Mean (relative)", lambda test,test0,units: getRelativeVal(test, test0, "mean")),
688
"min%": ("Min (relative)", lambda test,test0,units: getRelativeVal(test, test0, "min")),
689
"median%": ("Median (relative)", lambda test,test0,units: getRelativeVal(test, test0, "median")),
690
"stddev%": ("Standard deviation (relative)", lambda test,test0,units: getRelativeVal(test, test0, "stddev")),
691
"gstddev%": ("Standard deviation of Ln(time) (relative)", lambda test,test0,units: getRelativeVal(test, test0, "gstddev")),
692
693
"gmean$": ("Geometric mean (cycle reduction)", lambda test,test0,units: getCycleReduction(test, test0, "gmean")),
694
"mean$": ("Mean (cycle reduction)", lambda test,test0,units: getCycleReduction(test, test0, "mean")),
695
"min$": ("Min (cycle reduction)", lambda test,test0,units: getCycleReduction(test, test0, "min")),
696
"median$": ("Median (cycle reduction)", lambda test,test0,units: getCycleReduction(test, test0, "median")),
697
"stddev$": ("Standard deviation (cycle reduction)", lambda test,test0,units: getCycleReduction(test, test0, "stddev")),
698
"gstddev$": ("Standard deviation of Ln(time) (cycle reduction)", lambda test,test0,units: getCycleReduction(test, test0, "gstddev")),
699
700
"score": ("SCORE", lambda test,test0,units: getScore(test, test0, "gstddev")),
701
}
702
703
def formatValue(val, metric, units = None):
704
if val is None:
705
return "-"
706
if metric.endswith("%"):
707
return "%.2f" % val
708
if metric.endswith("$"):
709
return "%.2f%%" % val
710
if metric.endswith("S"):
711
if val > 3.5:
712
return "SLOWER"
713
if val < -3.5:
714
return "FASTER"
715
if val > -1.5 and val < 1.5:
716
return " "
717
if val < 0:
718
return "faster"
719
if val > 0:
720
return "slower"
721
#return "%.4f" % val
722
if units:
723
return "%.3f %s" % (val, units)
724
else:
725
return "%.3f" % val
726
727
if __name__ == "__main__":
728
if len(sys.argv) < 2:
729
print("Usage:\n", os.path.basename(sys.argv[0]), "<log_name>.xml")
730
exit(0)
731
732
parser = OptionParser()
733
parser.add_option("-o", "--output", dest="format", help="output results in text format (can be 'txt', 'html', 'markdown' or 'auto' - default)", metavar="FMT", default="auto")
734
parser.add_option("-m", "--metric", dest="metric", help="output metric", metavar="NAME", default="gmean")
735
parser.add_option("-u", "--units", dest="units", help="units for output values (s, ms (default), us, ns or ticks)", metavar="UNITS", default="ms")
736
(options, args) = parser.parse_args()
737
738
options.generateHtml = detectHtmlOutputType(options.format)
739
if options.metric not in metrix_table:
740
options.metric = "gmean"
741
742
#print options
743
#print args
744
745
# tbl = table()
746
# tbl.newColumn("first", "qqqq", align = "left")
747
# tbl.newColumn("second", "wwww\nz\nx\n")
748
# tbl.newColumn("third", "wwasdas")
749
#
750
# tbl.newCell(0, "ccc111", align = "right")
751
# tbl.newCell(1, "dddd1")
752
# tbl.newCell(2, "8768756754")
753
# tbl.newRow()
754
# tbl.newCell(0, "1\n2\n3\n4\n5\n6\n7", align = "center", colspan = 2, rowspan = 2)
755
# tbl.newCell(2, "xxx\nqqq", align = "center", colspan = 1, valign = "middle")
756
# tbl.newRow()
757
# tbl.newCell(2, "+", align = "center", colspan = 1, valign = "middle")
758
# tbl.newRow()
759
# tbl.newCell(0, "vcvvbasdsadassdasdasv", align = "right", colspan = 2)
760
# tbl.newCell(2, "dddd1")
761
# tbl.newRow()
762
# tbl.newCell(0, "vcvvbv")
763
# tbl.newCell(1, "3445324", align = "right")
764
# tbl.newCell(2, None)
765
# tbl.newCell(1, "0000")
766
# if sys.stdout.isatty():
767
# tbl.consolePrintTable(sys.stdout)
768
# else:
769
# htmlPrintHeader(sys.stdout)
770
# tbl.htmlPrintTable(sys.stdout)
771
# htmlPrintFooter(sys.stdout)
772
773
import testlog_parser
774
775
if options.generateHtml:
776
htmlPrintHeader(sys.stdout, "Tables demo")
777
778
getter = metrix_table[options.metric][1]
779
780
for arg in args:
781
tests = testlog_parser.parseLogFile(arg)
782
tbl = table(arg, format=options.format)
783
tbl.newColumn("name", "Name of Test", align = "left")
784
tbl.newColumn("value", metrix_table[options.metric][0], align = "center", bold = "true")
785
786
for t in sorted(tests):
787
tbl.newRow()
788
tbl.newCell("name", str(t))
789
790
status = t.get("status")
791
if status != "run":
792
tbl.newCell("value", status)
793
else:
794
val = getter(t, None, options.units)
795
if val:
796
if options.metric.endswith("%"):
797
tbl.newCell("value", "%.2f" % val, val)
798
else:
799
tbl.newCell("value", "%.3f %s" % (val, options.units), val)
800
else:
801
tbl.newCell("value", "-")
802
803
if options.generateHtml:
804
tbl.htmlPrintTable(sys.stdout)
805
else:
806
tbl.consolePrintTable(sys.stdout)
807
808
if options.generateHtml:
809
htmlPrintFooter(sys.stdout)
810
811