1# Copyright 2017 The TensorFlow Authors. All Rights Reserved. 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14# ============================================================================== 15"""Make HTML tables that report where TF and TOCO failed to convert models. 16 17This is primarily used by generate_examples.py. See it or 18`make_report_table` for more details on usage. 19""" 20from __future__ import absolute_import 21from __future__ import division 22from __future__ import print_function 23 24import html 25import json 26 27FAILED = "FAILED" 28SUCCESS = "SUCCESS" 29NOTRUN = "NOTRUN" 30 31 32def make_report_table(fp, title, reports): 33 """Make an HTML report of the success/failure reports. 34 35 Args: 36 fp: File-like object in which to put the html. 37 title: "Title of the zip file this pertains to." 38 reports: a list of conversion attempts. (report_args, report_vals) i.e. 39 ({"shape": [1,2,3], "type": "tf.float32"}, 40 {"tf": "SUCCESS", "converter": "FAILURE", 41 "converter_log": "Unsupported type.", "tf_log": ""}) 42 """ 43 # sort reports by if TOCO failure and then TF failure (reversed) 44 reports.sort(key=lambda x: x[1]["converter"], reverse=False) 45 reports.sort(key=lambda x: x[1]["tf"], reverse=True) 46 def result_cell(x, row, col): 47 """Produce a cell with the condition string `x`.""" 48 s = html.escape(repr(x), quote=True) 49 color = "#44ff44" if x == SUCCESS else ( 50 "#ff4444" if x == FAILED else "#eeeeee") 51 handler = "ShowLog(%d, %d)" % (row, col) 52 fp.write("<td style='background-color: %s' onclick='%s'>%s</td>\n" % ( 53 color, handler, s)) 54 55 fp.write("""<html> 56<head> 57<title>tflite report</title> 58<style> 59body { font-family: Arial; } 60th { background-color: #555555; color: #eeeeee; } 61td { vertical-align: top; } 62td.horiz {width: 50%;} 63pre { white-space: pre-wrap; word-break: keep-all; } 64table {width: 100%;} 65</style> 66</head> 67""") 68 # Write the log data to a javascript variable and also make a function 69 # in javascript to show the log when an item is clicked. 70 fp.write("<script> \n") 71 fp.write(""" 72function ShowLog(row, col) { 73 74var log = document.getElementById("log"); 75log.innerHTML = "<pre>" + data[row][col] + "</pre>"; 76} 77""") 78 fp.write("var data = \n") 79 logs = json.dumps([[html.escape(x[1]["tf_log"], quote=True), 80 html.escape(x[1]["converter_log"], quote=True) 81 ] for x in reports]) 82 fp.write(logs) 83 fp.write(";</script>\n") 84 85 # Write the main table and use onclick on the items that have log items. 86 fp.write(""" 87<body> 88<h1>TOCO Conversion</h1> 89<h2>%s</h2> 90""" % title) 91 92 # Get a list of keys that are in any of the records. 93 param_keys = {} 94 for params, _ in reports: 95 for k in params.keys(): 96 param_keys[k] = True 97 98 fp.write("<table>\n") 99 fp.write("<tr><td class='horiz'>\n") 100 fp.write("<div style='height:1000px; overflow:auto'>\n") 101 fp.write("<table>\n") 102 fp.write("<tr>\n") 103 for p in param_keys: 104 fp.write("<th>%s</th>\n" % html.escape(p, quote=True)) 105 fp.write("<th>TensorFlow</th>\n") 106 fp.write("<th>TOCO</th>\n") 107 fp.write("</tr>\n") 108 for idx, (params, vals) in enumerate(reports): 109 fp.write("<tr>\n") 110 for p in param_keys: 111 fp.write(" <td>%s</td>\n" % html.escape(repr(params[p]), quote=True)) 112 113 result_cell(vals["tf"], idx, 0) 114 result_cell(vals["converter"], idx, 1) 115 fp.write("</tr>\n") 116 fp.write("</table>\n") 117 fp.write("</div>\n") 118 fp.write("</td>\n") 119 fp.write("<td class='horiz' id='log'></td></tr>\n") 120 fp.write("</table>\n") 121 fp.write("<script>\n") 122 fp.write("</script>\n") 123 fp.write(""" 124 </body> 125 </html> 126 """) 127