From fe6f8c8dfed86d39c80f2804a753c05bb2e485b4 Mon Sep 17 00:00:00 2001
From: "Aflitos, Saulo Alves" <sauloalves.aflitos@wur.nl>
Date: Wed, 5 Oct 2016 16:14:46 +0200
Subject: [PATCH] viewer

---
 viewer/.gitignore       |   3 +
 viewer/stats_to_html.py | 350 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 353 insertions(+)
 create mode 100644 viewer/.gitignore
 create mode 100644 viewer/stats_to_html.py

diff --git a/viewer/.gitignore b/viewer/.gitignore
new file mode 100644
index 0000000..385e72e
--- /dev/null
+++ b/viewer/.gitignore
@@ -0,0 +1,3 @@
+*.html
+*.css
+*.js
diff --git a/viewer/stats_to_html.py b/viewer/stats_to_html.py
new file mode 100644
index 0000000..81a0287
--- /dev/null
+++ b/viewer/stats_to_html.py
@@ -0,0 +1,350 @@
+#!/usr/bin/env python
+
+import os
+import sys
+import argparse
+from collections import OrderedDict, defaultdict
+
+def sanitize(n):
+    return n.lower().replace(" ", "_").replace(".", "_")
+
+class table(object):
+    def __init__(self, lines, has_header=True, has_row_name=True):
+        self.lines        = lines
+        self.has_header   = has_header
+        self.has_row_name = has_row_name
+        self.header       = []
+        self.rows         = []
+        self.data         = []
+        self.process()
+        
+    def process(self):
+        for line_num, line in enumerate(self.lines.split("\n")):
+            cols = [l.strip() for l in line.split("\t")]
+            
+            if line_num == 0:
+                if   self.has_header:
+                    self.header = cols
+                
+                elif self.has_row_name:
+                    self.rows.append(cols[0] )
+                    self.data.append(cols[1:])
+                    
+                else:
+                    if len(cols) > 0 and sum([len(c) for c in cols]) > 0:
+                        self.data.append(cols)
+                    
+            else:
+                if len(cols) > 0 and sum([len(c) for c in cols]) > 0:
+                    if self.has_row_name:
+                        self.rows.append(cols[0] )
+                        self.data.append(cols[1:])
+                        
+                    else:
+                        self.data.append(cols)
+
+    def to_html(self, tb_id, tb_class, decimals=1, colored=False, no_diag=False):
+        tb_class = sanitize(tb_class)
+        #return OrderedDict((('header', self.header), ('rows', self.rows), ('data', self.data)))
+
+        if no_diag:
+            for a in xrange(len(self.data)):
+                self.data[a][a] = None
+
+        min_val = min([min([float(e) for e in d if e is not None]) for d in self.data])
+        max_val = max([max([float(e) for e in d if e is not None]) for d in self.data])
+
+        print "min_val {} max_val {}".format(min_val, max_val)
+
+        res     = ['            <table id="{}" class="table_header {}" min_val="{}" max_val="{}">'.format(tb_id, tb_class + (" colored" if colored else ""), min_val, max_val)]
+        
+        if   self.has_header:
+            res.append( '                <tr row_num="-1" row_name="_HEADER_" class="header_row {tb_class}_header">'.format(**{
+                'tb_class'  : tb_class            ,
+            }) )
+                
+            for col_num, col_name in enumerate(self.header):
+                res.append( '                    <th col_num="{col_num}" col_name="{col_name}" class="header_cell {tb_class}_header {tb_class}_th"><div><span>{col_name}</span></div></th>'.format(**{
+                    'col_num'   : col_num           ,
+                    'col_name'  : col_name          ,
+                    'tb_class'  : tb_class          ,
+                    }) )
+                
+            res.append( '                </tr>' )
+        
+        for row_num, row in enumerate(self.data):
+            row_name = row_num
+
+            if len(row) == 0:
+                continue
+
+            res.append( '                <tr row_num="{row_num}" row_name="{row_name}" class="table_row {tb_class}_row">'.format(**{
+                'row_num'   : row_num             ,
+                'row_name'  : row_name            ,
+                'tb_class'  : tb_class            ,
+            }) )
+            
+            for col_num, col_val in enumerate(row):
+                if self.has_row_name and col_num == 0:
+                    row_name = self.rows[row_num]
+                    res.append( '                    <th col_num="{col_num}" col_name="{col_name}" row_num="{row_num}" row_name="{row_name}" class="row_name {tb_class}_row_name {tb_class}_th">{row_name}</th>'.format(**{
+                        'col_num' :   col_num             ,
+                        'col_name'  : self.header[col_num],
+                        'row_num'   : row_num             ,
+                        'row_name'  : row_name            ,
+                        'tb_class'  : tb_class
+                    }) )
+
+                if self.has_row_name:
+                    col_num += 1
+                    
+                col_name = col_num
+                
+                if self.has_header:
+                    col_name = self.header[col_num]
+                
+                if col_val is None:
+                    col_val = "-"
+                
+                else:
+                    if '.' in col_val:
+                        col_val = ("{:,."+str(decimals)+"f}").format(float(col_val))
+                    else:
+                        col_val = "{:,d}".format(int(col_val))
+                
+                res.append( '                    <td col_num="{col_num}" col_name="{col_name}" row_num="{row_num}" row_name="{row_name}" class="cell {tb_class}_td">{col_val}</th>'.format(**{
+                        'col_num' :   col_num             ,
+                        'col_name'  : self.header[col_num],
+                        'row_num'   : row_num             ,
+                        'row_name'  : row_name            ,
+                        'row_name_s': sanitize(row_name)  ,
+                        'tb_class'  : tb_class            ,
+                        'col_val'   : col_val
+                    }) )
+            
+            res.append( '                </tr>' )
+
+        res.append( '            </table>' )
+
+        return "\n".join(res)
+
+def main():
+    basename = sys.argv[1]
+    
+    f_json, f_stats, f_count, f_matrix = [x.format(basename) for x in ("{}.json","{}.json.count.csv","{}.json.csv","{}.json.jaccard.matrix")]
+    
+    for f in (f_json, f_stats, f_count, f_matrix):
+        if not os.path.exists(f):
+            print "input file {} does not exists".format(f)
+            sys.exit(1)
+            
+    json     = open(f_json  , 'r').read()
+    stats    = open(f_stats , 'r').read()
+    count    = open(f_count , 'r').read()
+    matrix   = open(f_matrix, 'r').read()
+    
+    stats_t  = table(stats , has_header=True, has_row_name=True ).to_html( 'stats_table' , 'stats_table' , decimals=1, colored=False, no_diag=False )
+    count_t  = table(count , has_header=True, has_row_name=True ).to_html( 'count_table' , 'count_table' , decimals=1, colored=True , no_diag=True  )
+    matrix_t = table(matrix, has_header=True, has_row_name=True ).to_html( 'matrix_table', 'matrix_table', decimals=5, colored=True , no_diag=True )
+    
+    res      = TEMPLATE.format(**{
+        "title" : basename,
+        "json"  : ''      , #json    ,
+        "count" : count_t ,
+        "stats" : stats_t ,
+        "matrix": matrix_t,
+        "script": '<script>{}</script>'.format(SCRIPT),
+        "css"   : '<style>{}</style>'  .format(CSS   ),
+        # "script": '<script src="{}.js"></script>'.format(basename),
+        # "css"   : '<link rel="stylesheet" href="{}.css">'.format(basename)
+    })
+    
+    #print res
+    
+    open("{}.html".format(basename), 'w').write(res)
+
+TEMPLATE = """<!doctype html>
+<html>
+    <head>
+        <meta charset="UTF-8">
+        <title>{title}</title>
+{css}
+        <script src="https://cdn.rawgit.com/gka/chroma.js/master/chroma.min.js"></script>
+{script}
+    </head>
+    <body>
+        <script type="application/json" id="json">
+{json}
+        </script>
+        <div id="stats">
+{stats}
+        </div>
+        <div id="count">
+{count}
+        </div>
+        <div id="matrix">
+{matrix}
+        </div>
+    </body>
+</html>
+"""
+
+SCRIPT = """
+function isNumeric(n) {
+  //https://stackoverflow.com/questions/18082/validate-decimal-numbers-in-javascript-isnumeric
+  return !isNaN(parseFloat(n)) && isFinite(n);
+}
+
+var bscale = chroma.scale(['yellow' , 'orange', 'red' ]);
+var fscale = chroma.scale(['black', 'white']);
+
+function heatMapColorforValue(min_val, max_val, value){
+  /*
+  2-3-4-5 = (2 - 2) / (5 - 2) = 0 / 3 = 0
+  2-3-4-5 = (3 - 2) / (5 - 2) = 1 / 3 = 0.3
+  2-3-4-5 = (4 - 2) / (5 - 2) = 2 / 3 = 0.6
+  2-3-4-5 = (5 - 2) / (5 - 2) = 3 / 3 = 1.0
+  */
+  var ival   = (value - min_val) / (max_val - min_val);
+  var bcolor = bscale(ival).hex();
+  var fcolor = fscale(ival).hex();
+  return [ival, bcolor, fcolor];
+}
+
+function color_cells() {
+  var coloreds = document.getElementsByClassName("colored");
+  
+  console.log(coloreds.length, coloreds);
+  
+  for (var c = 0; c < coloreds.length; c++) {
+    var e = coloreds[c];
+    
+    var min_val = parseFloat(e.getAttribute('min_val'));
+    var max_val = parseFloat(e.getAttribute('max_val'));
+    
+    console.log("C",c,"E",e,"min",min_val,"max",max_val);
+    
+    var tds = e.getElementsByTagName("td");
+    
+    //console.log(" TDS", tds.length, tds);
+    
+    for ( var t = 0; t < tds.length; t++) {
+      var td    = tds[t];
+      var value = parseFloat(td.innerHTML.replace(/,/g, ""));
+      if ( isNumeric(value) ) {
+        var cdata  = heatMapColorforValue(min_val, max_val, value);
+        var prop   = cdata[0];
+        var bcolor = cdata[1];
+        var fcolor = cdata[2];
+        td.style.backgroundColor = bcolor;
+        //td.style.color           = fcolor;
+      }
+    }
+  }
+}
+
+
+document.addEventListener("DOMContentLoaded", color_cells);
+"""
+
+CSS = """
+th.header_cell {
+    text-align: left;
+    height: 500px;
+}
+
+th.header_cell > div {
+    /*float: left;*/
+    transform:
+    /*translate(25px, 51px)*/
+    /*rotate(315deg);*/
+    translate(15px, 180px)
+    rotate(270deg);
+    width: 50px;
+	/*transform-origin: left top 0;*/
+}
+
+th.header_cell > div > span {
+    /*border-bottom: 1px solid #ccc;*/
+    padding: 5px 10px;
+}
+
+th.row_name {
+    text-align: left;
+}
+
+td.cell {
+    text-align: right;
+    /*text-shadow: 1px 1px 1px #000;*/
+}
+
+th {
+    white-space: nowrap;
+}
+"""
+
+"""
+<div id="stats">
+    <table id="stats_table" class=table_header "stats_table">
+        <tr row_num="-1" row_name="_HEADER_" class="header_row stats_table_header">
+            <th col_num="0" col_name="NAME" class="header_cell stats_table_header stats_table_th">NAME</th>
+            <th col_num="1" col_name="TOTAL" class="header_cell stats_table_header stats_table_th">TOTAL</th>
+            <th col_num="2" col_name="VALID" class="header_cell stats_table_header stats_table_th">VALID</th>
+            <th col_num="3" col_name="PROP" class="header_cell stats_table_header stats_table_th">PROP</th>
+        </tr>
+        <tr row_num="176" row_name="176" class="table_row stats_table_row">
+            <th col_num="0" col_name="NAME" row_num="176" row_name="Tribolium castaneum" class="row_name stats_table_row_name stats_table_th">Tribolium castaneum</th>
+            <td col_num="1" col_name="TOTAL" row_num="176" row_name="Tribolium castaneum" class="cell stats_table_td">6581748</th>
+            <td col_num="2" col_name="VALID" row_num="176" row_name="Tribolium castaneum" class="cell stats_table_td">1505999</th>
+            <td col_num="3" col_name="PROP" row_num="176" row_name="Tribolium castaneum" class="cell stats_table_td"> 22.88</th>
+        </tr>
+        <tr row_num="177" row_name="177" class="table_row stats_table_row">
+        </tr>
+    </table>
+</div>
+<div id="count">
+    <table id="count_table" class=table_header "count_table">
+        <tr row_num="-1" row_name="_HEADER_" class="header_row count_table_header">
+            <th col_num="0" col_name="" class="header_cell count_table_header count_table_th"></th>
+            <th col_num="1" col_name="Arabidopsis lyrata" class="header_cell count_table_header count_table_th">Arabidopsis lyrata</th>
+            <th col_num="2" col_name="Arabidopsis thaliana TAIR10" class="header_cell count_table_header count_table_th">Arabidopsis thaliana TAIR10</th>
+            <th col_num="3" col_name="Citrus sinensis" class="header_cell count_table_header count_table_th">Citrus sinensis</th>
+            <th col_num="176" col_name="Struthio camelus australis" class="header_cell count_table_header count_table_th">Struthio camelus australis</th>
+            <th col_num="177" col_name="Tribolium castaneum" class="header_cell count_table_header count_table_th">Tribolium castaneum</th>
+        </tr>
+        <tr row_num="0" row_name="0" class="table_row count_table_row">
+            <th col_num="0" col_name="" row_num="0" row_name="Arabidopsis lyrata" class="row_name count_table_row_name count_table_th">Arabidopsis lyrata</th>
+            <td col_num="1" col_name="Arabidopsis lyrata" row_num="0" row_name="Arabidopsis lyrata" class="cell count_table_td">0</th>
+            <td col_num="176" col_name="Struthio camelus australis" row_num="176" row_name="Tribolium castaneum" class="cell count_table_td">47911</th>
+            <td col_num="177" col_name="Tribolium castaneum" row_num="176" row_name="Tribolium castaneum" class="cell count_table_td">0</th>
+        </tr>
+        <tr row_num="177" row_name="177" class="table_row count_table_row">
+        </tr>
+    </table>
+</div>
+<div id="matrix">
+    <table id="matrix_table" class=table_header "matrix_table">
+        <tr row_num="-1" row_name="_HEADER_" class="header_row matrix_table_header">
+            <th col_num="0" col_name="" class="header_cell matrix_table_header matrix_table_th"></th>
+            <th col_num="1" col_name="Arabidopsis lyrata" class="header_cell matrix_table_header matrix_table_th">Arabidopsis lyrata</th>
+            <th col_num="176" col_name="Struthio camelus australis" class="header_cell matrix_table_header matrix_table_th">Struthio camelus australis</th>
+            <th col_num="177" col_name="Tribolium castaneum" class="header_cell matrix_table_header matrix_table_th">Tribolium castaneum</th>
+            <th col_num="178" col_name="" class="header_cell matrix_table_header matrix_table_th"></th>
+        </tr>
+        <tr row_num="0" row_name="0" class="table_row matrix_table_row">
+            <th col_num="0" col_name="" row_num="0" row_name="Arabidopsis lyrata" class="row_name matrix_table_row_name matrix_table_th">Arabidopsis lyrata</th>
+            <td col_num="1" col_name="Arabidopsis lyrata" row_num="0" row_name="Arabidopsis lyrata" class="cell matrix_table_td">1.0000000000</th>
+            <td col_num="2" col_name="Arabidopsis thaliana TAIR10" row_num="0" row_name="Arabidopsis lyrata" class="cell matrix_table_td">0.7233067471</th>
+            <td col_num="176" col_name="Struthio camelus australis" row_num="176" row_name="Tribolium castaneum" class="cell matrix_table_td">0.9962171649</th>
+            <td col_num="177" col_name="Tribolium castaneum" row_num="176" row_name="Tribolium castaneum" class="cell matrix_table_td">1.0000000000</th>
+        </tr>
+        <tr row_num="177" row_name="177" class="table_row matrix_table_row">
+        </tr>
+        <tr row_num="178" row_name="178" class="table_row matrix_table_row">
+        </tr>
+    </table>
+</div>
+"""
+
+if __name__ == '__main__':
+    main()
\ No newline at end of file
-- 
GitLab