14 from io 
import StringIO
 
   15 from html 
import escape
 
   17 from dateutil.relativedelta 
import relativedelta
 
   22     A base class for widgets in the hep ipython projects. 
   35         from IPython.core.display 
import display
 
   42     """The css string for styling the notebook.""" 
   60         """Create the styling widget.""" 
   61         from IPython.core.display 
import HTML
 
   62         html = HTML(
"<style>\n%s\n</style>" % self.
css_stringcss_string)
 
   68     Viewer Object used to print data to the IPython Notebook. 
   69     Do not use it on your own. 
   74         Create a new progress bar viewer. 
   76         from IPython.core.display 
import display
 
   77         from ipywidgets 
import FloatProgress, VBox, Layout, Label
 
   85         self.
progress_barprogress_bar = FloatProgress(value=0, min=0, max=1,
 
   86                                           layout=Layout(width=
"100%", height=
"40px"))
 
   94     def update(self, text_or_percentage):
 
   96         Update the widget with a new event number 
   99         if isinstance(text_or_percentage, numbers.Number):
 
  101             current_percentage = float(text_or_percentage)
 
  102             current_time = time.time()
 
  104             remaining_percentage = 1.0 - current_percentage
 
  106             time_delta = current_time - self.
last_timelast_time
 
  107             percentage_delta = current_percentage - self.
last_percentagelast_percentage
 
  109             if percentage_delta > 0:
 
  110                 time_delta_per_percentage = 1.0 * time_delta / percentage_delta
 
  113                 attrs = [
'years', 
'months', 
'days', 
'hours', 
'minutes', 
'seconds']
 
  115                 def human_readable(delta): 
return [
'%d %s' % (getattr(delta, attr), getattr(delta, attr) > 1 
and attr 
or attr[:-1])
 
  116                                                    for attr 
in attrs 
if getattr(delta, attr)]
 
  118                 times_list = human_readable(relativedelta(seconds=time_delta_per_percentage * remaining_percentage))
 
  119                 human_readable_str = 
" ".join(times_list)
 
  121                 display_text = 
"%d %% Remaining time: %s" % (
 
  122                     100 * current_percentage, human_readable_str)
 
  125                 self.
progress_barprogress_bar.value = float(current_percentage)
 
  128             self.
progress_labelprogress_label.value = f
"Status: {text_or_percentage}" 
  129             if "finished" in str(text_or_percentage):
 
  132             elif "failed" in str(text_or_percentage):
 
  141         from IPython.core.display 
import display
 
  148     Viewer object for the store entries. 
  149     Do not use it on your own. 
  154         Create a new collections viewer with the collections object from the process. 
  155         Collections must be a StoreContentList with a list of StoreContents. 
  161         self.
table_row_htmltable_row_html = 
"""<tr><td style="padding: 10px 0;">{content.name}</td> 
  162                                  <td style="padding: 10px 0;">{content.number}</td></tr>""" 
  169         import ipywidgets 
as widgets
 
  172             return widgets.HTML(
"")
 
  177         for i, event 
in enumerate(self.
collectionscollections):
 
  178             html = widgets.HTML()
 
  179             html.value = 
"""<table style="border-collapse: separate; border-spacing: 50px 0;">""" 
  180             for store_content 
in event.content:
 
  181                 html.value += self.
table_row_htmltable_row_html.format(content=store_content)
 
  182             html.value += 
"</table>" 
  183             children.append(html)
 
  184             a.set_title(i, 
"Event " + str(event.event_number))
 
  186         a.children = children
 
  193     A viewer widget for displaying the 
  194     statistics in a nicer way in ipython 
  198         """ Init the widget with the statistics from the process. 
  199         The statistics must be an instance of Statistics. """ 
  208         self.
table_cell_htmltable_cell_html = 
"""<td style="padding: 10px; text-align: left">{content}</td>""" 
  210         self.
table_cell_3_htmltable_cell_3_html = 
"""<td style=\"text-align: right\">{content[0]}</td><td>{content[1]}</td><td>{content[2]}</td>""" 
  216         import ipywidgets 
as widgets
 
  219             return widgets.HTML(
"")
 
  221         html = widgets.HTML()
 
  222         html.value = 
"""<table style="border-collapse: collapsed; border: 1px solid black;"> 
  223                         <thead><tr style="background: #AAA; font-weight: bold">""" 
  225         for column 
in self.
statisticsstatistics.columns:
 
  226             if column.three_column_format:
 
  227                 html.value += self.
table_column_3_htmltable_column_3_html.format(content=column.display_name)
 
  229                 html.value += self.
table_column_htmltable_column_html.format(content=column.display_name)
 
  230         html.value += 
"</tr></thead><tbody>" 
  232         for n, module 
