ILinePlotGen.py revision 67527ddea39e858c957997356a16bd8e3819f359
1# $Copyright: 2# ---------------------------------------------------------------- 3# This confidential and proprietary software may be used only as 4# authorised by a licensing agreement from ARM Limited 5# (C) COPYRIGHT 2015 ARM Limited 6# ALL RIGHTS RESERVED 7# The entire notice above must be reproduced on all authorised 8# copies and copies may only be made to the extent permitted 9# by a licensing agreement from ARM Limited. 10# ---------------------------------------------------------------- 11# File: ILinePlotGen.py 12# ---------------------------------------------------------------- 13# $ 14# 15"""This module is reponsible for creating a layout 16of plots as a 2D axes and handling corener cases 17and deleting empty plots 18""" 19 20from cr2.plotter import AttrConf 21import uuid 22import json 23import os 24from IPython.display import display, HTML 25 26 27if not AttrConf.PLOTTER_IPYTHON: 28 raise ImportError("No Ipython Environment found") 29 30# Install resources 31from cr2.plotter import Utils 32Utils.iplot_install("ILinePlot") 33 34 35class ILinePlotGen(object): 36 37 """Cols is the number of columns to draw 38 rows are calculated as 1D - 2D transformation 39 the same transformation is used to index the 40 axes array 41 """ 42 43 def _add_graph_cell(self, fig_name): 44 """Add a HTML table cell to hold the plot""" 45 46 width = int(self._attr["width"] / self._cols) 47 div_js = """ 48 <script> 49 var ilp_req = require.config( { 50 51 paths: { 52 "dygraph-sync": "/static/plotter_scripts/ILinePlot/synchronizer", 53 "dygraph": "/static/plotter_scripts/ILinePlot/dygraph-combined", 54 "ILinePlot": "/static/plotter_scripts/ILinePlot/ILinePlot", 55 }, 56 57 shim: { 58 "dygraph-sync": ["dygraph"], 59 "ILinePlot": { 60 61 "deps": ["dygraph-sync", "dygraph" ], 62 "exports": "ILinePlot" 63 } 64 } 65 }); 66 ilp_req(["require", "ILinePlot"], function() { 67 ILinePlot.generate('""" + fig_name + """'); 68 }); 69 </script> 70 """ 71 72 cell = '<td style="border-style: hidden;"><div class="ilineplot" id="{0}" style="width: \ 73{1}px; height: {2}px;">{3}</div></td>'.format(fig_name, 74 width, 75 self._attr["height"], div_js) 76 77 self._html.append(cell) 78 79 def _add_legend_cell(self, fig_name): 80 """Add HTML table cell for the legend""" 81 82 width = int(self._attr["width"] / self._cols) 83 legend_div_name = fig_name + "_legend" 84 cell = '<td style="border-style: hidden;"><div style="text-align:right; \ 85width: {0}px; height: auto;"; id="{1}"></div></td>'.format(width, 86 legend_div_name) 87 88 self._html.append(cell) 89 90 def _begin_row(self): 91 """Add the opening tag for HTML row""" 92 93 self._html.append("<tr>") 94 95 def _end_row(self): 96 """Add the closing tag for the HTML row""" 97 98 self._html.append("</tr>") 99 100 def _generate_fig_name(self): 101 """Generate a unique figure name""" 102 103 fig_name = "fig_" + uuid.uuid4().hex 104 self._fig_map[self._fig_index] = fig_name 105 self._fig_index += 1 106 return fig_name 107 108 def _init_html(self): 109 """Initialize HTML code for the plots""" 110 111 width = self._attr["width"] 112 table = '<table style="width: {0}px; border-style: hidden;">'.format( 113 width) 114 self._html.append(table) 115 116 for _ in range(self._rows): 117 self._begin_row() 118 119 legend_figs = [] 120 for _ in range(self._cols): 121 fig_name = self._generate_fig_name() 122 legend_figs.append(fig_name) 123 self._add_graph_cell(fig_name) 124 125 self._end_row() 126 self._begin_row() 127 128 for l_fig in legend_figs: 129 self._add_legend_cell(l_fig) 130 131 self._end_row() 132 133 def __init__(self, cols, num_plots, **kwargs): 134 """ 135 Args: 136 cols (int): Number of plots in a single line 137 num_plots (int): Total Number of Plots 138 """ 139 140 self._cols = cols 141 self._attr = kwargs 142 self._html = [] 143 self.num_plots = num_plots 144 self._fig_map = {} 145 self._fig_index = 0 146 147 self._single_plot = False 148 if self.num_plots == 0: 149 raise RuntimeError("No plots for the given constraints") 150 151 if self.num_plots < self._cols: 152 self._cols = self.num_plots 153 self._rows = (self.num_plots / self._cols) 154 155 if self.num_plots % self._cols != 0: 156 self._rows += 1 157 158 self._attr["width"] = AttrConf.HTML_WIDTH 159 self._attr["height"] = AttrConf.HTML_HEIGHT 160 self._init_html() 161 162 def add_plot(self, plot_num, data_frame, title=""): 163 """Add a plot to for a corresponding index""" 164 165 fig_name = self._fig_map[plot_num] 166 fig_params = {} 167 fig_params["data"] = json.loads(data_frame.to_json()) 168 fig_params["name"] = fig_name 169 fig_params["rangesel"] = False 170 fig_params["logscale"] = False 171 fig_params["title"] = title 172 fig_params["step_plot"] = self._attr["step_plot"] 173 fig_params["fill_graph"] = self._attr["fill"] 174 175 if "group" in self._attr: 176 fig_params["syncGroup"] = self._attr["group"] 177 if "sync_zoom" in self._attr: 178 fig_params["syncZoom"] = self._attr["sync_zoom"] 179 else: 180 fig_params["syncZoom"] = AttrConf.DEFAULT_SYNC_ZOOM 181 182 if "ylim" in self._attr: 183 fig_params["valueRange"] = self._attr["ylim"] 184 185 json_file = os.path.join(AttrConf.PLOTTER_STATIC_DATA_DIR, fig_name + ".json") 186 fh = open(json_file, "w") 187 json.dump(fig_params, fh) 188 fh.close() 189 190 def finish(self): 191 """Called when the Plotting is finished""" 192 193 figs = [] 194 195 for fig_idx in self._fig_map.keys(): 196 figs.append(self._fig_map[fig_idx]) 197 198 display(HTML(self.html())) 199 200 def html(self): 201 """Return the raw HTML text""" 202 203 return "\n".join(self._html) 204