File size: 4,727 Bytes
92f0e98 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# show.py
#
# An abbreviated way to output simple HTML layout of text and images
# into a python notebook.
#
# - show a PIL image to show an inline HTML <img>.
# - show an array of items to vertically stack them, centered in a block.
# - show an array of arrays to horizontally lay them out as inline blocks.
# - show an array of tuples to create a table.
import PIL.Image, base64, io, IPython, types, sys
import html as html_module
from IPython.display import display
g_buffer = None
def blocks(obj, space=''):
return IPython.display.HTML(space.join(blocks_tags(obj)))
def rows(obj, space=''):
return IPython.display.HTML(space.join(rows_tags(obj)))
def rows_tags(obj):
if isinstance(obj, dict):
obj = obj.items()
results = []
results.append('<table style="display:inline-table">')
for row in obj:
results.append('<tr style="padding:0">')
for item in row:
results.append('<td style="text-align:left; vertical-align:top;' +
'padding:1px">')
results.extend(blocks_tags(item))
results.append('</td>')
results.append('</tr>')
results.append('</table>')
return results
def blocks_tags(obj):
results = []
if hasattr(obj, '_repr_html_'):
results.append(obj._repr_html_())
elif isinstance(obj, PIL.Image.Image):
results.append(pil_to_html(obj))
elif isinstance(obj, (str, int, float)):
results.append('<div>')
results.append(html_module.escape(str(obj)))
results.append('</div>')
elif isinstance(obj, dict):
results.extend(blocks_tags([(k, v) for k, v in obj.items()]))
elif hasattr(obj, '__iter__'):
if hasattr(obj, 'tolist'):
# Handle numpy/pytorch tensors as lists.
try:
obj = obj.tolist()
except:
pass
blockstart, blockend, tstart, tend, rstart, rend, cstart, cend = [
'<div style="display:inline-block;text-align:center;line-height:1;' +
'vertical-align:top;padding:1px">',
'</div>',
'<table style="display:inline-table">',
'</table>',
'<tr style="padding:0">',
'</tr>',
'<td style="text-align:left; vertical-align:top; padding:1px">',
'</td>',
]
needs_end = False
table_mode = False
for i, line in enumerate(obj):
if i == 0:
needs_end = True
if isinstance(line, tuple):
table_mode = True
results.append(tstart)
else:
results.append(blockstart)
if table_mode:
results.append(rstart)
if not isinstance(line, str) and hasattr(line, '__iter__'):
for cell in line:
results.append(cstart)
results.extend(blocks_tags(cell))
results.append(cend)
else:
results.append(cstart)
results.extend(blocks_tags(line))
results.append(cend)
results.append(rend)
else:
results.extend(blocks_tags(line))
if needs_end:
results.append(table_mode and tend or blockend)
return results
def pil_to_b64(img, format='png'):
buffered = io.BytesIO()
img.save(buffered, format=format)
return base64.b64encode(buffered.getvalue()).decode('utf-8')
def pil_to_url(img, format='png'):
return 'data:image/%s;base64,%s' % (format, pil_to_b64(img, format))
def pil_to_html(img, margin=1):
mattr = ' style="margin:%dpx"' % margin
return '<img src="%s"%s>' % (pil_to_url(img), mattr)
def a(x, cols=None):
global g_buffer
if g_buffer is None:
g_buffer = []
g_buffer.append(x)
if cols is not None and len(g_buffer) >= cols:
flush()
def reset():
global g_buffer
g_buffer = None
def flush(*args, **kwargs):
global g_buffer
if g_buffer is not None:
x = g_buffer
g_buffer = None
display(blocks(x, *args, **kwargs))
def show(x=None, *args, **kwargs):
flush(*args, **kwargs)
if x is not None:
display(blocks(x, *args, **kwargs))
def html(obj, space=''):
return blocks(obj, space)._repr_html_()
class CallableModule(types.ModuleType):
def __init__(self):
# or super().__init__(__name__) for Python 3
types.ModuleType.__init__(self, __name__)
self.__dict__.update(sys.modules[__name__].__dict__)
def __call__(self, x=None, *args, **kwargs):
show(x, *args, **kwargs)
sys.modules[__name__] = CallableModule()
|