mirror of
https://github.com/wassname/baukit.git
synced 2026-06-27 18:22:46 +08:00
327 lines
9.4 KiB
Plaintext
327 lines
9.4 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "d5d14b97",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%bash\n",
|
|
"!(stat -t /usr/local/lib/*/dist-packages/google/colab > /dev/null 2>&1) && exit\n",
|
|
"pip install git+https://github.com/davidbau/baukit > /dev/null"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "5bf765e1",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Using baukit show()\n",
|
|
"\n",
|
|
"`show()` is similar to notebook's `display()`, but it is gives you more control over layout and rendering of the HTML.\n",
|
|
"\n",
|
|
"To start, you can use it just like `print()` or `display()`."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "ac2488b8",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from baukit import show\n",
|
|
"\n",
|
|
"show('hello', 'world')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "8d40a6a9",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Easy layouts by nesting arrays\n",
|
|
"\n",
|
|
"`show()` makes it easy to produce layouts of data by arranging it in nested arrays. At the top level, data is arranged in rows; then at the second level, data is arranged in columns; then at the third level, it is split into rows again, and so on.\n",
|
|
"\n",
|
|
"(Technical detail: the HTML it produces uses [CSS flexbox layouts](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox), alternating row and column flex containers for each level of nesting.)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "c67bd9a1",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"show(['first row ' * 30,\n",
|
|
" ['second row ' * 10, 'second row second item ' * 5],\n",
|
|
" ['third row ' * 10, ['third row second item ' * 5, ['some more', 'data', 'here']]]])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "b43c195d",
|
|
"metadata": {},
|
|
"source": [
|
|
"## A simple grid layout example\n",
|
|
"\n",
|
|
"A very common pattern is to show data in a grid. Here is a three-level nested piece of retangular data:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "c969092b",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"show([[['hello', [i, j]] for j in range(1, 8)] for i in range(1, 6)])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "3c2ec531",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Showing images\n",
|
|
"\n",
|
|
"Unlike `display()`, `show()` knows how to directly render PIL images and matplotlib figures and other types of data. It also provides more powerful layout in HTML and gives you much more control over CSS formatting. "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "623a727b",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from PIL import Image\n",
|
|
"from numpy.random import randint\n",
|
|
"\n",
|
|
"show([[[f'image {i}',\n",
|
|
" Image.fromarray(randint(0,255,(128,128,3),dtype='uint8'))]\n",
|
|
" for i in range(10)]])\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "118175c2",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Controlling CSS\n",
|
|
"\n",
|
|
"The style of anything emitted by show can be controlled by using `show.style()` to inject CSS properties. `show.style` will alter the CSS style of the next item rendered by `show()`."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "0799c0f5",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"show([show.style(background='pink', font='italic 24px serif'), 'A demonstration of CSS control',\n",
|
|
" [show.style(background='skyblue'), 2, show.style(background='yellow', flex=2), 3],\n",
|
|
" show.style(background='lightgreen'), 4])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "b78f64fa",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Tight columns and Wrapped rows\n",
|
|
"\n",
|
|
"A few useful `show.style` instances are defined as constants. For example, `show.style(display='inline-flex')` is also called `show.TIGHT`, because it provides a tight layout of rows that are sized to fit the content instead of making the flexbox expand to fill its container. Similaly `show.WRAP` makes a row that packs the data to the left and wraps it (like the way text flows), instad of as spaced-out columns."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "a3e7884e",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"show(show.TIGHT,\n",
|
|
" [[[show.style(font='italic 24px serif'), 'lots of data',\n",
|
|
" show.style(background='gainsboro'),\n",
|
|
" show.WRAP, [f'({a},{b})' for a in range(i) for b in range(j)]]\n",
|
|
" for j in range(1, 5)] for i in range(1, 3)])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "92a1c75c",
|
|
"metadata": {
|
|
"scrolled": false
|
|
},
|
|
"source": [
|
|
"## Showing widgets\n",
|
|
"\n",
|
|
"baukit also contains a bunch of widgets like `Range()` and `Numberbox()` that can be shown and laid out:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "816a2956",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from baukit import Range, Numberbox\n",
|
|
"\n",
|
|
"nb = Numberbox()\n",
|
|
"ra = Range()\n",
|
|
"\n",
|
|
"show([[nb, show.style(flex=5), ra]])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "63713d4b",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Getting and setting widget values\n",
|
|
"\n",
|
|
"Widgets are live data-bound objects. So if you change a value in the widget, it will display that value right away. Also, if the user enters some input, it will be reflected in the python value right away. To see that effect, run the following cells while interacting with the widgets above:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "8e8a3115",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import random\n",
|
|
"nb.value = random.randrange(100)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "74bf1a9c",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"print(nb.value)\n",
|
|
"print(ra.value)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "770f5858",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Binding live widget properties\n",
|
|
"\n",
|
|
"Widget properties can be bound together - if you refer to a widget property using the `widget.prop()` method, it will return a live property object that can be bound to another property.\n",
|
|
"\n",
|
|
"(Also notice that if you show the same widget instance multiple times, all the rendered views will in sync.)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "a9c0f78f",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"nb2 = Numberbox()\n",
|
|
"ra2 = Range(max=1, step=0.001)\n",
|
|
"\n",
|
|
"ra2.value = nb2.prop('value')\n",
|
|
"\n",
|
|
"show([[nb2, show.style(flex=6), ra2]])\n",
|
|
"show(ra2)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "8b8a23a9",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Using PlotWidget\n",
|
|
"\n",
|
|
"Matplotlib plots can be displayed within HTML by showing the matplotlib figure.\n",
|
|
"\n",
|
|
"`PlotWidget` is a widget that manages the matplotlib figure and allows you to create a parameterized plot by writing a plotting function. Any arguments in your plotting function become parameters of the PlotWidget that you can adjust.\n",
|
|
"\n",
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "1146dbc8",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import torch\n",
|
|
"from baukit import PlotWidget\n",
|
|
"\n",
|
|
"def myplot(plt, frequency=1.0, amplitude=1.0):\n",
|
|
" [ax] = plt.axes\n",
|
|
" ax.clear()\n",
|
|
" ax.set_title(f'Sine wave of frequency {frequency}, amplitude {amplitude}')\n",
|
|
" x = torch.linspace(0, 20, 300)\n",
|
|
" y = (frequency * x).sin()\n",
|
|
" ax.plot(x, amplitude * y)\n",
|
|
" ax.set_ylim(-5, 5)\n",
|
|
"\n",
|
|
"show([[PlotWidget(myplot, format='svg', figsize=(5,3.5)), PlotWidget(myplot, frequency=2, amplitude=3, format='svg', figsize=(5,3.5))]])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "bc9f6a72",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Making interactive matplotlib plots with PlotWidget\n",
|
|
"\n",
|
|
"`PlotWidget` properties can be bound together just like any other widget properties, so it is easy to define an interactive plot interface."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "8ed28ab5",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"\n",
|
|
"freq_ra = Range(min=0.1, max=5.0, step=0.01, value=1.0)\n",
|
|
"freq_nb = Numberbox(freq_ra.prop('value'))\n",
|
|
"amp_ra = Range(min=0.1, max=5.0, step=0.01, value=1.0)\n",
|
|
"amp_nb = Numberbox(amp_ra.prop('value'))\n",
|
|
"pw = PlotWidget(myplot, frequency=freq_ra.prop('value'), amplitude=amp_ra.prop('value'))\n",
|
|
"show(show.TIGHT, [[pw],\n",
|
|
" ['frequency', show.style(flex=10), freq_ra, freq_nb],\n",
|
|
" ['amplitude', show.style(flex=10), amp_ra, amp_nb]])"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Python 3 (ipykernel)",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.9.12"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
} |