in enumerate(self.
statisticsstatistics.modules):
 
  234                 html.value += 
"""<tr style="background: #EEE;">""" 
  236                 html.value += 
"""<tr>""" 
  238             for column 
in self.
statisticsstatistics.columns:
 
  239                 if column.three_column_format:
 
  240                     html.value += self.
table_cell_3_htmltable_cell_3_html.format(content=module[column.name])
 
  242                     html.value += self.
table_cell_htmltable_cell_html.format(content=module[column.name])
 
  244             html.value += 
"</tr>" 
  248         html.value += 
"</tbody></table>" 
  255     A widget to summarize all the infromation from different processes. 
  256     Must be filled with the widgets of the single processes 
  261         Create a process viewer 
  271         import ipywidgets 
as widgets
 
  274         for i 
in range(len(self.
childrenchildren)):
 
  275             a.set_title(i, 
"Process " + str(i))
 
  276         a.children = [children.create() 
for children 
in self.
childrenchildren 
if children 
is not None]
 
  284         import ipywidgets 
as widgets
 
  285         from IPython.core.display 
import display
 
  291             a = widgets.HTML(
"<strong>Calculation list empty. Nothing to show.</strong>")
 
  298     A widget to show the log of a calculation. 
  303         Initialize the log viewer. 
  310         self.
log_levelslog_levels = [
"DEBUG", 
"INFO", 
"RESULT", 
"WARNING", 
"ERROR", 
"FATAL", 
"DEFAULT"]
 
  313         self.
log_color_codeslog_color_codes = {
"DEBUG": 
"gray", 
"ERROR": 
"red", 
"FATAL": 
"red", 
"INFO": 
"black", 
"RESULT": 
"green",
 
  314                                 "WARNING": 
"orange", 
"DEFAULT": 
"black"}
 
  317         self.
log_messagelog_message = 
"""<pre class="log-line-{type_lower}" title="{info}">[{level}] {message}{var_output}</pre>""" 
  321                                                  $('.log-line-{type_lower}-hide-button').hide(); 
  322                                                  $('.log-line-{type_lower}-show-button').show();" 
  323                                         style="cursor: pointer; margin: 0px 10px;" 
  324                                         class="log-line-{type_lower}-hide-button">Hide {type_upper}</a> 
  325                                      <a onclick="$('.log-line-{type_lower}').show(); 
  326                                                  $('.log-line-{type_lower}-hide-button').show(); 
  327                                                  $('.log-line-{type_lower}-show-button').hide();" 
  328                                         style="cursor: pointer; margin: 0px 10px; display: none;" 
  329                                         class="log-line-{type_lower}-show-button">Show {type_upper}</a>""" 
  333         Format the json object of a logmessage as key: value list with recursion and indentation 
  334         Funnily this is faster than json.dumps() and looks a bit better in the title attribute 
  336         for key, val 
in message.items():
 
  339             if isinstance(val, dict):
 
  340                 buf.write(f
"{key}:\n")
 
  341                 self.
format_logmessageformat_logmessage(buf, val, indent=indent, base=base + indent)
 
  343                 buf.write(base * 
" ")
 
  344                 buf.write(f
"{key}: {val!r}\n")
 
  348         Create the log viewer. 
  350         from ipywidgets 
import HTML, HBox, VBox
 
  353         output.write(
"<style scoped>\n")
 
  355             level = level.lower()
 
  356             output.write(f
".log-line-{level} {{margin:0; padding:0; line-height:normal; color: {color} !important;}}\n")
 
  358         output.write(
"""</style><div style="max-height: 400px; overflow-y: auto; width: 100%";>""")
 
  360         for line 
in self.
log_contentlog_content.split(
"\n"):
 
  361             if line.startswith(
'{"level"'):
 
  363                     message = json.loads(line)
 
  370                     info = escape(buf.getvalue())
 
  372                     variables = message.get(
"variables", 
"")
 
  374                         variables = 
"\n".join([
""] + [f
"\t{k} = {v}" for k, v 
in variables.items()])
 
  376                     level = message[
"level"].lower()
 
  377                     output.write(self.
log_messagelog_message.format(info=info, type_lower=level, var_output=variables, **message))
 
  379                 except json.JSONDecodeError:
 
  383             output.write(
'<pre class="log-line-default">')
 
  385             output.write(
'</pre>')
 
  387         output.write(
"</div>")
 
  390         html.value = output.getvalue()
 
  396             buttons.append(HTML(self.
toggle_button_linetoggle_button_line.format(type_lower=type.lower(), type_upper=type.upper())))
 
  398         buttons_view = HBox(buttons)
 
  399         buttons_view.margin = 
"10px 0px" 
  400         result_vbox = VBox((buttons_view, html))