summaryrefslogtreecommitdiff
path: root/heatmap.py
diff options
context:
space:
mode:
Diffstat (limited to 'heatmap.py')
-rwxr-xr-xheatmap.py158
1 files changed, 158 insertions, 0 deletions
diff --git a/heatmap.py b/heatmap.py
new file mode 100755
index 0000000..37dcdf1
--- /dev/null
+++ b/heatmap.py
@@ -0,0 +1,158 @@
+#!/usr/bin/env python3
+
+import sys, math, re
+
+if len(sys.argv)!=3:
+ print("Usage: {0} <source.bf> <heatmap.txt>".format(sys.argv[0]),file=sys.stderr)
+ sys.exit(1)
+
+bffname=sys.argv[1]
+hmfname=sys.argv[2]
+
+#def setgray(brightness):
+# ramp=[231,230,225,224,219,218,213,212,207,206,201,200,199,198,197,196]
+# code="\x1B[38;5;{0}m".format(ramp[int(brightness*(len(ramp)-1))])
+# brightness=int(brightness*25)
+# #if brightness==0: code="\x1B[0;30m"
+# #elif brightness==25: code="\x1B[1;37m"
+# #else: code="\x1B[38;5;{0}m".format(brightness-1+232)
+# print(code,end="")
+
+#for (c,count) in source:
+# setgray(math.log(count/maxcount*3+1)/math.log(4))
+# print(c,end="")
+
+def htmlconvert(ch):
+ if ch=="<": return "&lt;"
+ elif ch==">": return "&gt;"
+ elif ch=="\n": return "<br>"
+ elif ch==" ": return "&nbsp;"
+ else: return ch
+
+def hexcolor(r,g,b):
+ r,g,b=[int(x*255) for x in [r,g,b]]
+ return "#{0:0>2}{1:0>2}{2:0>2}".format(hex(r)[2:],hex(g)[2:],hex(b)[2:])
+
+def colorfor(freq):
+ ramp=[
+ (0.0, (1.0,1.0,1.0)),
+ (0.3, (0.3,0.5,0.5)),
+ (0.7, (0.2,0.2,1.0)),
+ (0.85, (0.6,0.1,1.0)),
+ (1.0, (1.0,0.0,0.0))
+ ]
+ for i in range(len(ramp)):
+ if ramp[i][0]>=freq:
+ break;
+ if i==0:
+ return hexcolor(*ramp[i][1])
+ c1=ramp[i-1][1]
+ c2=ramp[i][1]
+ t=(freq-ramp[i-1][0])/(ramp[i][0]-ramp[i-1][0])
+ return hexcolor(*[c1[i]*(1-t)+c2[i]*t for i in [0,1,2]])
+
+with open(bffname) as f:
+ source=[c for c in f.read()]
+
+maxcount=0
+with open(hmfname) as f:
+ for line in f:
+ idx,count=[int(x) for x in line.split(" ")]
+ source[idx]=(htmlconvert(source[idx]),count)
+ maxcount=max(maxcount,count)
+
+print("""<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Heatmap for execution of """+bffname+"""</title>
+<style>
+body{
+ font-family:Monaco,Meslo,monospace;
+ font-size:13px;
+}
+span.s{
+ border-radius:3px;
+ padding-top:1px;
+ padding-bottom:1px;
+}
+span.s:hover{
+ -webkit-box-shadow: inset 0px 0px 6px 0px rgba(0, 0, 0, 0.6);
+ -moz-box-shadow: inset 0px 0px 6px 0px rgba(0, 0, 0, 0.6);
+ box-shadow: inset 0px 0px 6px 0px rgba(0, 0, 0, 0.6);
+}
+div.codebox{
+ line-height:1.4em;
+}
+div#tooltip{
+ position:absolute;
+ display:none;
+ font-size:11px;
+ padding:3px;
+ background-color:black;
+ color:white;
+ opacity:0.9;
+ border-radius:6px;
+}
+div#tooltip.shown{
+ display:block;
+}
+</style>
+<script>
+var incounter=0;
+var tooltip,ttfreq,ttperc;
+
+function menter(e){
+ incounter++;
+ ttfreq.innerHTML=e.target.getAttribute("data-freq");
+ ttperc.innerHTML=e.target.getAttribute("data-perc");
+ var bbox=e.target.getBoundingClientRect();
+ tooltip.style.left=bbox.left+30+"px";
+ tooltip.style.top=document.body.scrollTop+bbox.top+18+"px";
+ tooltip.classList.add("shown");
+}
+function mleave(e){
+ incounter--;
+ if(incounter<0)incounter=0;
+ if(incounter==0)tooltip.classList.remove("shown");
+}
+
+window.addEventListener("load",function(){
+ tooltip=document.getElementById("tooltip");
+ tooltip.setAttribute("style","left:0;top:0");
+ ttfreq=tooltip.getElementsByClassName("ttfreq")[0];
+ ttperc=tooltip.getElementsByClassName("ttperc")[0];
+ var l=document.getElementsByClassName("s");
+ var i;
+ for(i=0;i<l.length;i++){
+ l[i].addEventListener("mouseenter",menter);
+ l[i].addEventListener("mouseleave",mleave);
+ //l[i].setAttribute("title","count: "+l[i].getAttribute("data-freq")+"\\nfreq: "+l[i].getAttribute("data-perc")+"%");
+ }
+});
+</script>
+</head>
+<body>
+<h1>"""+bffname+"""</h1>
+<div id="tooltip">
+ Frequency: <span class="ttfreq"></span><br>
+ (<span class="ttperc"></span>% of maximum)
+</div>
+<div class="codebox">""")
+
+i=0
+for (c,count) in source:
+ if i==0 or source[i-1][1]!=count:
+ print(
+ "<span class=\"s\" data-freq=\"{1}\" data-perc=\"{2}\" style=\"background-color:{0}\">"
+ .format(colorfor(count/maxcount),count,int(count/maxcount*100)),
+ end="")
+ print(c,end="")
+ if i==len(source)-1 or source[i+1][1]!=count:
+ print("</span>",end="")
+ i+=1
+
+print("""
+</pre>
+</body>
+</html>""")