def test_dropdown_link(): page = markup.page() html.dropdown_link(page, None) assert parse_html(str(page)) == parse_html('<li class="divider">\n</li>') page = markup.page() html.dropdown_link(page, 'test', active=True) assert parse_html( str(page)) == parse_html('<li class="active">\ntest\n</li>') page = markup.page() html.dropdown_link(page, 'test') assert parse_html(str(page)) == parse_html('<li>\ntest\n</li>')
def test_dropdown_link(): page = markup.page() html.dropdown_link(page, None) assert parse_html(str(page)) == parse_html( '<div class="dropdown-divider"></div>') page = markup.page() html.dropdown_link(page, 'test', active=True) assert parse_html(str(page)) == parse_html('test') page = markup.page() html.dropdown_link(page, 'test') assert parse_html(str(page)) == parse_html('test')
def test_dropdown_link(): page = markup.page() html.dropdown_link(page, None) assert parse_html(str(page)) == parse_html( '<li class="divider">\n</li>') page = markup.page() html.dropdown_link(page, 'test', active=True) assert parse_html(str(page)) == parse_html( '<li class="active">\ntest\n</li>') page = markup.page() html.dropdown_link(page, 'test') assert parse_html(str(page)) == parse_html( '<li>\ntest\n</li>')
def write_arguments(content, start, end, flag=None, section='Parameters', info='This analysis used the following parameters:', id_='parameters'): """Render an informative section with run parameters in HTML Parameters ---------- content: `dict` a collection of parameters to list section: `str` name of the section, will appear as a header with an <h2> tag """ content.insert(0, ('Start time', '{} ({})'.format(start, from_gps(start)))) content.insert(1, ('End time', '{} ({})'.format(end, from_gps(end)))) if flag is not None: content.insert(2, ('State flag', flag)) page = markup.page() page.h2(section, id_=id_) page.p(info) for item in content: page.add(write_param(*item)) page.add(write_param('Command-line', '')) page.add(get_command_line()) return page()
def get_command_line(language='bash', about=True): """Render the command line invocation used to generate a page Parameters ---------- language : `str`, optional type of environment the code is run in, default: `'bash'` Returns ------- page : `~MarkupPy.markup.page` fully rendered command-line arguments """ page = markup.page() if about: page.p('This page was generated with the following command-line call:') if sys.argv[0].endswith('__main__.py'): module = getmodule(stack()[1][0]).__name__ cmdline = '$ python -m {0} {1}'.format(module, ' '.join(sys.argv[1:])) else: script = os.path.basename(sys.argv[0]) cmdline = ' '.join(['$', script, ' '.join(sys.argv[1:])]) page.add(render_code(cmdline.replace(' --html-only', ''), language)) if about: page.p('The install path used was <code>{}</code>.'.format(sys.prefix)) return page()
def scaffold_omega_scans(times, channel, plot_durations=[1, 4, 16], scandir=os.path.curdir): """Preview a batch of omega scans in HTML """ page = markup.page() page.div(class_='panel well panel-default') page.div(class_='panel-heading clearfix') page.h3(cis_link(channel), class_='panel-title') page.div.close() # panel-heading page.ul(class_='list-group') for t in times: page.li(class_='list-group-item') page.div(class_='container') page.div(class_='row') page.div(class_='pull-right') page.a("[full scan]", href='{}/{}'.format(scandir, t), class_='text-dark') page.div.close() # pull-right page.h4(t) page.div.close() # row chanstr = channel.replace('-', '_').replace(':', '-') plots = [ '{}/{}/plots/{}-qscan_whitened-{}.png'.format( scandir, t, chanstr, dur) for dur in plot_durations] page.add(scaffold_plots( [FancyPlot(plot) for plot in plots], nperrow=3)) page.div.close() # container page.li.close() # list-group-item page.ul.close() # list-group page.div.close() # panel return page()
def state_switcher(states, default=0): """Build a state switch button, including all of the given states, with the default selected by index """ current, chref = states[default] page = markup.page() page.ul(class_='nav navbar-nav') page.li(class_='nav-item dropdown') page.a(str(current), class_='nav-link dropdown-toggle', href='#', id_='states', role='button', title='Show/hide state menu', **{'data-toggle': 'dropdown'}) page.div( class_='dropdown-menu dropdown-menu-right state-switch shadow', id_='statemenu', ) page.h6( 'Select below to view this page in another state (different ' 'time segments).', class_='dropdown-header') page.div('', class_='dropdown-divider') for i, (state, href) in enumerate(states): page.a(str(state), class_='dropdown-item state', title=str(state), id_='state_%s' % re_cchar.sub('_', str(state)).lower(), onclick='jQuery(this).load_state(\'%s\');' % href) page.div.close() # dropdown-menu dropdown-menu-right page.li.close() # nav-item dropdown state-switch page.ul.close() # nav navbar-nav return page
def banner(ifo, start, end): """Initialise a new markup banner Parameters ---------- ifo : `str` the interferometer prefix start : `int` the GPS start time of the analysis end : `int` the GPS end time of the analysis Returns ------- page : `markup.page` the structured markup to open an HTML document """ # create page page = markup.page() # write banner page.div(class_='page-header', role='banner') page.h1("%s HierarchicalVeto" % ifo, class_='pb-2 mt-3 mb-2 border-bottom') page.h3("%d-%d" % (start, end), class_='mt-3') page.div.close() return page()
def comments_box(name, identifier=None, title=None, url=None): """Generate a Disqus comments box """ page = markup.page() page.div(id_='disqus_thread') page.script(type='text/javascript') page.add(' var disqus_shortname = "%s";' % name) if identifier: page.add(' var disqus_identifier = "%s";' % identifier) if title: page.add(' var disqus_title = "%s";' % title) if url: page.add(' var disqus_url = "%s";' % url) page.add(""" (function() { var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js'; (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); })(); """) page.script.close() page.noscript("Please enable JavaScript to view the") page.a("comments powered by Disqus", href="https://disqus.com/?ref_noscript") page.div.close() return page
def get_command_line(language='bash', about=True, prog=None): """Render the command-line invocation used to generate a page Parameters ---------- language : `str`, optional type of environment the code is run in, default: `'bash'` about : `bool`, optional whether this markup is for an 'about' page, default: `True` prog : `str`, optional name of the program which produced this page, defaults to the script run on the command-line Returns ------- page : `~MarkupPy.markup.page` fully rendered command-line arguments """ prog = prog or os.path.basename(sys.argv[0]) page = markup.page() if about: page.p('This page was generated with the following command-line call:') args = ' '.join(sys.argv[1:]) cmdline = ' '.join(['$', prog, args]) page.add(render_code(cmdline.replace(' --html-only', ''), language)) if about: page.p('The install path used was <code>{}</code>.'.format(sys.prefix)) return page()
def banner(title, subtitle=None, titleclass=None, subtitleclass=None): """Construct a banner heading in bootstrap format Parameters ---------- title : `str` name of page (<h1>) subtitle : `str`, optional description of page (<p>) titleclass : `str`, optional class option for <h1> subtitleclass : `str`, optional class option for <p> Returns ------- banner : `~MarkupPy.markup.page` markup.py `page` instance """ page = markup.page() page.div(class_='banner') if titleclass is None: page.h1(str(title)) else: page.h1(str(title), class_=titleclass) if subtitle is not None and subtitleclass is not None: page.p(subtitle, class_=subtitleclass) elif subtitle is not None: page.p(subtitle) page.div.close() return page
def write_null_page(reason, context='info'): """Write the Hveto results to HTML Parameters ---------- ifo : `str` the prefix of the interferometer used in this analysis start : `int` the GPS start time of the analysis end : `int` the GPS end time of the analysis reason : `str` the explanation for this null result context : `str`, optional the bootstrap context class for this result, see the bootstrap docs for more details outdir : `str`, optional the output directory for the HTML Returns ------- index : `str` the path of the HTML written for this analysis """ page = markup.page() # write alert page.div(class_='alert alert-%s' % context) page.p(reason) page.div.close() # alert return page
def write_null_page(reason, context='default'): """Write the Qscan results to HTML Parameters ---------- ifo : `str` the prefix of the interferometer used in this analysis gpstime : `float` the central GPS time of the analysis reason : `str` the explanation for this null result context : `str`, optional the bootstrap context class for this result, see the bootstrap docs for more details Returns ------- index : `str` the path of the HTML written for this analysis """ page = markup.page() # write alert page.div(class_='alert alert-%s' % context) page.p(reason) page.div.close() # alert return page
def write_qscan_page(blocks, context): """Write the Qscan results to HTML Parameters ---------- ifo : `str` the prefix of the interferometer used in this analysis gpstime : `float` the central GPS time of the analysis blocks : `dict` of `OmegaChannel` the channel blocks scanned in the analysis context : `str`, optional the type of Bootstrap ``<panel>`` object to use, color-coded by GWO standard Returns ------- index : `str` the path of the HTML written for this analysis """ page = markup.page() page.div(class_='banner') page.h2('Channel details') page.div.close() # banner for key, block in blocks.items(): page.add(write_block(key, block, context)) return page
def overlay_canvas(): """Generate a dialog box allowing users to select and overlay plots Returns ------- page : `~MarkupPy.markup.page` fully rendered HTML containing the dialog box """ page = markup.page() page.h1('Overlay figures for easy comparison') page.hr(class_='row-divider') page.div(class_='row', id_='overlay-outer') page.div(class_='col-md-4') page.div(class_='card card-body shadow-sm', id_='overlay-info') page.h4('Instructions') page.add(markdown(OVERLAY_INSTRUCTIONS)) page.div.close() # card card-body shadow-sm page.div.close() # col-md-4 page.div(class_='col-md-8') page.div(class_='text-center') page.a('Overlay', title='Overlay all selected figures', class_='btn btn-light shadow-sm', id_='overlay-figures') page.a('Download', title='Download overlay figure', class_='btn btn-light shadow-sm', id_='download-overlay') page.a('Clear', title='Clear all figure selections', class_='btn btn-light shadow-sm', id_='clear-figures') page.div.close() # text-center page.br() page.add(markup.oneliner.canvas(id_='overlay-canvas')) page.div.close() # col-md-8 page.div.close() # row return dialog_box( str(page), title='Overlay figures', id_='overlay', btntxt=markup.oneliner.i('', class_='fas fa-layer-group'))
def write_hveto_page(rounds, plots): """Write the Hveto results to HTML Parameters ---------- ifo : `str` the prefix of the interferometer used in this analysis start : `int` the GPS start time of the analysis end : `int` the GPS end time of the analysis rounds : `list` of `HvetoRound` the rounds produced by this analysis plots : `list` of `str` the `list` of summary plots outdir : `str`, optional the output directory for the HTML Returns ------- index : `str` the path of the HTML written for this analysis """ page = markup.page() page.add(write_summary(rounds, plots)) page.h2('Round details') for r in rounds: page.add(write_round(r)) return page
def write_footer(about=None, link=None, issues=None, content=None): """Write a <footer> for a bootstrap page Parameters ---------- about : `str`, optional path of about page to link link : `str`, optional HTML link to software name and version issues : `str`, optional HTML link to issue report page content : `str` or `~MarkupPy.markup.page`, optional additional footer content Returns ------- page : `~MarkupPy.markup.page` the markup object containing the footer HTML """ page = markup.page() page.twotags.append('footer') markup.element('footer', case=page.case, parent=page)(class_='footer') page.div(class_='container') # write user/time for analysis if link is None: version = get_versions()['version'] commit = get_versions()['full-revisionid'] url = 'https://github.com/gwdetchar/gwdetchar/tree/{}'.format(commit) link = markup.oneliner.a('View gwdetchar-{} on GitHub'.format(version), href=url, target='_blank') if issues is None: report = 'https://github.com/gwdetchar/gwdetchar/issues' issues = markup.oneliner.a('Report an issue', href=report, target='_blank') page.div(class_='row') page.div(class_='col-md-12') now = datetime.datetime.now() tz = reference.LocalTimezone().tzname(now) date = now.strftime('%H:%M {} on %d %B %Y'.format(tz)) page.p('This page was created by {user} at {date}.'.format(user=getuser(), date=date)) page.p('{link} | {issues}'.format(link=link, issues=issues)) # link to 'about' if about is not None: page.a('How was this page generated?', href=about) # extra content if isinstance(content, markup.page): page.add(str(content)) elif content is not None: page.p(str(content)) page.div.close() # col-md-12 page.div.close() # row page.div.close() # container markup.element('footer', case=page.case, parent=page).close() return page()
def state_switcher(states, default=0): """Build a state switch button, including all of the given states, with the default selected by index """ current, chref = states[default] page = markup.page() page.div(class_="btn-group pull-right state-switch") page.a(class_='navbar-brand dropdown-toggle', href='#', id_='states', title="Show/hide state menu", **{'data-toggle': 'dropdown'}) page.add(str(current)) page.b('', class_='caret') page.a.close() page.ul(class_='dropdown-menu', id_='statemenu') page.li( "Select an option below to view these data in another state " "(different time segments).", class_="dropdown-header") page.li('', class_="divider") for i, (state, href) in enumerate(states): page.li() page.a(str(state), class_='state', title=str(state), id_='state_%s' % re_cchar.sub('_', str(state)).lower(), onclick='$(this).load_state(\'%s\');' % href) page.li.close() page.ul.close() page.div.close() # btn-group return page
def write_hveto_page(rounds, plots, context='default'): """Write the Hveto results to HTML Parameters ---------- ifo : `str` the prefix of the interferometer used in this analysis start : `int` the GPS start time of the analysis end : `int` the GPS end time of the analysis rounds : `list` of `HvetoRound` the rounds produced by this analysis plots : `list` of `str` the `list` of summary plots outdir : `str`, optional the output directory for the HTML winners : `list` of `str`, optional list of channels that won each round context : `str`, optional the bootstrap context class for this result, see the bootstrap docs for more details Returns ------- index : `str` the path of the HTML written for this analysis """ page = markup.page() page.add(write_summary(rounds, plots)) page.h2('Round details', class_='mt-4', id_='rounds') for r in rounds: page.add(write_round(r, context=context)) return page
def scaffold_plots(plots, nperrow=3): """Embed a `list` of images in a bootstrap scaffold Parameters ---------- plot : `list` of `FancyPlot` the list of image paths to embed nperrow : `int` the number of images to place in a row (on a desktop screen) Returns ------- page : `~MarkupPy.markup.page` the markup object containing the scaffolded HTML """ page = markup.page() x = int(12//nperrow) # scaffold plots for i, p in enumerate(plots): if i % nperrow == 0: page.div(class_='row') page.div(class_='col-sm-%d' % x) page.add(fancybox_img(p)) page.div.close() # col if i % nperrow == nperrow - 1: page.div.close() # row if i % nperrow < nperrow-1: page.div.close() # row return page()
def write_state_information(self, state): page = markup.page() # state information page.h1("State information") if state.name.lower() == ALLSTATE: page.p("This page was generated using all available data, " "regardless of observatory operational state.") elif state.filename is None and state.definition is None: page.p("This page was generated using data in the " "<strong>%s</strong> state, segments for which depend " "on the input data for a given figure." % state.name) else: if state.filename: defn = 'via a segment file' elif state.MATH_DEFINITION.search(state.definition): defn = ('by the data condition <samp>%s</samp>' % state.definition) else: defn = ('by the data-quality flag <samp>%s</samp>' % state.definition) page.p("This page was generated using data in the " "<strong>%s</strong> state. This is defined %s." % (state.name, defn)) page.add( str( self.print_segments( state.active, table=True, caption='Segments for <strong>%s</strong> state' % state.name))) return page
def about_this_page(config, packagelist=True): """Write a blurb documenting how a page was generated, including the command-line arguments and configuration files used Parameters ---------- config : `str`, `list`, optional the absolute path(s) to one or a number of INI files used in this process packagelist : `bool`, optional boolean switch to include (`True`) or exclude (`False`) a comprehensive list of system packages Returns ------- page : :class:`~MarkupPy.markup.page` the HTML page to be inserted into the #main <div>. """ page = markup.page() page.div(class_='row') page.div(class_='col-md-12') page.h2('On the command-line') page.add(get_command_line()) # render config file(s) page.h2('Configuration files') page.p('The following INI-format configuration file(s) were passed ' 'on the comand-line and are reproduced here in full:') if isinstance(config, str): with open(config, 'r') as fobj: contents = fobj.read() page.add(render_code(contents, 'ini')) elif isinstance(config, list): page.div(class_='panel-group', id="accordion") for i, cpfile in enumerate(config): page.div(class_='panel panel-default') page.a(href='#file%d' % i, **{ 'data-toggle': 'collapse', 'data-parent': '#accordion' }) page.div(class_='panel-heading') page.h4(os.path.basename(cpfile), class_='panel-title') page.div.close() page.a.close() page.div(id_='file%d' % i, class_='panel-collapse collapse') page.div(class_='panel-body') with open(cpfile, 'r') as fobj: contents = fobj.read() page.add(render_code(contents, 'ini')) page.div.close() page.div.close() page.div.close() page.div.close() # render package list if packagelist: page.add(package_table()) page.div.close() page.div.close() return page()
def banner(ifo, start, end): """Initialise a new markup banner Parameters ---------- ifo : `str` the interferometer prefix start : `int` the GPS start time of the analysis end : `int` the GPS end time of the analysis Returns ------- page : `markup.page` the structured markup to open an HTML document """ # create page page = markup.page() # write banner page.div(class_='page-header', role='banner') page.h1("%s HierarchicalVeto" % ifo) page.h3("%d-%d" % (start, end)) page.div.close() return page()
def write_hveto_page(rounds, plots, context='default'): """Write the Hveto results to HTML Parameters ---------- ifo : `str` the prefix of the interferometer used in this analysis start : `int` the GPS start time of the analysis end : `int` the GPS end time of the analysis rounds : `list` of `HvetoRound` the rounds produced by this analysis plots : `list` of `str` the `list` of summary plots outdir : `str`, optional the output directory for the HTML winners : `list` of `str`, optional list of channels that won each round context : `str`, optional the bootstrap context class for this result, see the bootstrap docs for more details Returns ------- index : `str` the path of the HTML written for this analysis """ page = markup.page() page.add(write_summary(rounds, plots)) page.h2('Round details', id_='rounds') for r in rounds: page.add(write_round(r, context=context)) return page
def dialog_box(content, id_): """Generate a dialog box to be loaded modal atop the main page Parameters ---------- content : `str` either raw markdown text or the path to a file containing markdown, this will be rendered in HTML as the contents of the dialog box id_ : `str` unique identifier for the dialog box Returns ------- page : `~MarkupPy.markup.page` fully rendered HTML containing the dialog box """ page = markup.page() page.add('<dialog id="%s">' % id_) # MarkupPy does not support dialog page.a('✕', title='Close', onclick="closeDialog('%s')" % id_, class_='btn btn-default pull-right', **{'aria-label': 'Close'}) if os.path.isfile(content): with open(content, 'r') as source: content = source.read() page.add(markdown(str(content))) page.add('</dialog>') return page
def new_bootstrap_page(base=os.path.curdir, lang='en', refresh=False, navbar=None, **kwargs): """Create a new `~markup.page` with custom twitter bootstrap CSS and JS headers Parameters ---------- base : `str` relative path to the base directory where the page is located lang : `str`, optional language of the page, default: en refresh : `bool`, optional boolean switch to enable periodic page refresh, default: False navbar : `str`, optional HTML enconding of a floating navbar, will be ignored if not given, default: None """ # get kwargs with sensible defaults css = kwargs.pop('css', CSS_FILES) script = kwargs.pop('script', JS_FILES) # write CSS to static dir css, script = finalize_static_urls( os.path.join(os.path.curdir, 'static'), css, script, ) # create page page = markup.page() page.header.append('<!DOCTYPE HTML>') page.html(lang=lang) page.head() if refresh: # force-refresh if requested page.meta(http_equiv='refresh', content='60') # ensure nice formatting on most devices page.meta(http_equiv='Content-Type', content='text/html; charset=utf-8') page.meta(content='width=device-width, initial-scale=1.0', name='viewport') page.base(href=base) page._full = True # link files for f in css: page.link(href=f, rel='stylesheet', type='text/css', media='all') for f in script: page.script('', src=f, type='text/javascript') # add other attributes for key in kwargs: getattr(page, key)(kwargs[key]) # finalize header page.head.close() # open body and container page.body() if navbar is not None: page.add(navbar) page.div(class_='container') return page
def write_html(self, config=list(), top=None, **kwargs): if top is None: top = kwargs.get('base', self.path) kwargs.setdefault('title', '404: Page not found') page = markup.page() page.div(class_='alert alert-danger text-justify shadow-sm') page.p() page.strong("The page you are looking for does not exist.") page.p.close() page.p("This could be because the times for which you are looking " "were never processed (or have not happened yet), or because " "no page exists for the specific data products you want. " "Either way, if you think this is in error, please contact " "<a class=\"alert-link\" " "href=\"mailto:[email protected]\">the DetChar group</a>.") page.p("Otherwise, you might be interested in one of the following:") page.div(style="padding-top: 10px;") page.a("Take me back", role="button", class_="btn btn-lg btn-info", title="Back", href="javascript:history.back()") page.a("Take me up one level", role="button", class_="btn btn-lg btn-warning", title="Up", href="javascript:linkUp()") page.a("Take me to the top level", role="button", class_="btn btn-lg btn-success", title="Top", href=top) page.div.close() page.div.close() # alert alert-danger page.script(""" function linkUp() { var url = window.location.href; if (url.substr(-1) == '/') url = url.substr(0, url.length - 2); url = url.split('/'); url.pop(); window.location = url.join('/'); }""", type="text/javascript") return super(Error404Tab, self).write_html(page, **kwargs)
def scaffold_plots(plots, nperrow=3): """Embed a `list` of images in a bootstrap scaffold Parameters ---------- plot : `list` of `FancyPlot` the list of image paths to embed nperrow : `int` the number of images to place in a row (on a desktop screen) Returns ------- page : `~MarkupPy.markup.page` the markup object containing the scaffolded HTML """ page = markup.page() x = int(12 // nperrow) # scaffold plots for i, p in enumerate(plots): if i % nperrow == 0: page.div(class_='row') page.div(class_='col-sm-%d' % x) page.add(fancybox_img(p)) page.div.close() # col if i % nperrow == nperrow - 1: page.div.close() # row if i % nperrow < nperrow - 1: page.div.close() # row return page()
def export_set(cls, dataset): """HTML representation of a Dataset.""" stream = BytesIO() page = markup.page() page.table.open() if dataset.headers is not None: new_header = [ item if item is not None else '' for item in dataset.headers ] page.thead.open() headers = markup.oneliner.th(new_header) page.tr(headers) page.thead.close() for row in dataset: new_row = [item if item is not None else '' for item in row] html_row = markup.oneliner.td(new_row) page.tr(html_row) page.table.close() # Allow unicode characters in output wrapper = codecs.getwriter("utf8")(stream) wrapper.writelines(str(page)) return stream.getvalue().decode('utf-8')
def wrap_content(page): """Utility to wrap some HTML into the relevant <div>s for the main body of a page in bootstrap format Parameters ---------- page : :class:`~MarkupPy.markup.page`, `str` HTML content to be wrapped span : `int` column span of content, default: 'full' (``12``) Returns ------- wrappedpage : :class:`~MarkupPy.markup.page` A new `page` with the input content wrapped as .. code:: html <div class="container"> </div> """ out = markup.page() out.div(class_='container', id_='main') out.add(str(page)) out.div.close() return out
def base_map_dropdown(this, class_='btn-group pull-left base-map', id_=None, bases=dict()): """Construct a dropdown menu that links to a version of the current page on another server, based on a new base. """ # format id if id_: id_ = dict(id_=id_) else: id_ = dict() # format links baselinks = [ markup.oneliner.a(key, title=key, **{'data-new-base': val}) for (key, val) in bases.items() if key != this ] # slam it all together page = markup.page() if baselinks: page.div(class_=class_, **id_) page.add( str( html.dropdown(this, baselinks, class_='navbar-brand dropdown-toggle'))) page.div.close() else: page.div(str(this), class_='navbar-brand', **id_) return page
def write_about_page(configfiles): """Write a page explaining how a Qscan analysis was completed Parameters ---------- ifo : `str` the prefix of the interferometer used in this analysis gpstime : `float` the central GPS time of the analysis configfiles : `list` of `str` list of paths of the configuration files to embed outdir : `str`, optional the output directory for the HTML Returns ------- index : `str` the path of the HTML written for this analysis """ # set up page page = markup.page() page.h2('On the command line') page.p('This page was generated with the command line call shown below.') page.add(htmlio.get_command_line()) page.h2('Configuration file') page.p('Omega scans are configured with INI-format files. The ' 'configuration files for this analysis are shown below in full.') # range over config files for configfile in configfiles: with open(configfile, 'r') as fobj: inifile = fobj.read() page.add(htmlio.render_code(inifile, 'ini')) # add environment listing page.add(str(htmlio.package_table())) return page
def write_null_page(reason, context='info'): """Write the Qscan results to HTML Parameters ---------- ifo : `str` the prefix of the interferometer used in this analysis gpstime : `float` the central GPS time of the analysis reason : `str` the explanation for this null result context : `str` type of bootstrap alert box to use, default: ``info`` Returns ------- index : `str` the path of the HTML written for this analysis """ page = markup.page() page.add(htmlio.alert(reason, context=context, dismiss=False)) return page
def write_state_information(self, state): page = markup.page() # state information page.h1("State information") if state.name.lower() == ALLSTATE: page.p("This page was generated using all available data, " "regardless of observatory operational state.") elif state.filename is None and state.definition is None: page.p("This page was generated using data in the " "<strong>%s</strong> state, segments for which depend " "on the input data for a given figure." % state.name) else: if state.filename: defn = 'via a segment file' elif state.MATH_DEFINITION.search(state.definition): defn = ('by the data condition <samp>%s</samp>' % state.definition) else: defn = ('by the data-quality flag <samp>%s</samp>' % state.definition) page.p("This page was generated using data in the " "<strong>%s</strong> state. This is defined %s." % (state.name, defn)) page.add(str(self.print_segments( state.active, table=True, caption='Segments for <strong>%s</strong> state' % state.name))) return page
def scaffold_omega_scans(times, channel, plot_durations=[1, 4, 16], scandir=os.path.curdir): """Preview a batch of omega scans in HTML """ page = markup.page() page.div(class_='panel well panel-default') page.div(class_='panel-heading clearfix') page.h3(cis_link(channel), class_='panel-title') page.div.close() # panel-heading page.ul(class_='list-group') for t in times: page.li(class_='list-group-item') page.div(class_='container') page.div(class_='row') page.div(class_='pull-right') page.a("[full scan]", href='{}/{}'.format(scandir, t), class_='text-dark') page.div.close() # pull-right page.h4(t) page.div.close() # row chanstr = channel.replace('-', '_').replace(':', '-') plots = [ '{}/{}/plots/{}-qscan_whitened-{}.png'.format( scandir, t, chanstr, dur) for dur in plot_durations ] page.add(scaffold_plots([FancyPlot(plot) for plot in plots], nperrow=3)) page.div.close() # container page.li.close() # list-group-item page.ul.close() # list-group page.div.close() # panel return page()
def write_html(self, config=list(), top=None, **kwargs): if top is None: top = kwargs.get('base', self.path) kwargs.setdefault('title', '404: Page not found') page = markup.page() page.div(class_='alert alert-danger') page.p() page.strong("The page you are looking for doesn't exist") page.p.close() page.p("This could be because the times for which you are looking " "were never processed (or haven't even happened yet), or " "because no page exists for the specific data products you " "want. Either way, if you think this is in error, please " "contact <a class=\"alert-link\" " "href=\"mailto:[email protected]\">the DetChar group</a>.") page.p("Otherwise, you might be interested in one of the following:") page.div(style="padding-top: 10px;") page.a("Take me back", role="button", class_="btn btn-lg btn-info", title="Back", href="javascript:history.back()") page.a("Take me up one level", role="button", class_="btn btn-lg btn-warning", title="Up", href="javascript:linkUp()") page.a("Take me to the top level", role="button", class_="btn btn-lg btn-success", title="Top", href=top) page.div.close() page.div.close() page.script(""" function linkUp() { var url = window.location.href; if (url.substr(-1) == '/') url = url.substr(0, url.length - 2); url = url.split('/'); url.pop(); window.location = url.join('/'); }""", type="text/javascript") return super(Error404Tab, self).write_html(page, **kwargs)
def write_state_html(self, state): """Write the '#main' HTML content for this `StampPEMTab`. """ page = markup.page() a = markup.oneliner.a('analysis', href=self.url + '/', class_='alert-link', rel='external', target='_blank') if not (os.path.isdir(self.directory)): page.add( html.alert(( "No %s was performed for this period, " "please try again later." % a, "If you believe these data should have been found, please " "contact %s." % markup.oneliner.a('the DetChar group', class_='alert-link', href='mailto:[email protected]'), ), context='warning', dismiss=False)) elif not self.plots: page.add( html.alert(( "This %s produced no plots." % a, "If you believe these data should have been found, please " "contact %s." % markup.oneliner.a('the DetChar group', class_='alert-link', href='mailto:[email protected]'), ), context='warning', dismiss=False)) else: page.add( str( self.scaffold_plots(aclass='fancybox-stamp plot', **{'data-fancybox-type': 'iframe'}))) page.hr(class_='row-divider') # link full results page.hr(class_='row-divider') page.div(class_='btn-group') page.a('Click here for the full Stamp PEM results', href=self.url + '/', rel='external', target='_blank', class_='btn btn-default btn-info btn-xl') page.div.close() # write to file idx = self.states.index(state) with open(self.frames[idx], 'w') as fobj: fobj.write(str(page)) return self.frames[idx]
def write_footer(about=None, link=None, issues=None, content=None): """Write a <footer> for a bootstrap page Parameters ---------- about : `str`, optional path of about page to link link : `str`, optional HTML link to software name and version issues : `str`, optional HTML link to issue report page content : `str` or `~MarkupPy.markup.page`, optional additional footer content Returns ------- page : `~MarkupPy.markup.page` the markup object containing the footer HTML """ page = markup.page() page.twotags.append('footer') markup.element('footer', case=page.case, parent=page)(class_='footer') page.div(class_='container') # write user/time for analysis if link is None: version = get_versions()['version'] commit = get_versions()['full-revisionid'] url = 'https://github.com/gwdetchar/gwdetchar/tree/{}'.format(commit) link = markup.oneliner.a('View gwdetchar-{} on GitHub'.format(version), href=url, target='_blank') if issues is None: report = 'https://github.com/gwdetchar/gwdetchar/issues' issues = markup.oneliner.a('Report an issue', href=report, target='_blank') page.div(class_='row') page.div(class_='col-md-12') now = datetime.datetime.now() tz = reference.LocalTimezone().tzname(now) date = now.strftime('%H:%M {} on %d %B %Y'.format(tz)) page.p('This page was created by {user} at {date}.'.format( user=getuser(), date=date)) page.p('{link} | {issues}'.format(link=link, issues=issues)) # link to 'about' if about is not None: page.a('How was this page generated?', href=about) # extra content if isinstance(content, markup.page): page.add(str(content)) elif content is not None: page.p(str(content)) page.div.close() # col-md-12 page.div.close() # row page.div.close() # container markup.element('footer', case=page.case, parent=page).close() return page()
def write_param(param, value): """Format a parameter value with HTML """ page = markup.page() page.p() page.strong('%s: ' % param) page.add(str(value)) page.p.close() return page()
def afterword(self, content): if isinstance(content, markup.page) or content is None: self._post = content else: self._post = markup.page() if not str(content).startswith('<'): self._post.p(str(content)) else: self._post.add(str(content))
def foreword(self, content): if isinstance(content, markup.page) or content is None: self._pre = content else: self._pre = markup.page() if not str(content).startswith('<'): self._pre.p(str(content)) else: self._pre.add(str(content))
def about_this_page(config, packagelist=True): """Write a blurb documenting how a page was generated, including the command-line arguments and configuration files used Parameters ---------- config : `str`, `list`, optional the absolute path(s) to one or a number of INI files used in this process packagelist : `bool`, optional boolean switch to include (`True`) or exclude (`False`) a comprehensive list of system packages Returns ------- page : :class:`~MarkupPy.markup.page` the HTML page to be inserted into the #main <div>. """ page = markup.page() page.div(class_='row') page.div(class_='col-md-12') page.h2('On the command-line') page.add(get_command_line()) # render config file(s) page.h2('Configuration files') page.p('The following INI-format configuration file(s) were passed ' 'on the comand-line and are reproduced here in full:') if isinstance(config, str): with open(config, 'r') as fobj: contents = fobj.read() page.add(render_code(contents, 'ini')) elif isinstance(config, list): page.div(class_='panel-group', id="accordion") for i, cpfile in enumerate(config): page.div(class_='panel panel-default') page.a(href='#file%d' % i, **{'data-toggle': 'collapse', 'data-parent': '#accordion'}) page.div(class_='panel-heading') page.h4(os.path.basename(cpfile), class_='panel-title') page.div.close() page.a.close() page.div(id_='file%d' % i, class_='panel-collapse collapse') page.div(class_='panel-body') with open(cpfile, 'r') as fobj: contents = fobj.read() page.add(render_code(contents, 'ini')) page.div.close() page.div.close() page.div.close() page.div.close() # render package list if packagelist: page.add(package_table()) page.div.close() page.div.close() return page()
def calendar(date, tag='a', class_='navbar-brand dropdown-toggle', id_='calendar', dateformat=None, mode=None): """Construct a bootstrap-datepicker calendar. Parameters ---------- date : :class:`datetime.datetime`, :class:`datetime.date` active date for the calendar tag : `str` type of enclosing HTML tag, default: ``<a>`` Returns ------- calendar : `str` a onliner string of HTML containing the calendar text and a triggering dropdown """ mode = get_mode(mode) if dateformat is None: if mode == Mode.day: dateformat = '%B %d %Y' elif mode == Mode.week: dateformat = 'Week of %B %d %Y' elif mode == Mode.month: dateformat = '%B %Y' elif mode == Mode.year: dateformat = '%Y' else: raise ValueError("Cannot generate calendar for Mode %s" % mode) datestring = date.strftime(dateformat).replace(' 0', ' ') data_date = date.strftime('%d-%m-%Y') page = markup.page() page.a('«', class_='navbar-brand step-back', title='Step back', onclick='stepDate(-1)') page.a(id_=id_, class_=class_, title='Show/hide calendar', **{ 'data-date': data_date, 'data-date-format': 'dd-mm-yyyy', 'data-viewmode': '%ss' % mode.name }) page.add(datestring) page.b('', class_='caret') page.a.close() page.a('»', class_='navbar-brand step-forward', title='Step forwards', onclick='stepDate(1)') return page
def html_content(self, content): page = markup.page() if self.foreword: page.add(str(self.foreword)) if content: page.add(str(content)) page.add(str(self.scaffold_plots())) if self.afterword: page.add(str(self.afterword)) return Tab.html_content(str(page))
def get_brand(ifo, name, gps, about=None): """Return a brand for navigation bar formatting Parameters ---------- ifo : `str` interferometer prefix for color-coding, e.g. `'L1'` name : `str` name of the analysis, e.g. `'Scattering'` gps : `float` GPS second of the analysis about : `str`, optional relative path to the `about` page for this analysis, default: None Returns ------- brand : `~MarkupPy.markup.page` the navbar brand `page` object class_ : `str` object class of the navbar """ page = markup.page() page.div(ifo, class_='navbar-brand') page.div(name, class_='navbar-brand') page.div(class_='btn-group pull-right ifo-links') page.a(class_='navbar-brand dropdown-toggle', href='#', **{'data-toggle': 'dropdown'}) page.add('Links') page.b('', class_='caret') page.a.close() page.ul(class_='dropdown-menu') if about is not None: page.li('Internal', class_='dropdown-header') page.li() page.a('About this page', href=about) page.li.close() page.li('', class_='divider') page.li('External', class_='dropdown-header') for name, url in OBSERVATORY_MAP[ifo]['links'].items(): if 'Summary' in name: day = from_gps(gps).strftime(r"%Y%m%d") url = '/'.join([url, day]) page.li() page.a(name, href=url, target='_blank') page.li.close() page.ul.close() page.div.close() # btn-group pull-right class_ = 'navbar navbar-fixed-top navbar-{}'.format(ifo.lower()) return (page(), class_)
def package_table( h2="Environment", class_="table table-hover table-condensed table-responsive", caption="Table of packages installed in the production environment", ): """Write a table listing packages installed in the current environment Parameters ---------- h2 : `str`, `None`, optional the header for the HTML section caption : `str`, `None`, optional the `<caption>` for the package table Returns ------- html : `str` an HTML table """ # get package list and inspect columns pkgs = package_list() if "build_string" in pkgs[0]: # conda list cols = ("name", "version", "channel", "build_string") else: # pip list installed cols = ("name", "version") # create page and write <table> page = markup.page(separator="") if h2 is not None: page.h2(h2) page.table(class_=class_) if caption is not None: page.caption(caption) page.thead() page.tr() for head in cols: page.th(head.title(), scope="col") page.tr.close() page.thead.close() page.tbody() for pkg in sorted(pkgs, key=itemgetter("name")): page.tr() for col in cols: page.td(pkg[col.lower()]) page.tr.close() page.tbody.close() page.table.close() return page()
def fancybox_img(img, linkparams=dict(), **params): """Return the markup to embed an <img> in HTML Parameters ---------- img : `FancyPlot` a `FancyPlot` object containing the path of the image to embed and its caption to be displayed linkparams : `dict` the HTML attributes for the ``<a>`` tag **params the HTML attributes for the ``<img>`` tag Returns ------- page : `~MarkupPy.markup.page` the markup object containing fancyplot HTML """ page = markup.page() aparams = { 'title': img.caption, 'class_': 'fancybox', 'target': '_blank', 'data-fancybox-group': 'images', } aparams.update(linkparams) img = str(img) substrings = os.path.basename(img).split('-') channel = '%s-%s' % tuple(substrings[:2]) duration = substrings[-1].split('.')[0] page.a(href=img, id_='a_%s_%s' % (channel, duration), **aparams) imgparams = { 'alt': os.path.basename(img), 'class_': 'img-responsive', } if img.endswith('.svg') and os.path.isfile(img.replace('.svg', '.png')): imgparams['src'] = img.replace('.svg', '.png') else: imgparams['src'] = img imgparams.update(params) page.img(id_='img_%s_%s' % (channel, duration), **imgparams) page.a.close() return page()
def write_about_page(configfile): """Write a page explaining how an hveto analysis was completed Parameters ---------- ifo : `str` the prefix of the interferometer used in this analysis start : `int` the GPS start time of the analysis end : `int` the GPS end time of the analysis configfile : `str` the path of the configuration file to embed outdir : `str`, optional the output directory for the HTML Returns ------- index : `str` the path of the HTML written for this analysis """ # configure syntax highlighting blexer = get_lexer_by_name('bash', stripall=True) ilexer = get_lexer_by_name('ini', stripall=True) formatter = HtmlFormatter(noclasses=True) # set up page page = markup.page() # command line page.h2('On the command line') page.p('This page was generated with the command line call shown below.') commandline = highlight(' '.join(sys.argv), blexer, formatter) page.add(commandline) # configuration file page.h2('Configuration') with open(configfile, 'r') as fobj: inifile = fobj.read() contents = highlight(inifile, ilexer, formatter) page.add(contents) # runtime environment page.add(gwhtml.package_table()) return page
def html_content(content): """Build the #main div for this tab. Parameters ---------- content : `str`, `~MarkupPy.markup.page` HTML content to be wrapped Returns ------- #main : `~MarkupPy.markup.page` A new `page` with the input content wrapped as """ page = markup.page() page.div(id_='main') page.div(str(content), id_='content') page.div.close() return page
def write_footer(about=None, date=None, class_=False, linkstyle='color:#000;'): """Write a <footer> for a bootstrap page Parameters ---------- about : `str`, optional path of about page to link date : `datetime.datetime`, optional the datetime representing when this analysis was generated, defaults to `~datetime.datetime.now` Returns ------- page : `~MarkupPy.markup.page` the markup object containing the footer HTML """ page = markup.page() if class_: page.twotags.append('footer') markup.element('footer', case=page.case, parent=page)(class_='footer') page.div(class_='container') # write user/time for analysis if date is None: date = datetime.datetime.now().replace(second=0, microsecond=0) version = get_versions()['version'] commit = get_versions()['full-revisionid'] url = 'https://github.com/gwdetchar/gwdetchar/tree/{}'.format(commit) link = markup.oneliner.a('gwdetchar version {}'.format(version), href=url, target='_blank', style=linkstyle) page.div(class_='row') page.div(class_='col-md-12') page.p('These results were obtained using {link} by {user} at ' '{date}.'.format(link=link, user=getuser(), date=date)) # link to 'about' if about is not None: page.a('How was this page generated?', href=about, style=linkstyle) page.div.close() # col-md-12 page.div.close() # row page.div.close() # container if class_: markup.element('footer', case=page.case, parent=page).close() return page()
def write_flag_html(flag, span=None, id=0, parent='accordion', context='warning', title=None, plotdir=None, plot_func=plot_segments, **kwargs): """Write HTML for data quality flags """ page = markup.page() page.div(class_='panel panel-%s' % context) page.div(class_='panel-heading') if title is None: title = flag.name page.a(title, class_="panel-title", href='#flag%s' % id, **{'data-toggle': 'collapse', 'data-parent': '#%s' % parent}) page.div.close() page.div(id_='flag%s' % id, class_='panel-collapse collapse') page.div(class_='panel-body') # render segment plot if plotdir is not None and plot_func is not None: flagr = flag.name.replace('-', '_').replace(':', '-', 1) png = os.path.join( plotdir, '%s-%d-%d.png' % (flagr, span[0], abs(span))) plot = plot_func(flag, span, **kwargs) plot.save(png) plot.close() # set up fancybox img = FancyPlot( img=png, caption='Known (small) and active (large) analysis ' 'segments for {}'.format(title)) page.add(fancybox_img(img)) # write segments segs = StringIO() try: flag.active.write(segs, format='segwizard', coltype=type(flag.active[0][0])) except IndexError: page.p("No segments were found.") else: page.pre(segs.getvalue()) page.div.close() page.div.close() page.div.close() return page()
def html_navbar(self, brand=None, tabs=list(), ifo=None, ifomap=dict(), **kwargs): """Build the navigation bar for this tab. Parameters ---------- brand : `str`, `~MarkupPy.markup.page` content to place inside `<div class="navbar-brand"></div>` tabs : `list`, optional list of parent tabs (each with a list of children) to include in the navigation bar. ifo : `str`, optional prefix for this IFO. ifomap : `dict`, optional `dict` of (ifo, {base url}) pairs to map to summary pages for other IFOs. **kwargs other keyword arguments to pass to :meth:`gwsumm.html.navbar` Returns ------- page : `~MarkupPy.markup.page` a markup page containing the navigation bar. """ class_ = 'navbar navbar-fixed-top' # build interferometer cross-links if ifo is not None: brand_ = html.base_map_dropdown(ifo, id_='ifos', bases=ifomap) class_ += ' navbar-%s' % ifo.lower() else: brand_ = markup.page() # build HTML brand if brand: brand_.add(str(brand)) # combine and return return gwhtml.navbar(self._html_navbar_links(tabs), class_=class_, brand=brand_, **kwargs)
def write_state_html(self, state, pre=None, post=None, plots=True): """Write the frame HTML for the specific state of this tab Parameters ---------- state : `~gwsumm.state.SummaryState` `SummaryState` over which to generate inner HTML """ # build page page = markup.page() if pre: page.add(str(pre)) if plots: page.add(str(self.scaffold_plots(state=state))) if post: page.add(str(post)) # write to file idx = self.states.index(state) with open(self.frames[idx], 'w') as fobj: fobj.write(str(page)) return self.frames[idx]