CMSIS-DSP: Improved formating script for test reports.

pull/19/head
Christophe Favergeon 6 years ago
parent 4d049610c1
commit 575d68f280

@ -4,6 +4,361 @@ import re
import pandas as pd
import numpy as np
class Document:
def __init__(self,runid,date):
self._runid = runid
self._date = date
self._sections = []
@property
def runid(self):
return(self._runid)
@property
def date(self):
return(self._date)
@property
def sections(self):
return(self._sections)
def addSection(self,section):
self._sections.append(section)
def accept(self, visitor):
visitor.visitDocument(self)
for element in self._sections:
element.accept(visitor)
visitor.leaveDocument(self)
class Section:
def __init__(self,name):
self._name=name
self._subsections = []
self._tables = []
def addSection(self,section):
self._subsections.append(section)
def addTable(self,table):
self._tables.append(table)
@property
def hasChildren(self):
return(len(self._subsections)>0)
@property
def name(self):
return(self._name)
def accept(self, visitor):
visitor.visitSection(self)
for element in self._subsections:
element.accept(visitor)
for element in self._tables:
element.accept(visitor)
visitor.leaveSection(self)
class Table:
def __init__(self,columns):
self._columns=columns
self._rows=[]
def addRow(self,row):
self._rows.append(row)
@property
def columns(self):
return(self._columns)
@property
def rows(self):
return(self._rows)
def accept(self, visitor):
visitor.visitTable(self)
class Markdown:
def __init__(self,output):
self._id=0
self._output = output
# Write columns in markdown format
def writeColumns(self,cols):
colStr = "".join(joinit(cols,"|"))
self._output.write("|")
self._output.write(colStr)
self._output.write("|\n")
sepStr="".join(joinit([":-:" for x in cols],"|"))
self._output.write("|")
self._output.write(sepStr)
self._output.write("|\n")
# Write row in markdown format
def writeRow(self,row):
row=[str(x) for x in row]
rowStr = "".join(joinit(row,"|"))
self._output.write("|")
self._output.write(rowStr)
self._output.write("|\n")
def visitTable(self,table):
self.writeColumns(table.columns)
for row in table.rows:
self.writeRow(row)
def visitSection(self,section):
self._id = self._id + 1
header = "".join(["#" for i in range(self._id)])
output.write("%s %s\n" % (header,section.name))
def leaveSection(self,section):
self._id = self._id - 1
def visitDocument(self,document):
self._output.write("Run number %d on %s\n" % (document.runid, str(document.date)))
def leaveDocument(self,document):
pass
styleSheet="""
<style type='text/css'>
#TOC {
position: fixed;
left: 0;
top: 0;
width: 250px;
height: 100%;
overflow:auto;
}
html {
font-size: 16px;
}
html, body {
background-color: #f3f2ee;
font-family: "PT Serif", 'Times New Roman', Times, serif;
color: #1f0909;
line-height: 1.5em;
margin: auto;
margin-left:220px;
}
table {
border-collapse: collapse;
border-spacing: 0;
width: 100%;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: bold;
}
h1 {
font-size: 1.875em;
line-height: 1.6em;
margin-top: 1em;
}
h2,
h3 {
font-size: 1.3125em;
line-height: 1.15;
margin-top: 2.285714em;
margin-bottom: 1.15em;
}
h4 {
font-size: 1.125em;
margin-top: 2.67em;
}
h5,
h6 {
font-size: 1em;
}
table {
margin-bottom: 1.5em;
/*24 / 16*/
font-size: 1em;
/* width: 100%; */
}
thead th,
tfoot th {
padding: .25em .25em .25em .4em;
text-transform: uppercase;
}
th {
text-align: left;
}
td {
vertical-align: top;
padding: .25em .25em .25em .4em;
}
.ty-table-edit {
background-color: transparent;
}
thead {
background-color: #dadada;
}
tr:nth-child(even) {
background: #e8e7e7;
}
ul, #myUL {
list-style-type: none;
padding-inline-start:10px;
}
/* Remove margins and padding from the parent ul */
#myUL {
margin: 0;
padding: 0;
}
/* Style the caret/arrow */
.caret {
cursor: pointer;
user-select: none; /* Prevent text selection */
}
/* Create the caret/arrow with a unicode, and style it */
.caret::before {
content: "\\25B6";
color: black;
display: inline-block;
margin-right: 6px;
}
/* Rotate the caret/arrow icon when clicked on (using JavaScript) */
.caret-down::before {
transform: rotate(90deg);
}
/* Hide the nested list */
.nested {
display: none;
}
/* Show the nested list when the user clicks on the caret/arrow (with JavaScript) */
.active {
display: block;
}
</style>
"""
script="""<script type="text/javascript">
var toggler = document.getElementsByClassName("caret");
var i;
for (i = 0; i < toggler.length; i++) {
toggler[i].addEventListener("click", function() {
this.parentElement.querySelector(".nested").classList.toggle("active");
this.classList.toggle("caret-down");
});
}</script>"""
class HTMLToc:
def __init__(self,output):
self._id=0
self._sectionID = 0
self._output = output
def visitTable(self,table):
pass
def visitSection(self,section):
self._id = self._id + 1
self._sectionID = self._sectionID + 1
if section.hasChildren:
self._output.write("<li><span class=\"caret\"><a href=\"#section%d\">%s</a></span>\n" % (self._sectionID,section.name))
self._output.write("<ul class=\"nested\">\n")
else:
self._output.write("<li><span><a href=\"#section%d\">%s</a></span>\n" % (self._sectionID,section.name))
def leaveSection(self,section):
if section.hasChildren:
self._output.write("</ul></li>\n")
self._id = self._id - 1
def visitDocument(self,document):
self._output.write("<div id=\"TOC\"><h1>Table of content</h1><ul id=\"myUL\">\n")
def leaveDocument(self,document):
self._output.write("</ul></div>%s\n" % script)
class HTML:
def __init__(self,output):
self._id=0
self._sectionID = 0
self._output = output
def visitTable(self,table):
output.write("<table>\n")
output.write("<thead>\n")
output.write("<tr>\n")
for col in table.columns:
output.write("<th>")
output.write(str(col))
output.write("</th>\n")
output.write("</tr>\n")
output.write("</thead>\n")
for row in table.rows:
output.write("<tr>\n")
for elem in row:
output.write("<td>")
output.write(str(elem))
output.write("</td>\n")
output.write("</tr>\n")
output.write("</table>\n")
def visitSection(self,section):
self._id = self._id + 1
self._sectionID = self._sectionID + 1
output.write("<h%d id=\"section%d\">%s</h%d>\n" % (self._id,self._sectionID,section.name,self._id))
def leaveSection(self,section):
self._id = self._id - 1
def visitDocument(self,document):
self._output.write("""<!doctype html>
<html>
<head>
<meta charset='UTF-8'><meta name='viewport' content='width=device-width initial-scale=1'>
<title>Benchmarks</title>%s</head><body>\n""" % styleSheet)
self._output.write("<p>Run number %d on %s</p>\n" % (document.runid, str(document.date)))
def leaveDocument(self,document):
document.accept(HTMLToc(self._output))
self._output.write("</body></html>\n")
# Command to get last runid
lastID="""SELECT runid FROM RUN ORDER BY runid DESC LIMIT 1
"""
@ -27,6 +382,7 @@ parser = argparse.ArgumentParser(description='Generate summary benchmarks')
parser.add_argument('-b', nargs='?',type = str, default="bench.db", help="Benchmark database")
parser.add_argument('-o', nargs='?',type = str, default="full.md", help="Full summary")
parser.add_argument('-r', action='store_true', help="Regression database")
parser.add_argument('-t', nargs='?',type = str, default="md", help="md,html")
# For runid or runid range
parser.add_argument('others', nargs=argparse.REMAINDER)
@ -203,28 +559,11 @@ def getColNamesAndData(benchTable,comp,typeid):
vals =np.array([list(x) for x in list(result)])
return(keepCols,vals)
# Write columns in markdown format
def writeColumns(f,cols):
colStr = "".join(joinit(cols,"|"))
f.write("|")
f.write(colStr)
f.write("|\n")
sepStr="".join(joinit([":-:" for x in cols],"|"))
f.write("|")
f.write(sepStr)
f.write("|\n")
# Write row in markdown format
def writeRow(f,row):
row=[str(x) for x in row]
rowStr = "".join(joinit(row,"|"))
f.write("|")
f.write(rowStr)
f.write("|\n")
PARAMS=["NB","NumTaps", "NBA", "NBB", "Factor", "NumStages","VECDIM","NBR","NBC","NBI","IFFT", "BITREV"]
def regressionTableFor(name,output,ref,toSort,indexCols,field):
def regressionTableFor(name,section,ref,toSort,indexCols,field):
data=ref.pivot_table(index=indexCols, columns='core',
values=[field], aggfunc='first')
@ -233,7 +572,9 @@ def regressionTableFor(name,output,ref,toSort,indexCols,field):
cores = [c[1] for c in list(data.columns)]
columns = diff(indexCols,['NAME']) + cores
writeColumns(output,columns)
dataTable=Table(columns)
section.addTable(dataTable)
dataForFunc=data.loc[name]
if type(dataForFunc) is pd.DataFrame:
for row in dataForFunc.itertuples():
@ -242,11 +583,11 @@ def regressionTableFor(name,output,ref,toSort,indexCols,field):
row=[row[0]] + row[1:]
else:
row=list(row[0]) + row[1:]
writeRow(output,row)
dataTable.addRow(row)
else:
writeRow(output,dataForFunc)
dataTable.addRow(dataForFunc)
def formatTableByCore(output,testNames,cols,vals):
def formatTableByCore(typeSection,testNames,cols,vals):
if vals.size != 0:
ref=pd.DataFrame(vals,columns=cols)
toSort=["NAME"]
@ -272,16 +613,20 @@ def formatTableByCore(output,testNames,cols,vals):
for name in testNames:
if args.r:
output.write("#### %s\n" % name)
testSection = Section(name)
typeSection.addSection(testSection)
output.write("##### Regression\n" )
regressionTableFor(name,output,ref,toSort,indexCols,'Regression')
regressionSection = Section("Regression")
testSection.addSection(regressionSection)
regressionTableFor(name,regressionSection,ref,toSort,indexCols,'Regression')
output.write("##### Max cycles\n" )
regressionTableFor(name,output,ref,toSort,indexCols,'MAX')
maxCyclesSection = Section("Max cycles")
testSection.addSection(maxCyclesSection)
regressionTableFor(name,maxCyclesSection,ref,toSort,indexCols,'MAX')
output.write("##### Max Reg Coef\n" )
regressionTableFor(name,output,ref,toSort,indexCols,'MAXREGCOEF')
maxRegCoefSection = Section("Max Reg Coef")
testSection.addSection(maxRegCoefSection)
regressionTableFor(name,maxRegCoefSection,ref,toSort,indexCols,'MAXREGCOEF')
else:
data=ref.pivot_table(index=indexCols, columns='core',
@ -292,8 +637,12 @@ def formatTableByCore(output,testNames,cols,vals):
cores = [c[1] for c in list(data.columns)]
columns = diff(indexCols,['NAME']) + cores
output.write("#### %s\n" % name)
writeColumns(output,columns)
testSection = Section(name)
typeSection.addSection(testSection)
dataTable=Table(columns)
testSection.addTable(dataTable)
dataForFunc=data.loc[name]
if type(dataForFunc) is pd.DataFrame:
for row in dataForFunc.itertuples():
@ -302,23 +651,25 @@ def formatTableByCore(output,testNames,cols,vals):
row=[row[0]] + row[1:]
else:
row=list(row[0]) + row[1:]
writeRow(output,row)
dataTable.addRow(row)
else:
writeRow(output,dataForFunc)
dataTable.addRow(dataForFunc)
# Add a report for each table
def addReportFor(output,benchName):
def addReportFor(document,benchName):
nbElems = getNbElemsInBenchCmd(benchName)
if nbElems > 0:
benchSection = Section(benchName)
document.addSection(benchSection)
print("Process %s\n" % benchName)
output.write("# %s\n" % benchName)
allTypes = getExistingTypes(benchName)
# Add report for each type
for aTypeID in allTypes:
nbElems = getNbElemsInBenchAndTypeCmd(benchName,aTypeID)
if nbElems > 0:
typeName = getTypeName(aTypeID)
output.write("## %s\n" % typeName)
typeSection = Section(typeName)
benchSection.addSection(typeSection)
## Add report for each compiler
allCompilers = getExistingCompiler(benchName,aTypeID)
for compiler in allCompilers:
@ -326,23 +677,31 @@ def addReportFor(output,benchName):
nbElems = getNbElemsInBenchAndTypeAndCompilerCmd(benchName,compiler,aTypeID)
# Print test results for table, type, compiler
if nbElems > 0:
output.write("### %s (%s)\n" % compiler)
compilerSection = Section("%s (%s)" % compiler)
typeSection.addSection(compilerSection)
cols,vals=getColNamesAndData(benchName,compiler,aTypeID)
names=getTestNames(benchName,compiler,aTypeID)
formatTableByCore(output,names,cols,vals)
formatTableByCore(compilerSection,names,cols,vals)
try:
with open(args.o,"w") as output:
benchtables=getBenchTables()
theDate = getrunIDDate(runid)
output.write("Run number %d on %s\n" % (runid, str(theDate)))
document = Document(runid,theDate)
for bench in benchtables:
addReportFor(output,bench)
addReportFor(document,bench)
with open(args.o,"w") as output:
if args.t=="md":
document.accept(Markdown(output))
if args.t=="html":
document.accept(HTML(output))
finally:
c.close()

Loading…
Cancel
Save