def getDescriptionPills(statistics): statistics = np.round(statistics, 1) statisticstable = table(cls='table') table_header_row = tr() table_header_row.appendChild(th('Measurements count')) table_header_row.appendChild(th('Mean error')) table_header_row.appendChild(th('Standard Error dev')) table_header_row.appendChild(th('Min error measured')) table_header_row.appendChild(th('First quartile (25%)')) table_header_row.appendChild(th('Median (50%)')) table_header_row.appendChild(th('Third quartile (75%)')) table_header_row.appendChild(th('Max error measured')) table_row = tr() table_row.appendChild(td(str(statistics[0]))) table_row.appendChild(td(str(statistics[1]))) table_row.appendChild(td(str(statistics[2]))) table_row.appendChild(td(str(statistics[3]))) table_row.appendChild(td(str(statistics[4]))) table_row.appendChild(td(str(statistics[5]))) table_row.appendChild(td(str(statistics[6]))) table_row.appendChild(td(str(statistics[7]))) statisticstable.appendChild(thead(table_header_row)) statisticstable.appendChild(tbody(table_row)) return statisticstable
def status_class(octiron: Octiron, iri: URIRef): """Visualize all available status values as a table.""" choices = octiron.query(''' SELECT ?status ?label ?symbol ?defined_by_iri ?defined_by_url ?defined_by_label WHERE { ?status a adr:Status . GRAPH ?defined_by_iri { ?status rdfs:label ?label . OPTIONAL { ?status octa:symbol ?symbol . } } OPTIONAL { ?defined_by_iri octa:url ?defined_by_url . } OPTIONAL { ?defined_by_iri rdfs:label ?defined_by_label . } } ORDER BY ?label ''') rows = map(build_table_row, choices) return table(thead(tr( th('Code'), th('Label'), th('Defined By'), )), tbody(*rows))
def _create_table(self, rows): columns = [] for row in rows: for column in row.keys(): if column in columns: continue columns.append(column) # Create table table = tags.table() thead = tags.thead() tr = tags.tr() for column in columns: tr += tags.th(raw(column)) thead += tr tbody = tags.tbody() for row in rows: tr = tags.tr() for column in columns: tr += tags.td(row.get(column, '')) tbody += tr table += thead table += tbody return table
def render(self): """Print unique values for a column.""" rows: List[Row] = self.query( query_text=self.legend_query, column=self.iri, ) table_rows = [ tr( td( raw( render( node=row['prov_value'], octiron=self.octiron, environments=[ TABLE.td, IOLANTA.html, ], ) if row['prov_value'] is not None else '', ), ), td(*self.render_comment(row)), td(row['count']), ) for row in rows ] return table( thead( tr( # These are hard coded, and I cannot change that. See the # docstring for details. th('Value'), th('Description'), th('Count'), ), ), tbody(*table_rows), )
def mount_discrepancy_table(contest: str, contest_disagreed_df: pd.DataFrame, precinct_marks_df: pd.DataFrame) -> table: contest_marks_df = precinct_marks_df.loc[precinct_marks_df['contest'] == contest] overvotes = contest_marks_df['overvotes'].sum() undervotes = contest_marks_df['undervotes'].sum() options = [ o for o in contest_marks_df['option'].unique().tolist() if not o.startswith('#contest vote_for') ] with table(cls='table table-striped'): with thead(): with tr(): th('Candidate or Issue', scope="col") th('Audit System Adjudicated Votes', scope="col") th('Audit Indeterminate Votes', scope="col") th('Canvassing Board Adjustments', scope="col") th('Audit Total Votes', scope="col") th('Certified Results Total', scope="col") th('Difference', scope="col") with tbody(): for option in options: mount_option_row(option, contest_disagreed_df, contest_marks_df) with tr(): td('Number of overvotes') td(overvotes, colspan=6) with tr(): td('Number of undervotes') td(undervotes, colspan=6)
def build_discrepancy_parent_report(discrepancy_reports): version = utils.show_version() doc = dominate.document(title='Audit Engine version: ' + version) report_head(doc) discrepancy_reports.sort(key=itemgetter('discrepancy', 'ballots'), reverse=True) with doc: with div(cls='container'): report_headline(version) with table(cls='table table-striped'): with thead(): with tr(): th('#', scope="col") th('Precinct', scope="col") th('Ballots total', scope="col") th('Discrepancy', scope="col") th('Report', scope="col") with tbody(): for index, report in enumerate(discrepancy_reports): with tr(): report_abs_path = os.path.abspath( report.get('path')) th(index + 1) td(report.get('precinct')) td(report.get('ballots')) td(f"{report.get('discrepancy')}%") td( a(i(cls='far fa-file-alt'), href=report_abs_path, targer='_blank')) return doc
def build_header(l_cols): html_head = thead() with html_head: with tr(): for c in l_cols: th(c if isinstance(c, (unicode, str)) else str(c)) return html_head
def user_summary_for(rtype, storages, output_path: Path): ustats = {} def reg(user, query, stats): if user not in ustats: ustats[user] = {} ustats[user][query] = stats with ProcessPoolExecutor() as pp: digests = pp.map(get_digest, [s.path for s in storages]) for s, digest in zip(storages, digests): everything = flatten([ch for ch in digest.changes.values()]) for user, items in group_by_key(everything, key=lambda x: x.user).items(): reg(user, s.name, len(items)) now = datetime.now() doc = dominate.document( title= f'axol tags summary for {[s.name for s in storages]}, rendered at {fdate(now)}' ) with doc.head: T.style(STYLE) raw_script(JS) # TODO necessary? # TODO FIXME can't inline due to some utf shit sortable_js = Path(__file__).absolute().parent / 'js' / 'sorttable.js' T.script(src=str(sortable_js)) ft = FormatTrait.for_(rtype) with doc.body: with T.table(cls='sortable'): emitted_head = False for user, stats in sorted(ustats.items(), key=lambda x: (-len(x[1]), x)): if not emitted_head: with T.thead(): T.td('user') for q, _ in stats.items(): T.td(q) emitted_head = True with T.tr(): T.td(ft.user_link(user)) for q, st in stats.items(): with T.td(sorttable_customkey=str(st)): # TODO I guess unclear which tag to choose though. T.a( q, href=f'summary/{q}.html' ) # TODO link to source in index? or on pinboard maybe # TODO also project onto user's tags straight away T.sup( str(st) if st < 5 else T.b( T.font(str(st), color='red'))) # TODO css output_path.write_text(str(doc)) logger.info('Dumped user summary to %s', output_path)
def make_table_header(): h = thead() with h: r = tr() r.add(th('NUMBER')) r.add(th('TITLE')) r.add(th('ASSIGNEES')) r.add(th('PRIORITY')) r.add(th('LAST COMMENT'))
def __init__(self, *args, **kwargs): super().__init__(*args, id=f"{self.table_id}", style="width: 100%;") kwargs.setdefault('order', [[0, "desc"]]) kwargs.setdefault('select', {"items": "row"}) self.head = self.add(tags.thead()) self.body = self.add(tags.tbody()) #self.dtargs = 'order:[[0,"desc"]], select:{"items": "row"}, ' \ self.dtargs = ",".join([f' {x}: {y}' for x, y in kwargs.items()]) self.on_ready_scriptage = f"var {self.table_id} = $('#{self.table_id}').DataTable({{{self.dtargs}}});"
def render(self) -> table: """Render the table.""" columns = list_columns( iri=self.uriref, octiron=self.octiron, ) ordering = get_ordering( iri=self.uriref, octiron=self.octiron, ) headers = construct_headers( octiron=self.octiron, table_iri=self.uriref, columns=columns, ) instances = select_instances( iri=self.uriref, octiron=self.octiron, ) rows = [ construct_row( instance=instance, columns=columns, octiron=self.octiron, ) for instance in instances ] rows = order_rows( rows=rows, ordering=ordering, ) rows = [ tr( *render_row( row=row, columns=columns, octiron=self.octiron, ), ) for row in rows ] return table( thead( tr(*headers), ), tbody(*rows), )
def _write_header(self): if not self.is_write_header: return tr_tag = tags.tr() for header in self.header_list: tr_tag += tags.th(header) thead_tag = tags.thead() thead_tag += tr_tag self._table_tag += thead_tag
def __get__(self, obj: Table, objtype: Any = None) -> html_tag: thead_ = thead(_class="bg-primary text-white") if obj.columns: tr_ = tr(_class="bg-dark text-white") for column in obj.columns: span_ = span(column, _title=column) class_ = "whitespace-nowrap py-2 resize-x truncate min-w-2" width = obj.column_width.get(column) style = "" if not width else f"width: {width}" th_ = th(span_, _class=class_, _style=style) tr_.add(th_) thead_.add(tr_) return thead_
def _write_header(self): if not self.is_write_header: return if typepy.is_empty_sequence(self.header_list): raise EmptyHeaderError("header_list is empty") tr_tag = tags.tr() for header in self.header_list: tr_tag += tags.th(MultiByteStrDecoder(header).unicode_str) thead_tag = tags.thead() thead_tag += tr_tag self._table_tag += thead_tag
def mtable(columns, data, tclass): t = table(cls=tclass, style="width: 100%; table-layout:fixed;") _tr = tr() for c, style in columns: _tr.add(th(c, style=style)) t.add(thead(_tr)) tb = tbody() for r in data: _tr = tr() for i, c in enumerate(r): _tr.add(td(c, style=columns[i][1])) tb.add(_tr) t.add(tb) return t
def _write_header(self): tags = _get_tags_module() if not self.is_write_header: return if typepy.is_empty_sequence(self.headers): raise EmptyHeaderError("headers is empty") tr_tag = tags.tr() for header in self.headers: tr_tag += tags.th(MultiByteStrDecoder(header).unicode_str) thead_tag = tags.thead() thead_tag += tr_tag self._table_tag += thead_tag
def create_table(table_rows, *content): html_table = table(cellspacing="0", cellpadding="5", width="100%", margin="0 auto", border="1", style="white-space:nowrap;") with html_table.add(thead()).add(tr()): for val in [ "name", "purchase_price", "purchase_level", "min_price", "min_level", "min_profit", "min_percent", "relevant_price", "relevant_level", "relevant_profit", "relevant_percent" ]: th(val) with html_table: tbody(table_rows) return html(body(table(tr(td(html_table, *content)))))
def _write_header(self) -> None: tags, raw = _get_tags_module() if not self.is_write_header: return if typepy.is_empty_sequence(self._table_headers): raise ValueError("headers is empty") tr_tag = tags.tr() for header in self._table_headers: tr_tag += tags.th(raw(MultiByteStrDecoder(header).unicode_str)) thead_tag = tags.thead() thead_tag += tr_tag self._table_tag += thead_tag
def get_key_value_metadata_html(self): """generates html for viewing key/vale extra metadata""" extra_metadata_div = div() if self.extra_metadata: extra_metadata_div = div(cls="col-sm-12 content-block") with extra_metadata_div: legend('Extended Metadata') with table(cls="hs-table table dataTable no-footer", style="width: 100%"): with thead(): with tr(cls="header-row"): th("Key") th("Value") with tbody(): for k, v in self.extra_metadata.iteritems(): with tr(data_key=k): td(k) td(v) return extra_metadata_div
def get_cmpcvr_doc(cmpcvr_df: pd.DataFrame) -> dominate.document: version = utils.show_version() doc = dominate.document(title='Audit Engine version: ' + version) with doc.head: link( rel='stylesheet', href= 'https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css', integrity= "sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T", crossorigin="anonymous", ) script( src="https://code.jquery.com/jquery-3.4.1.slim.min.js", integrity= "sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n", crossorigin="anonymous") script( src= "https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js", integrity= "sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6", crossorigin="anonymous") with doc: with div(cls='container'): with div(cls='jumbotron'): h1('Audit Engine: {version} - vote records summary'.format( version=version)) build_time = datetime.datetime.now(datetime.timezone.utc) p(f'Summary built at: {build_time.strftime("%Y-%m-%d %H:%M:%S")}', cls='lead') get_summary_table(cmpcvr_df) with table(cls='table table-hover'): with thead(): with tr(): th('#', scope="col") th('Ballot ID', scope="col") th('Style', scope="col") table_body = tbody() table_body += mount_ballots_to_table(cmpcvr_df) return doc
def grid_table(data: Grid, rows: List[str], columns: List[str]): assert data.dimensions == 2 assert data.size(0) == len(rows) and data.size(1) == len(columns) with table() as element: with thead(): with tr(): th() [th(table_cell(column)) for column in columns] with tbody(): for i, row in enumerate(rows): with tr(): th(table_cell(row)) for value in data.row(i): if isinstance(value, tuple): if len(value) == 1: value = value[0] insert_cell(value, None) return element
def table_importer(): """Generate the new importer table.""" matrix = MANAGERS.matrix() with tags.table() as table: with tags.thead(): tags.th('Password Manager', align="center") tags.th('Formats', align="center") tags.th('How to export Data', align="center") tags.th('Command line', align="center") with tags.tbody(): for name in sorted(matrix): size = len(matrix[name]) for idx, pm in enumerate(matrix[name]): with tags.tr(): mm = ManagerMeta(pm, mode='html') if idx == 0: tags.td(tags.a(name, href=mm.url), rowspan=size, align="center", __pretty=False) mm.genrow() return "\n%s\n" % table.render()
def create_market_mission_table(missions, offers): html_table = table(cellspacing="0", cellpadding="5", width="30%", margin="0 auto", border="1", style="white-space:nowrap;") with html_table.add(thead()).add(tr()): for val in ["mission", "value"]: th(val) with html_table: if not offers: name_val = missions[0] if missions else "N/A" tbody(tr(td(name_val), td("N/A"))) else: for mission in missions: try: offer_price = offers[mission.name].get_min_price() except Exception as exception: logging.error("Failed to tabulate %s", mission.name) logging.error(str(exception)) offer_price = "N/A" tbody(tr(td(mission.name), td(offer_price))) return html_table
def futurize_code(args=None): """Main program. Args: fixer_pkg: the name of a package where the fixers are located. args: optional; a list of command line arguments. If omitted, sys.argv[1:] is used. Returns a suggested exit status (0, 1, 2). """ # Set up option parser parser = optparse.OptionParser(usage="futurize [options] file|dir ...") parser.add_option("-V", "--version", action="store_true", help="Report the version number of futurize") parser.add_option("-a", "--all-imports", action="store_true", help="Add all __future__ and future imports to each module") parser.add_option("-1", "--stage1", action="store_true", help="Modernize Python 2 code only; no compatibility with Python 3 (or dependency on ``future``)") parser.add_option("-2", "--stage2", action="store_true", help="Take modernized (stage1) code and add a dependency on ``future`` to provide Py3 compatibility.") parser.add_option("-0", "--both-stages", action="store_true", help="Apply both stages 1 and 2") parser.add_option("-u", "--unicode-literals", action="store_true", help="Add ``from __future__ import unicode_literals`` to implicitly convert all unadorned string literals '' into unicode strings") parser.add_option("-f", "--fix", action="append", default=[], help="Each FIX specifies a transformation; default: all.\nEither use '-f division -f metaclass' etc. or use the fully-qualified module name: '-f lib2to3.fixes.fix_types -f libfuturize.fixes.fix_unicode_keep_u'") parser.add_option("-j", "--processes", action="store", default=1, type="int", help="Run 2to3 concurrently") parser.add_option("-x", "--nofix", action="append", default=[], help="Prevent a fixer from being run.") parser.add_option("-l", "--list-fixes", action="store_true", help="List available transformations") parser.add_option("-p", "--print-function", action="store_true", help="Modify the grammar so that print() is a function") parser.add_option("-v", "--verbose", action="store_true", help="More verbose logging") parser.add_option("--no-diffs", action="store_true", help="Don't show diffs of the refactoring") parser.add_option("-w", "--write", action="store_true", help="Write back modified files") parser.add_option("-n", "--nobackups", action="store_true", default=False, help="Don't write backups for modified files.") parser.add_option("-o", "--output-dir", action="store", type="str", default="", help="Put output files in this directory " "instead of overwriting the input files. Requires -n. " "For Python >= 2.7 only.") parser.add_option("-W", "--write-unchanged-files", action="store_true", help="Also write files even if no changes were required" " (useful with --output-dir); implies -w.") parser.add_option("--add-suffix", action="store", type="str", default="", help="Append this string to all output filenames." " Requires -n if non-empty. For Python >= 2.7 only." "ex: --add-suffix='3' will generate .py3 files.") # Parse command line arguments flags = {} refactor_stdin = False options, args = parser.parse_args(args) if options.write_unchanged_files: flags["write_unchanged_files"] = True if not options.write: warn("--write-unchanged-files/-W implies -w.") options.write = True # If we allowed these, the original files would be renamed to backup names # but not replaced. if options.output_dir and not options.nobackups: parser.error("Can't use --output-dir/-o without -n.") if options.add_suffix and not options.nobackups: parser.error("Can't use --add-suffix without -n.") if not options.write and options.no_diffs: warn("not writing files and not printing diffs; that's not very useful") if not options.write and options.nobackups: parser.error("Can't use -n without -w") if "-" in args: refactor_stdin = True if options.write: print("Can't write to stdin.", file=sys.stderr) return 2 # Is this ever necessary? if options.print_function: flags["print_function"] = True # Set up logging handler level = logging.DEBUG if options.verbose else logging.INFO logging.basicConfig(format='%(name)s: %(message)s', level=level) logger = logging.getLogger('libfuturize.main') if options.stage1 or options.stage2: assert options.both_stages is None options.both_stages = False else: options.both_stages = True avail_fixes = set() if options.stage1 or options.both_stages: avail_fixes.update(lib2to3_fix_names_stage1) avail_fixes.update(libfuturize_fix_names_stage1) if options.stage2 or options.both_stages: avail_fixes.update(lib2to3_fix_names_stage2) avail_fixes.update(libfuturize_fix_names_stage2) if options.unicode_literals: avail_fixes.add('libfuturize.fixes.fix_unicode_literals_import') if options.version: print(__version__) return 0 if options.list_fixes: print("Available transformations for the -f/--fix option:") # for fixname in sorted(refactor.get_all_fix_names(fixer_pkg)): for fixname in sorted(avail_fixes): print(fixname) if not args: return 0 if not args: print("At least one file or directory argument required.", file=sys.stderr) print("Use --help to show usage.", file=sys.stderr) return 2 unwanted_fixes = set() for fix in options.nofix: if ".fix_" in fix: unwanted_fixes.add(fix) else: # Infer the full module name for the fixer. # First ensure that no names clash (e.g. # lib2to3.fixes.fix_blah and libfuturize.fixes.fix_blah): found = [f for f in avail_fixes if f.endswith('fix_{0}'.format(fix))] if len(found) > 1: print("Ambiguous fixer name. Choose a fully qualified " "module name instead from these:\n" + "\n".join(" " + myf for myf in found), file=sys.stderr) return 2 elif len(found) == 0: print("Unknown fixer. Use --list-fixes or -l for a list.", file=sys.stderr) return 2 unwanted_fixes.add(found[0]) extra_fixes = set() if options.all_imports: if options.stage1: prefix = 'libfuturize.fixes.' extra_fixes.add(prefix + 'fix_add__future__imports_except_unicode_literals') else: # In case the user hasn't run stage1 for some reason: prefix = 'libpasteurize.fixes.' extra_fixes.add(prefix + 'fix_add_all__future__imports') extra_fixes.add(prefix + 'fix_add_future_standard_library_import') extra_fixes.add(prefix + 'fix_add_all_future_builtins') explicit = set() if options.fix: all_present = False for fix in options.fix: if fix == 'all': all_present = True else: if ".fix_" in fix: explicit.add(fix) else: # Infer the full module name for the fixer. # First ensure that no names clash (e.g. # lib2to3.fixes.fix_blah and libfuturize.fixes.fix_blah): found = [f for f in avail_fixes if f.endswith('fix_{0}'.format(fix))] if len(found) > 1: print("Ambiguous fixer name. Choose a fully qualified " "module name instead from these:\n" + "\n".join(" " + myf for myf in found), file=sys.stderr) return 2 elif len(found) == 0: print("Unknown fixer. Use --list-fixes or -l for a list.", file=sys.stderr) return 2 explicit.add(found[0]) if len(explicit & unwanted_fixes) > 0: print("Conflicting usage: the following fixers have been " "simultaneously requested and disallowed:\n" + "\n".join(" " + myf for myf in (explicit & unwanted_fixes)), file=sys.stderr) return 2 requested = avail_fixes.union(explicit) if all_present else explicit else: requested = avail_fixes.union(explicit) fixer_names = (requested | extra_fixes) - unwanted_fixes input_base_dir = os.path.commonprefix(args) if (input_base_dir and not input_base_dir.endswith(os.sep) and not os.path.isdir(input_base_dir)): # One or more similar names were passed, their directory is the base. # os.path.commonprefix() is ignorant of path elements, this corrects # for that weird API. input_base_dir = os.path.dirname(input_base_dir) # if options.output_dir: # input_base_dir = input_base_dir.rstrip(os.sep) # logger.info('Output in %r will mirror the input directory %r layout.', # options.output_dir, input_base_dir) # Initialize the refactoring tool if future.utils.PY26: extra_kwargs = {} else: extra_kwargs = { 'append_suffix': options.add_suffix, 'output_dir': options.output_dir, 'input_base_dir': input_base_dir, } # Remove results directory. if os.path.isdir(RESULTS_DIR): shutil.rmtree(RESULTS_DIR) os.mkdir(RESULTS_DIR) if os.path.isdir(DIFF_DIR): shutil.rmtree(DIFF_DIR) os.mkdir(DIFF_DIR) # We override their RefactoringTool with `FileRefactoringTool` rt = FileRefactoringTool( sorted(fixer_names), flags, sorted(explicit), options.nobackups, not options.no_diffs, **extra_kwargs) # Refactor all files and directories passed as arguments if not rt.errors: if refactor_stdin: rt.refactor_stdin() else: try: rt.refactor(args, options.write, None, options.processes) except refactor.MultiprocessingUnsupported: assert options.processes > 1 print("Sorry, -j isn't supported on this platform.", file=sys.stderr) return 1 rt.summarize() # This is our own custom html reporting. table_body = tbody() remove_line_count_total = 0 with table_body: for file_name, file_summary in DiffSummary.list_all(): with tr(): td(a(file_name, href=file_summary.href)) td(file_summary.add_line_count, style="text-align:right") td(file_summary.remove_line_count, style="text-align:right") td(file_summary.percent_coverage, style="text-align:right") remove_line_count_total += file_summary.remove_line_count with document(title='2/3 Summary') as doc: h1('2/3 Summary', style='padding: 0 40px;') p('Total lines that need to be removed:', style='padding: 0 40px;').add(b(remove_line_count_total)) summary_table = table(width='100%', style="padding: 20px 40px; margin: 0 auto;") with summary_table.add(thead()): with tr(): th('File Name', style="text-align:left") th('Add Lines', style="text-align:right") th('Remove Lines', style="text-align:right") th('Coverage %', style="text-align:right") summary_table.add(table_body) with open('{results_dir}/summary.html'.format(results_dir=RESULTS_DIR), 'w+') as summary_file: summary_file.write(doc.render()) # Write a machine readable report that can be parsed later. json_report = { 'summary': { 'remove_line_count_total': remove_line_count_total }, 'files': [ { 'file_name': file_name, 'add_line_count': file_summary.add_line_count, 'remove_line_count': file_summary.remove_line_count, 'percent_coverage': file_summary.percent_coverage, } for file_name, file_summary in DiffSummary.list_all() ] } json.dump(json_report, open('{results_dir}/report.json'.format(results_dir=RESULTS_DIR), 'w+')) # Return error status (0 if rt.errors is zero) return int(bool(rt.errors))
def create_html_string(COUNTERS, BALLOTLISTS, DISAGREED_INFO_DICT): """Creates a HTML string for generating the summary file. Accesses the following: COUNTERS['ballots_processed'] COUNTERS['styles_detected'] COUNTERS['matched_ballots'] COUNTERS['non_matched_ballots'] COUNTERS['blank_ballots'] list of ballot OVERVOTED_BALLOTS list of ballot DISAGREED_BALLOTS accesses ballot pdf files per precinct and ballot_id DISAGREE_INFO_DICT is keyed by ballot_id which provides dict of contests providing error information f"{config_dict['RESOURCES_PATH']}{config_dict['DISAGREEMENTS_PATHFRAG']}{ballot.ballotdict['precinct']}/{ballot.ballotdict['ballot_id']}.pdf") list STYLES style.style_num style.number style.build_from_count files style_summary = glob.glob(f"{config_dict['RESOURCES_PATH']}{config_dict['STYLES_PATHFRAG']}{style.code}.html")[0] list VOTES_RESULTS (results for each contest) result_contest['contest_name'] result_contest['selections'] result_contest['vote_for'] result_contest['question'] result_contest['total_ballots'] result_contest['total_votes'] result_contest['undervote'] result_contest['overvote'] """ script_abs_path = os.path.abspath('assets/copy_to_clipboard.js') version = utils.show_version() doc = dominate.document(title='Audit Engine version: ' + version) with doc.head: link( rel='stylesheet', href= 'https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css', integrity= "sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T", crossorigin="anonymous", ) script(type='text/javascript', src=script_abs_path) with doc: with div(cls='container'): with div(cls='jumbotron'): h1('Audit Engine: {version} - vote records summary'.format( version=version)) build_time = datetime.datetime.now(datetime.timezone.utc) p(f'Summary built at: {build_time.strftime("%Y-%m-%d %H:%M:%S")}', cls='lead') with table(cls='table table-striped'): with tbody(): with tr(): th('Number of ballots processed') td(COUNTERS['ballots_processed']) with tr(): th('Number of different ballot types') td(COUNTERS['styles_detected']) with tr(): th('Number of ballots matching the CVR results') td(COUNTERS['matched_ballots']) with tr(): th('Number of ballots not matching the CVR results') td(COUNTERS['non_matched_ballots']) with tr(): th('Number of completely blank ballots') td(COUNTERS['blank_ballots']) with tr(): th('Number of overvotes') td(COUNTERS['overvoted_ballots']) with tr(): th('Number of disagreements') td(COUNTERS['disagreed_ballots']) with div(cls='my-4'): h2('Styles') with table(cls='table table-striped'): with thead(): with tr(): th('Style code', scope="col") th('Style number', scope="col") th('Based on number of ballots', scope="col") th('Built at', scope="col") with tbody(): for style in STYLES: with tr(): utc_time = datetime.datetime.utcfromtimestamp( style.timestamp) style_summary = glob.glob( f"{config_dict['RESOURCES_PATH']}{config_dict['STYLES_PATHFRAG']}{style.code}.html" )[0] td( a(style.style_num, href=os.path.realpath(style_summary), target="_blank")) td(style.number) td(style.build_from_count) td(f'{utc_time.strftime("%Y-%m-%d %H:%M:%S")}') # Tables with contests results: with div(cls='my-4'): h2('Contests results') for result_contest in VOTES_RESULTS: contest_name = result_contest['contest_name'] selections = result_contest['selections'] vote_for = result_contest['vote_for'] question = result_contest['question'] with div(cls='my-4'): h5(f'Contest results "{contest_name}" (vote for {vote_for}):' ) if question: h6(f'Question "{question}"') with table(cls='table table-striped'): with thead(): with tr(): th('#', scope="col") th('Candidate', scope="col") th('Votes', scope="col") th('%', scope="col") with tbody(): for index, candidate_name in enumerate( sort_option_names(selections.keys())): try: total_votes = result_contest['total_votes'] percent = round( (selections[candidate_name] / total_votes) * 100, 2) except ZeroDivisionError: percent = 0.0 with tr(): th(index + 1, scope="row") td(candidate_name) td(candidate_name) td(f'{percent}%') with table(cls='table table-striped'): with tbody(): with tr(): th('Total number of ballots') td(result_contest['total_ballots']) with tr(): th('Number of votes') td(result_contest['total_votes']) with tr(): th('Number of undervotes') td(result_contest['undervote']) with tr(): th('Number of overvotes') td(result_contest['overvote']) # Table with overvotes: with div(cls='my-4'): h2('Ballots with overvotes:') with table(cls='table table-striped'): with thead(): with tr(): th('#', scope="col") th('Precinct / Contest name', scope="col") th('Ballot file / Ballot and CVR status', scope="col") th('Overvotes / Contest validation status', scope="col") with tbody(): dirpath = DB.dirpath_from_dirname('overvotes') for index, ballot_id in enumerate( BALLOTLISTS['overvoted_ballots']): filepathlist = glob.glob( f"{dirpath}**/{ballot_id}i.pdf", recursive=True) if not filepathlist: continue filepath = filepathlist[0] with tr(): th(index + 1, scope="row") td('') with td(): ballot_image_filepath = os.path.abspath( filepath) a(ballot_id, href=ballot_image_filepath, target="_blank") td('') # overvotes_contests = list( # filter( # lambda x: (x.contest_ballot_status == STATUS_DICT['overvote']) or # (x.contest_cvr_status == STATUS_DICT['overvote']), ballot.ballotdict['contests'])) # for contest in overvotes_contests: # with tr(): # td() # td(contest.contest_name) # td(f"{contest.contest_ballot_status} / {contest.contest_cvr_status}") # td(contest.contest_validation if contest.contest_validation is not None else '') # Table with blank ballots: with div(cls='my-4'): h2('Blank Ballots:') with table(cls='table table-striped'): with thead(): with tr(): th('#', scope="col") th('Precinct / Contest name', scope="col") th('Ballot file / Ballot and CVR status', scope="col") th('Overvotes / Contest validation status', scope="col") with tbody(): dirpath = DB.dirpath_from_dirname('blank_ballots') for index, ballot_id in enumerate( BALLOTLISTS['blank_ballots']): filepathlist = glob.glob(f"f{dirpath}{ballot_id}i.pdf", recursive=True) if not filepathlist: continue filepath = filepathlist[0] with tr(): th(index + 1, scope="row") td('') with td(): ballot_image_filepath = os.path.abspath( filepath) a(ballot_id, href=ballot_image_filepath, target="_blank") td('') # Table with disagreements: with div(cls='my-4'): h2('Ballots with disagreements:') with table(cls='table table-striped'): with thead(): with tr(): th('#', scope="col") th('Ballot file', scope="col") th('Disagreement Details', scope="col") with tbody(): dirpath = DB.dirpath_from_dirname('disagreements') for index, ballot_id in enumerate( BALLOTLISTS['disagreed_ballots']): filepathlist = glob.glob( f"{dirpath}**/{ballot_id}i.pdf", recursive=True) if not filepathlist: continue filepath = filepathlist[0] with tr(): th(index + 1, scope="row") with td(): ballot_image_filepath = os.path.abspath( filepath) a(ballot_id, href=ballot_image_filepath, target="_blank") td( raw(f"<pre>{DISAGREED_INFO_DICT[ballot_id]}</PRE>" )) return doc
def generate_html_document(trackers: List[Tracker], sequences: List[Sequence], results, storage: Storage): import io import dominate from dominate.tags import h1, h2, table, thead, tbody, tr, th, td, div, p, li, ol, span, style, link, script from dominate.util import raw order_classes = {1: "first", 2: "second", 3: "third"} def insert_figure(): buffer = io.StringIO() plt.savefig(buffer, format="SVG", bbox_inches='tight', transparent=True) raw(buffer.getvalue()) plt.close() def insert_cell(value, order): attrs = dict(data_sort_value=order, data_value=value) if order in order_classes: attrs["cls"] = order_classes[order] td(_format_value(value), **attrs) def add_style(name, linked=False): if linked: link(rel='stylesheet', href='file://' + os.path.join(os.path.dirname(__file__), name)) else: style(_read_resource(name)) def add_script(name, linked=False): if linked: script(type='text/javascript', src='file://' + os.path.join(os.path.dirname(__file__), name)) else: with script(type='text/javascript'): raw("//<![CDATA[\n" + _read_resource(name) + "\n//]]>") logger = logging.getLogger("vot") legend = Legend() table_header, table_data, table_order = _extract_measures_table(trackers, results) graphs = _extract_graphs(trackers ,results, legend) doc = dominate.document(title='VOT report') linked = check_debug() with doc.head: add_style("pure.css", linked) add_style("report.css", linked) add_script("jquery.js", linked) add_script("table.js", linked) add_script("report.js", linked) with doc: h1("VOT report") with ol(cls="metadata"): li('Toolkit version: ' + version) li('Created: ' + datetime.datetime.now().isoformat()) if len(table_header[2]) == 0: logger.debug("No measures found, skipping table") else: with table(cls="measures pure-table pure-table-horizontal pure-table-striped"): with thead(): with tr(): th() [th(c[0].identifier, colspan=c[1]) for c in _merge_repeats(table_header[0])] with tr(): th() [th(c[0].name, colspan=c[1]) for c in _merge_repeats(table_header[1])] with tr(): th("Trackers") [th(c.abbreviation, data_sort="int" if order else "") for c, order in zip(table_header[2], table_order)] with tbody(): for tracker, data in table_data.items(): with tr(): number = legend.number(tracker.identifier) with td(id="legend_%d" % number): legend.figure(tracker.identifier) insert_figure() span(tracker.label) for value, order in zip(data, table_order): insert_cell(value, order[tracker] if not order is None else None) for experiment, experiment_graphs in graphs.items(): if len(experiment_graphs) == 0: continue h2("Experiment {}".format(experiment.identifier), cls="experiment") with div(cls="graphs"): for title, graph in experiment_graphs: with graph, div(cls="graph"): p(title) insert_figure() with storage.write("report.html") as filehandle: filehandle.write(doc.render())
def get_extra_metadata_html_form(self): def get_add_keyvalue_button(): add_key_value_btn = a(cls="btn btn-success", type="button", data_toggle="modal", data_target="#add-keyvalue-filetype-modal", style="margin-bottom:20px;") with add_key_value_btn: with span(cls="glyphicon glyphicon-plus"): span("Add Key/Value", cls="button-label") return add_key_value_btn if self.extra_metadata: root_div_extra = div(cls="col-xs-12", id="filetype-extra-metadata") with root_div_extra: legend('Extended Metadata') get_add_keyvalue_button() with table(cls="hs-table table dataTable no-footer", style="width: 100%"): with thead(): with tr(cls="header-row"): th("Key") th("Value") th("Edit/Remove") with tbody(): counter = 0 for k, v in self.extra_metadata.iteritems(): counter += 1 with tr(data_key=k): td(k) td(v) with td(): span( data_toggle="modal", data_placement="auto", title="Edit", cls= "btn-edit-icon glyphicon glyphicon-pencil " "icon-blue table-icon", data_target= "#edit-keyvalue-filetype-modal" "-{}".format(counter)) span( data_toggle="modal", data_placement="auto", title="Remove", cls= "btn-remove-icon glyphicon glyphicon-trash " "btn-remove table-icon", data_target= "#delete-keyvalue-filetype-modal" "-{}".format(counter)) self._get_add_key_value_modal_form() self._get_edit_key_value_modal_forms() self._get_delete_key_value_modal_forms() return root_div_extra else: root_div_extra = div(id="filetype-extra-metadata", cls="col-xs-12 content-block") with root_div_extra: legend('Extended Metadata') get_add_keyvalue_button() self._get_add_key_value_modal_form() return root_div_extra
def generate_html_document(trackers: List[Tracker], sequences: List[Sequence], results, storage: Storage): def insert_figure(figure): buffer = io.StringIO() figure.save(buffer, "SVG") raw(buffer.getvalue()) def insert_mplfigure(figure): buffer = io.StringIO() figure.savefig(buffer, format="SVG", bbox_inches='tight', pad_inches=0.01, dpi=200) raw(buffer.getvalue()) def add_style(name, linked=False): if linked: link(rel='stylesheet', href='file://' + os.path.join(os.path.dirname(__file__), name)) else: style(read_resource(name)) def add_script(name, linked=False): if linked: script(type='text/javascript', src='file://' + os.path.join(os.path.dirname(__file__), name)) else: with script(type='text/javascript'): raw("//<![CDATA[\n" + read_resource(name) + "\n//]]>") logger = logging.getLogger("vot") table_header, table_data, table_order = extract_measures_table( trackers, results) plots = extract_plots(trackers, results) legend = StyleManager.default().legend(Tracker) doc = dominate.document(title='VOT report') linked = check_debug() with doc.head: add_style("pure.css", linked) add_style("report.css", linked) add_script("jquery.js", linked) add_script("table.js", linked) add_script("report.js", linked) with doc: h1("VOT report") with ol(cls="metadata"): li('Toolkit version: ' + toolkit_version()) li('Created: ' + datetime.datetime.now().isoformat()) if len(table_header[2]) == 0: logger.debug("No measures found, skipping table") else: with table( cls= "overview-table pure-table pure-table-horizontal pure-table-striped" ): with thead(): with tr(): th() [ th(c[0].identifier, colspan=c[1]) for c in merge_repeats(table_header[0]) ] with tr(): th() [ th(c[0].title, colspan=c[1]) for c in merge_repeats(table_header[1]) ] with tr(): th("Trackers") [ th(c.abbreviation, data_sort="int" if order else "") for c, order in zip(table_header[2], table_order) ] with tbody(): for tracker, data in table_data.items(): with tr(data_tracker=tracker.reference): with td(): insert_mplfigure(legend.figure(tracker)) span(tracker.label) for value, order in zip(data, table_order): insert_cell( value, order[tracker] if not order is None else None) for experiment, experiment_plots in plots.items(): if len(experiment_plots) == 0: continue h2("Experiment {}".format(experiment.identifier), cls="experiment") with div(cls="plots"): for title, plot in experiment_plots: with div(cls="plot"): p(title) insert_figure(plot) with storage.write("report.html") as filehandle: filehandle.write(doc.render())
def report_table(self, *args, **kwargs): """ Helps create tables :param tuple \*args: Rows of data as tuples. Ex ('data1', 'data2', ...) :param str \**kwargs: Kwargs to control title, header, etc. :param tuple header: Kwarg The header for the table. Accepts a tuple :param str title: Kwarg The title of the section :param bool section: Kwarg Set to false to append table to previous section :param str header_color: Kwarg Sets the color of the header. Defaults to dark :param bool tindex: Kwarg Sets an index column :param tuple alert: Kwarg Creats a dismissable alert box. Requires a tuple. First value is color and second value is message. :param dict modal: Create a modal. Is a dictionary. Valid keys are button, title and content :return: A table object :raises TypeError: Raises exception if not a tuple or all lenghts are not the same :raises NotValidTag: If not a valid bootstrap color :raises TableError: When there are issues creating a table Example showing how to change the default theme: >>> r = report.report_table(('data1', 'demo1'), ('data2', 'demo2'), >>> header=('header1', 'header2'), title='demo') """ if 'section' in kwargs: style = rng.CSSControl.sticky_section_css else: style = "padding-bottom:3; padding-top:40;" if 'header_color' in kwargs: header_color = kwargs.get('header_color') if header_color not in rng.HelperFunctions.valid_tags: raise rng.NotValidTag('Not a valid header color') else: header_color = 'dark' # creates optional header if 'header' in kwargs: table_header = kwargs.get('header') # Check to make sure it is args if not isinstance(args, tuple): raise TypeError('Not a tuple') # Saves length of first arg check_length = len(args[0]) # Run checks agains header if not isinstance(table_header, tuple): raise TypeError('Headers are not a tuple') elif len(table_header) != check_length: raise rng.TableError('Header not the same length as data') # starts building the table with tag.div(_class="jumbotron container context reportng-table-class", style=style) as c: # padding mods if 'title' in kwargs: tag.h1( kwargs.get('title'), id="%s" % rng.HelperFunctions.id_with_random(5, kwargs.get('title'))) # create dismissable alert box if 'alert' in kwargs: rng.HelperFunctions.make_alert(kwargs.get('alert')) with tag.div( _class="container", style="overflow-x:auto; max-height: 70%; overflow: auto;"): with tag.table( _class="table table-striped display nowrap table-hover", style="width: 90%") as tables: # Make table header if table_header: with tag.thead( _class="table-%s" % rng.HelperFunctions.color_to_tag(header_color) ).add(tag.tr()): if kwargs.get('tindex') == True: tag.th('Index') for h in range(len(table_header)): tag.th(table_header[h], scope='col') for r in range(len(args)): with tag.tr(): if kwargs.get('tindex') == True: tag.td(str(r + 1)) # Checks length of subsequent args with first arg if len(args[r]) != check_length: raise rng.TableError( 'Length of all tuples has to be the same') for t in range(len(args[r])): tag.td(args[r][t]) if 'modal' in kwargs: if isinstance(kwargs.get('modal'), dict): rng.HelperFunctions.make_modals( kwargs.get('title').replace(' ', ''), kwargs.get('modal')) return rng.HelperFunctions.convert_to_string(c)
def visualization_html(header, data, metrics): challenges = data.keys() # geometry_options = { # "margin": "1.5in", # "headheight": "20pt", # "headsep": "10pt", # "includeheadfoot": True # } # doc = Document(header, page_numbers=True, geometry_options=geometry_options) file_path = os.path.join(os.getcwd(), 'evaluation_results.html') if os.path.isfile(file_path): os.remove(file_path) doc1 = dominate.document(title='Tracking Evaluator') with doc1: with div(): attr(cls='body') h1('Evaluation Results') with div(): h2('Results table') tags.style(".calendar_table{width:880px;}") tags.style("body{font-family:Helvetica}") tags.style("h1{font-size:x-large}") tags.style("h2{font-size:large}") tags.style("table{border-collapse:collapse}") tags.style( "th{font-size:small;border:1px solid gray;padding:4px;background-color:#DDD}" ) tags.style( "td{font-size:small;text-align:center;border:1px solid gray;padding:4px}" ) with tags.table(): with tags.thead(): tags.th("Challenge", style="color:#ffffff;background-color:#6A75F2") tags.th("Tracker", style="color:#ffffff;background-color:#6A75F2") for m in metrics: tags.th(m, style="color:#ffffff;background-color:#6A75F2") with tags.tbody(): for c in challenges: with tags.tr(): #New row Challenges tags.td( c, style= "font-size:small;text-align:center;padding:4px" ) for t in trackers: if data[c][t]: with tags.tr(): #New row Data per tracker tags.td( ' ', style= "font-size:small;text-align:center;padding:4px" ) tags.td( t, style= "font-size:small;text-align:center;padding:4px" ) if 'Accuracy' in metrics: tags.td( data[c][t]['tracker_acc'], style= "font-size:small;text-align:center;padding:4px" ) if 'Robustness' in metrics: tags.td( data[c][t]['tracker_robust'], style= "font-size:small;text-align:center;padding:4px" ) if 'Precision(Center Location Error)' in metrics: tags.td( data[c][t]['tracker_precision'], style= "font-size:small;text-align:center;padding:4px" ) with div(): h2('Graphs') for graph in plot_list: tags.img(src=graph, style='max-width:700px;margin-top: 50px;') tags.br() if frame_list: for c in challenges: if frame_list[c]: for t in frame_list[c].keys(): with figure(): h3('Low Frames for tracker: %s' % t + ' challenge: %s' % c) for i in range(len(frame_list[c][t])): tags.img(src=frame_list[c][t][i][0], style="width:340px;margin-top: 50px") tags.i(frame_list[c][t][i][1]) f = open(file_path, 'w') f.write(doc1.render()) f.close()