matplotlib
160 строк · 5.0 Кб
1#!/usr/bin/env python
2#
3# This builds a html page of all images from the image comparison tests
4# and opens that page in the browser.
5#
6# $ python tools/visualize_tests.py
7#
8
9import argparse10import os11from collections import defaultdict12
13# Non-png image extensions
14NON_PNG_EXTENSIONS = ['pdf', 'svg', 'eps']15
16html_template = """<!DOCTYPE html>17<html lang="en"><head>
18<meta charset="utf-8">
19<title>Matplotlib test result visualization</title>
20<style media="screen">
21img{{
22width:100%;
23max-width:800px;
24}}
25</style>
26</head><body>
27{failed}
28{body}
29</body></html>
30"""
31
32subdir_template = """<h2>{subdir}</h2><table>33<thead><tr><th>name</th><th>actual</th><th>expected</th><th>diff</th></tr></thead>
34<tbody>
35{rows}
36</tbody>
37</table>
38"""
39
40failed_template = """<h2>Only Failed</h2><table>41<thead><tr><th>name</th><th>actual</th><th>expected</th><th>diff</th></tr></thead>
42<tbody>
43{rows}
44</tbody>
45</table>
46"""
47
48row_template = ('<tr>'49'<td>{0}{1}</td>'50'<td>{2}</td>'51'<td><a href="{3}"><img src="{3}"></a></td>'52'<td>{4}</td>'53'</tr>')54
55linked_image_template = '<a href="{0}"><img src="{0}"></a>'56
57
58def run(show_browser=True):59"""60Build a website for visual comparison
61"""
62image_dir = "result_images"63_subdirs = (name64for name in os.listdir(image_dir)65if os.path.isdir(os.path.join(image_dir, name)))66
67failed_rows = []68body_sections = []69for subdir in sorted(_subdirs):70if subdir == "test_compare_images":71# These are the images which test the image comparison functions.72continue73
74pictures = defaultdict(dict)75for file in os.listdir(os.path.join(image_dir, subdir)):76if os.path.isdir(os.path.join(image_dir, subdir, file)):77continue78fn, fext = os.path.splitext(file)79if fext != ".png":80continue81if "-failed-diff" in fn:82file_type = 'diff'83test_name = fn[:-len('-failed-diff')]84elif "-expected" in fn:85for ext in NON_PNG_EXTENSIONS:86if fn.endswith(f'_{ext}'):87display_extension = f'_{ext}'88extension = ext89fn = fn[:-len(display_extension)]90break91else:92display_extension = ''93extension = 'png'94file_type = 'expected'95test_name = fn[:-len('-expected')] + display_extension96else:97file_type = 'actual'98test_name = fn99# Always use / for URLs.100pictures[test_name][file_type] = '/'.join((subdir, file))101
102subdir_rows = []103for name, test in sorted(pictures.items()):104expected_image = test.get('expected', '')105actual_image = test.get('actual', '')106
107if 'diff' in test:108# A real failure in the image generation, resulting in109# different images.110status = " (failed)"111failed = f'<a href="{test["diff"]}">diff</a>'112current = linked_image_template.format(actual_image)113failed_rows.append(row_template.format(name, "", current,114expected_image, failed))115elif 'actual' not in test:116# A failure in the test, resulting in no current image117status = " (failed)"118failed = '--'119current = '(Failure in test, no image produced)'120failed_rows.append(row_template.format(name, "", current,121expected_image, failed))122else:123status = " (passed)"124failed = '--'125current = linked_image_template.format(actual_image)126
127subdir_rows.append(row_template.format(name, status, current,128expected_image, failed))129
130body_sections.append(131subdir_template.format(subdir=subdir, rows='\n'.join(subdir_rows)))132
133if failed_rows:134failed = failed_template.format(rows='\n'.join(failed_rows))135else:136failed = ''137body = ''.join(body_sections)138html = html_template.format(failed=failed, body=body)139index = os.path.join(image_dir, "index.html")140with open(index, "w") as f:141f.write(html)142
143show_message = not show_browser144if show_browser:145try:146import webbrowser147webbrowser.open(index)148except Exception:149show_message = True150
151if show_message:152print(f"Open {index} in a browser for a visual comparison.")153
154
155if __name__ == '__main__':156parser = argparse.ArgumentParser()157parser.add_argument('--no-browser', action='store_true',158help="Don't show browser after creating index page.")159args = parser.parse_args()160run(show_browser=not args.no_browser)161