HTMLView.py
Go to the documentation of this file.
1 import common_tools as tools
2 from PageMaker import PageMaker
3 import naming_schema
4 import os
5 import glob
6 
7 class HTMLView():
8 
9  def __init__(self, controller_view, breadcrumb=False, reuse_histograms=False, verbose=True, testing=False):
10  self.verbose = verbose
11  self.testing = testing
12  self.reuse_histograms = reuse_histograms
13  self.controller_view = controller_view
14  self.breadcrumb = breadcrumb
15 
17  if self.testing:
18  self.directory_base = "%s/%s/v%s"%(os.environ["NOVAANAVALID_WEB_TEST"],self.controller_view.controller.name,self.controller_view.controller.version)
19  else:
20  self.directory_base = "%s/%s/v%s"%(os.environ["NOVAANAVALID_WEB"],self.controller_view.controller.name,self.controller_view.controller.version)
21  tools.mkdir(self.directory_base)
22  self.url_base = tools.directoryToURL(self.directory_base)
23  if self.verbose:
24  print "vhtml: Directory base: %s"%self.directory_base
25  print "vhtml: URL base: %s"%self.url_base
26 
27  # Fill a map for the cross linking
28  pages = []
29  page_info = []
30  components = []
31  dropdowns = {}
32  plot_map = {}
33 
34  for component_type in self.controller_view.component_type_keys:
35  if component_type not in self.controller_view.plot_groups.keys(): continue
36  if self.verbose: print "vhtml: component type: %s, %i plot groups"%(component_type,len(self.controller_view.plot_groups[component_type]))
37  component_directory_base = "%s/%s"%(self.directory_base,component_type)
38  tools.mkdir(component_directory_base)
39  component_url_base = tools.directoryToURL(component_directory_base)
40 
41  if component_type not in dropdowns.keys(): dropdowns[component_type] = []
42 
43  for plot_group in self.controller_view.plot_groups[component_type]:
44  if self.verbose: print "vhtml: group: %s"%(plot_group)
45  if plot_group not in dropdowns[component_type]: dropdowns[component_type].append(plot_group)
46 
47  html_page = PageMaker(plot_group.replace(" ","_")+".html", component_directory_base, component_url_base)
48  if self.breadcrumb:
49  breadcrumb = self.breadcrumb
50  breadcrumb += '<li><a href="%s/index.html">%s</a></li>'%(component_url_base, naming_schema.componentName(component_type))
51  breadcrumb += '<li class="active">%s</li>'%plot_group
52  html_page.addContent("<!--BREADCRUMB_HOOK-->", breadcrumb)
53  self.add_navbar_hook(html_page)
54  self.add_sidebar_hook(html_page)
55  self.add_controls(html_page, plot_group.replace(" ","_"))
56 
57  plots = self.controller_view.plot_information[component_type].keys()
58  plots = tools.sortPlotList(plots)
59 
60  title = '<h1 class="page-header">%s: %s</h1>'%(naming_schema.componentName(component_type), plot_group)
61  html_page.addContent("<!--BODY_HOOK-->",title)
62 
63  current_category = False
64  self.sidebar_index = -1
65  any_truth = False
66  previous_observable = False
67  reco_levels = []
68  for i,plot in enumerate(plots):
69  plot_info = self.controller_view.plot_information[component_type][plot]
70  if plot_info.group != plot_group: continue
71  plot_name = plot.split("/")[-1].split(".")[0]
72  true_level = tools.getHistogramTrueLevel(plot_name)
73  reco_level = tools.getHistogramRecoLevel(plot_name)
74  if plot_info.true_components: any_truth = True
75  # true levels are added as options
76  if (true_level != ""): continue
77  # check if this is the same observable as previously - if so we're in a reco group
78  observable = tools.getHistogramObservable(plot_name)
79  if (observable == previous_observable):
80  reco_levels.append(reco_level)
81  self.add_plot_information(html_page, plot_name, plot_info)
82  continue
83  # if not, then we're in a new observable
84  self.add_reco_level_controls(html_page, reco_levels)
85  previous_observable = observable
86  reco_levels = [reco_level]
87 
88  # populate the sidebar and body headings on category change
89  this_category = tools.getHistogramCategory(plot_name)
90  if (this_category == "meta"): continue
91  if (this_category == "true") and ("data" in plot_group): continue
92  if this_category != current_category:
93  current_category = this_category
94  self.add_sidebar_section(current_category, html_page)
95  subtitle = '<h2 id="%s">%s</h2><hr>'%(current_category,naming_schema.categoryName(current_category))
96  html_page.addContent("<!--BODY_HOOK-->",subtitle)
97 
98  # Are we expecting a ratio plot
99  ratio = (len(plot_info.names) > 1) and ("contour" not in observable)
100 
101  # print plot_name, plot_info.names, true_level
102  folder = plot_group.replace(" ","_")
103  self.copy_figure(plot,"%s/%s/"%(component_directory_base, folder))
104  self.add_figure(plot_name, folder, plot_info, html_page, component_type, plot_group, ratio=ratio, normalisations=plot_info.normalisations, truth=any_truth, reco_level=reco_level)
105  self.add_plot_information(html_page, plot_name, plot_info)
106  # add in the final reco level control
107  self.add_reco_level_controls(html_page, reco_levels)
108  # print html_page.content
109  html_page.addContent("<!--BODY_HOOK-->","<!--FOOTER_HOOK-->")
110  pages.append(html_page)
111  page_info.append([component_type, plot_group])
112 
113  # go over all pages and fill in links
114  for i,page in enumerate(pages):
115  self.add_navbar_dropdowns(page, page_info[i], dropdowns)
116  page.write()
117 
118  def add_controls(self, page, folder):
119  html = \
120  """
121  <script>
122  var DATA = {}
123  DATA.folder = "%s"
124  DATA.statistics = {};
125  var VIEW = {};
126  VIEW.plot_selections = {};
127  // JS_HOOK
128 
129  </script>
130  <script src="http://nusoft.fnal.gov/nova/production/static/d3.v3.min.js"></script>
131  <script src="http://nusoft.fnal.gov/nova/users/tamsett/validation/static/d3_controls_local.js"></script>
132  """%(folder)
133  page.addContent("<!--JS_HOOK-->",html)
134 
135  def copy_figure(self, full_path, target):
136  tools.mkdir(target)
137  path = "/".join(full_path.split("/")[:-1])
138  name_base = full_path.split("/")[-1][:-4]
139  category = tools.getHistogramCategory(name_base)
140  observable = tools.getHistogramObservable(name_base)
141  plot_type = "%s-%s"%(category,observable)
142 
143  files = glob.glob("%s/*%s*"%(path,plot_type))
144  for path in files:
145  if self.reuse_histograms:
146  name = path.split("/")[-1]
147  if os.path.exists("%s/%s"%(name_base,name)): continue
148  cmd = "cp %s %s"%(path,target)
149  os.system(cmd)
150 
151  def add_navbar_hook(self, page):
152  html = \
153  """
154  <ul class="nav navbar-nav navbar-right">
155  <li class="dropdown">
156  <a href="#" class="dropdown-toggle" data-toggle="dropdown">Datasets <span class="caret"></span></a>
157  <ul class="dropdown-menu" role="menu">
158  <!--NAVBAR_DATASET_HOOK-->
159  </ul>
160  </li>
161  </ul>
162  """
163  page.addContent("<!--NAVBAR_HOOK-->", html)
164 
165  def add_navbar_dropdowns(self, page, info, dropdowns):
166  plot_groups = dropdowns[info[0]]
167  plot_groups.sort()
168  for plot_group in plot_groups:
169  if plot_group == info[1]:
170  suffix = ' class="active"'
171  else:
172  suffix = ''
173  html = '<li%s><a href="%s/%s/%s">%s</a></li>'%(suffix, self.url_base, info[0], plot_group.replace(" ","_")+".html", plot_group)
174  page.addContent("<!--NAVBAR_DATASET_HOOK-->", html)
175 
176  def add_sidebar_hook(self, page):
177  page.addContent("<!--FOOTER_HOOK-->", "", destructive=True)
178  html = \
179  """
180  <div class="col-sm-3 col-md-2 sidebar">
181  <!--SIDEBAR_HOOK-->
182  </div> <!-- end of side bar -->
183  <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
184  <!--MODAL_HOOK-->
185  <!--BODY_HOOK-->
186  </div> <!-- end of main body -->
187  """
188  page.addContent("<!--BODY_HOOK-->", html, destructive=True)
189 
190  def add_sidebar_section(self, category, page):
191  self.sidebar_index += 1
192  title = \
193  """
194  <h4>%s</h4>
195  <!--SIDEBAR_SECTION_%i_HOOK-->
196  <hr>
197  """%(naming_schema.categoryName(category),self.sidebar_index)
198  page.addContent("<!--SIDEBAR_HOOK-->",title)
199 
200  def add_figure(self, name, folder, information, page, component_type, plot_group, ratio=False, reco_level="", reco_level_controls=True, normalisations=False, truth=False):
201  histogram_name = naming_schema.observableName(tools.getHistogramObservable(name))
202  if reco_level != "":
203  reco_value = "-%s"%reco_level
204  name_wo_reco = name.replace("-%s"%reco_level,"")
205  else:
206  reco_value = reco_level
207  name_wo_reco = name
208 
209  if len(normalisations): default_prefix = "area_norm_"
210  else: default_prefix = ""
211 
212  page.addContent("// JS_HOOK",'VIEW.plot_selections["%s"] = {};'%name_wo_reco)
213  page.addContent("// JS_HOOK",'VIEW.plot_selections["%s"]["log"] = "";'%name_wo_reco)
214  page.addContent("// JS_HOOK",'VIEW.plot_selections["%s"]["norm"] = "%s";'%(name_wo_reco,default_prefix))
215  page.addContent("// JS_HOOK",'VIEW.plot_selections["%s"]["truth"] = "";'%name_wo_reco)
216  page.addContent("// JS_HOOK",'VIEW.plot_selections["%s"]["zoom"] = "";'%name_wo_reco)
217  page.addContent("// JS_HOOK",'VIEW.plot_selections["%s"]["reco_level"] = "%s";'%(name_wo_reco,reco_value))
218 
219  sidebar_link = '<p><a href="#row_%s">%s</a></p>'%(name_wo_reco, histogram_name)
220  page.addContent("<!--SIDEBAR_SECTION_%i_HOOK-->"%self.sidebar_index, sidebar_link)
221 
222  row = \
223  """
224  <div class="row" id="row_%s">
225  <div class="col-xs-12 col-sm-12 col-md-12 col-lg-6" id="figure" value="%s", ratio="False">
226  <a href="#" data-toggle="modal" data-target="#%s">
227  <img src="./%s/%s%s.png" class="img-responsive" alt="..." id="%s">
228  </a>
229  <p class="text-right" id="download_%s">
230  <text><a href="./%s/%s.png" download>png</a> </text>
231  </p>
232  <!--RATIO_HOOK-->
233  </div>
234  <div class="col-xs-12 col-sm-12 col-md-12 col-lg-6">
235  <br>
236  <div class="panel panel-default">
237  <div class="panel-heading text-left">
238  <h3 class="panel-title">%s</h3>
239  </div>
240  <div class="panel-body text-left">
241 
242  <!--TEXT_HOOK-->
243  <!--TABLE_HOOK-->
244 
245  </div>
246  </div>
247  <div class="panel panel-default">
248  <div class="panel-heading text-left">
249  <h3 class="panel-title">Controls</h3>
250  </div>
251  <div class="panel-body text-left">
252  <div class="row">
253  <div class="form-group">
254  <label for="log_control_%s" class="col-lg-4 control-label">Log y:</label>
255  <div class="col-lg-8">
256  <select id="log_control_%s">
257  <option value="">disable</option>
258  <option value="log_">enable</option>
259  </select>
260  </div>
261  </div>
262  </div>
263  <!--PLOT_CONTROL_HOOK-->
264  </div>
265  </div>
266  <p class="text-right"><a href="#top">Top of page</a></p>
267  </div>
268  </div> <!-- end of this plot row -->
269  <hr>
270  """%(name_wo_reco,
271  name_wo_reco,
272  name_wo_reco,
273  folder,default_prefix,name,name_wo_reco,
274  name_wo_reco,
275  folder,name,
276  histogram_name,name_wo_reco,name_wo_reco)
277 
278  modal = \
279  """
280  <div class="modal fade" id="%s" tabindex="-1" role="dialog" aria-labelledby="%sLabel" aria-hidden="true">
281  <div class="modal-dialog modal-lg">
282  <div class="modal-content">
283  <div class="modal-body">
284  <img src="./%s/%s%s.png" class="img-responsive" alt="..." id="%s">
285  </div>
286  <div class="modal-footer">
287  <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
288  </div>
289  </div><!-- /.modal-content -->
290  </div><!-- /.modal-dialog -->
291  </div><!-- /.modal -->
292  """%(name_wo_reco,name_wo_reco,
293  folder,default_prefix,name,name_wo_reco)
294  page.addContent("<!--MODAL_HOOK-->",modal)
295 
296  if (len(normalisations) > 1):
297  norm_control = \
298  """
299  <div class="row">
300  <div class="form-group">
301  <label for="norm_control_%s" class="col-lg-4 control-label">Normalisation:</label>
302  <div class="col-lg-8">
303  <select id="norm_control_%s">
304  <!--NORM_CONTROL_HOOK-->
305  </select>
306  </div>
307  </div>
308  </div>
309  """%(name_wo_reco,name_wo_reco)
310  for norm in normalisations:
311  this_option = '<option value="%s">%s</option>'%(norm[1],norm[0])
312  norm_control = norm_control.replace("<!--NORM_CONTROL_HOOK-->","%s<!--NORM_CONTROL_HOOK-->"%this_option)
313  row = row.replace("<!--PLOT_CONTROL_HOOK-->","%s<!--PLOT_CONTROL_HOOK-->"%norm_control)
314 
315  if (truth):
316  truth_control = \
317  """
318  <div class="row">
319  <div class="form-group">
320  <label for="truth_control_%s" class="col-lg-4 control-label">Truth:</label>
321  <div class="col-lg-8">
322  <select id="truth_control_%s">
323  <option value="">All</option>
324  <option value="-truth-components">By component</option>
325  </select>
326  </div>
327  </div>
328  </div>
329  """%(name_wo_reco,name_wo_reco)
330  row = row.replace("<!--PLOT_CONTROL_HOOK-->","%s<!--PLOT_CONTROL_HOOK-->"%truth_control)
331 
332  if (ratio):
333  ratio_html = \
334  """
335  <br>
336  <a href="#" data-toggle="modal" data-target="#ratio_%s">
337  <img src="./%s/ratio_%s%s.png" class="img-responsive" alt="..." id="ratio_%s">
338  </a>
339  <p class="text-right" download id="download_ratio_%s">
340  <text><a href="./%s/ratio_%s.png">png</a> </text>
341  </p>
342  """%(name_wo_reco,folder,default_prefix,name,name_wo_reco,
343  name_wo_reco,
344  folder,name
345  )
346  row = row.replace("<!--RATIO_HOOK-->", ratio_html)
347  row = row.replace('ratio="False"', 'ratio="True"')
348  row_control = \
349  """
350  <div class="row">
351  <div class="form-group">
352  <label for="zoom_control_%s" class="col-lg-4 control-label">Ratio zoom:</label>
353  <div class="col-lg-8">
354  <select id="zoom_control_%s">
355  <option value="">none</option>
356  <option value="zoom_">zoom</option>
357  </select>
358  </div>
359  </div>
360  </div>
361  """%(name_wo_reco,name_wo_reco)
362  row = row.replace("<!--PLOT_CONTROL_HOOK-->","%s<!--PLOT_CONTROL_HOOK-->"%row_control)
363 
364  modal = \
365  """
366  <div class="modal fade" id="ratio_%s" tabindex="-1" role="dialog" aria-labelledby="ratio_%sLabel" aria-hidden="true">
367  <div class="modal-dialog modal-lg">
368  <div class="modal-content">
369  <div class="modal-body">
370  <img src="./%s/ratio_%s%s.png" class="img-responsive" alt="..." id="ratio_%s">
371  </div>
372  <div class="modal-footer">
373  <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
374  </div>
375  </div><!-- /.modal-content -->
376  </div><!-- /.modal-dialog -->
377  </div><!-- /.modal -->
378  """%(name_wo_reco,name_wo_reco,
379  folder,default_prefix,name,name_wo_reco)
380  page.addContent("<!--MODAL_HOOK-->",modal)
381 
382  if (reco_level_controls):
383  level_control = \
384  """
385  <div class="row">
386  <div class="form-group">
387  <label for="reco_level_control_%s" class="col-lg-4 control-label">Reco cuts:</label>
388  <div class="col-lg-8">
389  <select id="reco_level_control_%s">
390  <!--RECO_LEVEL_CONTROL_HOOK-->
391  </select>
392  </div>
393  </div>
394  </div>
395  """%(name_wo_reco,name_wo_reco)
396  row = row.replace("<!--PLOT_CONTROL_HOOK-->","%s"%level_control)
397 
398  dataset_list = ""
399  for i,dataset in enumerate(information.datasets):
400  dataset_html = \
401  """
402  <div class="row">
403  <div class="col-lg-4">
404  <strong>%s:</strong>
405  </div>
406  <div class="col-lg-8">
407  %s
408  </div>
409  </div>
410  """%(information.names[i],dataset)
411  dataset_list += dataset_html
412 
413  text = dataset_list
414 
415  table_rows = ""
416  for i in range(len(information.datasets)):
417  table_rows += \
418  """
419  <tr id="content">
420  <td>{}</td>
421  <td>{:,}</td>
422  <td>{:.2f}</td>
423  <td>{:.2f}</td>
424  </tr>
425  """.format(information.names[i],
426  int(information.entries[i]),
427  # information.modes[i],
428  # information.medians[i],
429  information.means[i],
430  information.mean_diffs[i])
431 
432  table = \
433  """
434  <table class="table table-striped">
435  <tbody id="table_%s">
436  <tr>
437  <th>Dataset</th>
438  <th>Entries</th>
439  <th>Mean</th>
440  <th>Mean diff [%%]</th>
441  </tr>
442  %s
443  </tbody>
444  </table>
445  """%(name_wo_reco,table_rows)
446 
447  row = row.replace("<!--TEXT_HOOK-->", text)
448  row = row.replace("<!--TABLE_HOOK-->",table)
449 
450  page.addContent("<!--BODY_HOOK-->",row)
451 
452  def add_plot_information(self, page, name, information):
453  page.addContent("// JS_HOOK",'DATA.statistics["%s"] = [];'%name)
454  for i,label in enumerate(information.names):
455  info_core = '"name":"{}","entries":"{:,}","mean":"{:.2f}","mean_diff":"{:.2f}"'.format(label,int(information.entries[i]),information.means[i],information.mean_diffs[i])
456  info = "{%s}"%info_core
457  page.addContent("// JS_HOOK",'DATA.statistics["%s"].push(%s);'%(name,info))
458 
459  def add_reco_level_controls(self, page, reco_levels):
460  html = ""
461  for reco_level in reco_levels:
462  if reco_level != "": reco_value = "-%s"%reco_level
463  else: reco_value = reco_level
464  html += '<option value="%s">%s</option>'%(reco_value,naming_schema.recoLevelName(reco_level))
465  page.addContent("<!--RECO_LEVEL_CONTROL_HOOK-->", html, destructive=True)
466 
467 
def add_navbar_hook(self, page)
Definition: HTMLView.py:151
void split(double tt, double *fr)
def add_sidebar_hook(self, page)
Definition: HTMLView.py:176
keys
Reco plots.
Definition: caf_analysis.py:46
def add_figure(self, name, folder, information, page, component_type, plot_group, ratio=False, reco_level="", reco_level_controls=True, normalisations=False, truth=False)
Definition: HTMLView.py:200
def copy_figure(self, full_path, target)
Definition: HTMLView.py:135
def add_controls(self, page, folder)
Definition: HTMLView.py:118
def __init__(self, controller_view, breadcrumb=False, reuse_histograms=False, verbose=True, testing=False)
Definition: HTMLView.py:9
def add_reco_level_controls(self, page, reco_levels)
Definition: HTMLView.py:459
def categoryName(name)
get a histogram category name
std::string format(const int32_t &value, const int &ndigits=8)
Definition: HexUtils.cpp:14
def add_sidebar_section(self, category, page)
Definition: HTMLView.py:190
def componentName(name)
get a component name
def write_component_html(self)
Definition: HTMLView.py:16
def add_navbar_dropdowns(self, page, info, dropdowns)
Definition: HTMLView.py:165
def observableName(name)
get a histogram observable name
def add_plot_information(self, page, name, information)
Definition: HTMLView.py:452
def recoLevelName(name)
get a reconstructed level