├── .gitignore ├── requirements.txt ├── README.md ├── index.ipynb ├── LICENSE ├── stl-display └── index.ipynb ├── gaussian-density └── index.ipynb └── country-indicators └── index.ipynb /.gitignore: -------------------------------------------------------------------------------- 1 | .ipynb_checkpoints -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | matplotlib==2.2.3 2 | ipywidgets 3 | voila==0.0.13 4 | pandas==0.23.4 5 | bqplot==0.11.5 6 | scipy==1.1.0 7 | ipyvolume==0.5.1 8 | numpy-stl==2.10.1 9 | ipyupload==0.1.3 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Voila gallery: Moved to [voila-gallery/gallery](https://github.com/voila-gallery/gallery) 3 | 4 | This repository has moved to its own organisation: [voila-gallery/gallery](https://github.com/voila-gallery/gallery). 5 | 6 | ~Available on [http://voila-gallery.pascalbugnion.net](http://voila-gallery.pascalbugnion.net/voila/render/index).~ 7 | 8 | ~To play with the code, open this in [Binder](https://mybinder.org/v2/gh/pbugnion/voila-gallery/master?urlpath=voila%2Ftree).~ 9 | -------------------------------------------------------------------------------- /index.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Voila gallery\n", 8 | "\n", 9 | "This is a set of examples demonstrating how to use [Voila](https://github.com/QuantStack/voila).\n", 10 | "\n", 11 | "The source for the examples is available [on GitHub](https://github.com/pbugnion/voila-gallery).\n", 12 | "\n", 13 | "## Index\n", 14 | "\n", 15 | "- [country-indicators](country-indicators/index) shows how to integrate Matplotlib plots using output widgets.\n", 16 | "- [gaussian-density](gaussian-density/index) shows how to build a dashboard around a bqplot plot.\n", 17 | "- [stl-display](stl-display/index) shows how to read STL files and display them with [ipyvolume](https://github.com/maartenbreddels/ipyvolume)." 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": null, 23 | "metadata": {}, 24 | "outputs": [], 25 | "source": [] 26 | } 27 | ], 28 | "metadata": { 29 | "kernelspec": { 30 | "display_name": "Python 3", 31 | "language": "python", 32 | "name": "python3" 33 | }, 34 | "language_info": { 35 | "codemirror_mode": { 36 | "name": "ipython", 37 | "version": 3 38 | }, 39 | "file_extension": ".py", 40 | "mimetype": "text/x-python", 41 | "name": "python", 42 | "nbconvert_exporter": "python", 43 | "pygments_lexer": "ipython3", 44 | "version": "3.6.4" 45 | } 46 | }, 47 | "nbformat": 4, 48 | "nbformat_minor": 2 49 | } 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD License 2 | 3 | Copyright (c) 2019 voila-gallery contributors. 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | a. Redistributions of source code must retain the above copyright notice, 10 | this list of conditions and the following disclaimer. 11 | 12 | b. Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in the 14 | documentation and/or other materials provided with the distribution. 15 | 16 | c. Neither the name of the authors nor the names of the contributors to 17 | this package may be used to endorse or promote products 18 | derived from this software without specific prior written 19 | permission. 20 | 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR 26 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 32 | DAMAGE. -------------------------------------------------------------------------------- /stl-display/index.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# STL file display\n", 8 | "\n", 9 | "This notebook shows how to display STL files used for 3D printing in a notebook.\n", 10 | "\n", 11 | "Displaying relies on the numpy-stl and the ipyvolume libraries.\n", 12 | "\n", 13 | "Upload an STL **ascii** file (*binary files not supported*)" 14 | ] 15 | }, 16 | { 17 | "cell_type": "code", 18 | "execution_count": 1, 19 | "metadata": {}, 20 | "outputs": [ 21 | { 22 | "data": { 23 | "application/vnd.jupyter.widget-view+json": { 24 | "model_id": "9206b73fb38b4ec58d9d944ad37a274b", 25 | "version_major": 2, 26 | "version_minor": 0 27 | }, 28 | "text/plain": [ 29 | "VBox(children=(HBox(children=(FileUpload(accept='*.stl'), Text(value=''))), ColorPicker(value='white', descrip…" 30 | ] 31 | }, 32 | "metadata": {}, 33 | "output_type": "display_data" 34 | } 35 | ], 36 | "source": [ 37 | "# imports\n", 38 | "from stl import mesh\n", 39 | "from traitlets import dlink\n", 40 | "import ipyvolume as ipv\n", 41 | "import ipywidgets as widgets\n", 42 | "from IPython.display import display\n", 43 | "from ipyupload import FileUpload\n", 44 | "from io import StringIO\n", 45 | "\n", 46 | "# widgets\n", 47 | "file_picker = FileUpload(accept='*.stl')\n", 48 | "file_name = widgets.Text()\n", 49 | "wireframe_flag = widgets.Checkbox(\n", 50 | " value=False,\n", 51 | " description='Wireframe',\n", 52 | " disabled=False)\n", 53 | "color_picker = widgets.ColorPicker(\n", 54 | " concise=False,\n", 55 | " description='Pick a color',\n", 56 | " value='white',\n", 57 | " disabled=False)\n", 58 | "vbox = widgets.VBox([widgets.HBox([file_picker, file_name]), color_picker, wireframe_flag])\n", 59 | "\n", 60 | "# display STL file\n", 61 | "def show_stl(file_content, wireframe, color):\n", 62 | " # bridge: FileUpload - stl.mesh\n", 63 | " content = next(iter(file_content.values()))['content']\n", 64 | " io = StringIO()\n", 65 | " io.write(content.decode('utf-8'))\n", 66 | " io.seek(0)\n", 67 | " name, data = mesh.Mesh.load(io)\n", 68 | " m = mesh.Mesh(data, True, name=name, speedups=True)\n", 69 | " \n", 70 | " ipv.figure()\n", 71 | " ipv.style.use('minimal')\n", 72 | " m2 = ipv.plot_mesh(m.x, m.z, m.y, color=color, wireframe=wireframe)\n", 73 | " return ipv.gcc()\n", 74 | "\n", 75 | "# get filename from FileUpload dict\n", 76 | "def get_name(file_upload):\n", 77 | " if len(file_upload) == 0:\n", 78 | " return ''\n", 79 | " return next(iter(file_upload.values()))['metadata']['name']\n", 80 | "\n", 81 | "def change_input(change):\n", 82 | " global vbox, file_picker, file_name, wireframe_flag, color_picker\n", 83 | " mymesh = show_stl(file_picker.value, wireframe_flag.value, color_picker.value)\n", 84 | " vbox.children = (widgets.HBox([file_picker, file_name]), wireframe_flag, color_picker, mymesh)\n", 85 | "\n", 86 | "# links between widgets\n", 87 | "color_picker.observe(change_input, 'value')\n", 88 | "dlink((file_picker, 'value'), (file_name, 'value'), get_name)\n", 89 | "wireframe_flag.observe(change_input, 'value')\n", 90 | "file_picker.observe(change_input, 'value')\n", 91 | "\n", 92 | "vbox" 93 | ] 94 | } 95 | ], 96 | "metadata": { 97 | "kernelspec": { 98 | "display_name": "Python 3", 99 | "language": "python", 100 | "name": "python3" 101 | }, 102 | "language_info": { 103 | "codemirror_mode": { 104 | "name": "ipython", 105 | "version": 3 106 | }, 107 | "file_extension": ".py", 108 | "mimetype": "text/x-python", 109 | "name": "python", 110 | "nbconvert_exporter": "python", 111 | "pygments_lexer": "ipython3", 112 | "version": "3.6.4" 113 | } 114 | }, 115 | "nbformat": 4, 116 | "nbformat_minor": 2 117 | } 118 | -------------------------------------------------------------------------------- /gaussian-density/index.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "In this app we:\n", 8 | "* Plot the gaussian density for a specific $\\mu$ and $\\sigma$\n", 9 | "* Use the FloatSlider widget in ipywidgets to represent $\\mu$ and $\\sigma$ values\n", 10 | "* Stack the density plot along with the sliders into a nice layout using HBox and VBox layout objects available in ipywidgets\n", 11 | "* Link the sliders to the plot so that the plot gets updated when the values of $\\mu$ and $\\sigma$ change\n", 12 | "\n", 13 | "Find the code [here](https://github.com/pbugnion/voila-gallery/blob/master/gaussian-density/index.ipynb).\n", 14 | "\n", 15 | "This example is taken from [ChakriCherukuri/mlviz](https://github.com/ChakriCherukuri/mlviz)." 16 | ] 17 | }, 18 | { 19 | "cell_type": "code", 20 | "execution_count": 1, 21 | "metadata": {}, 22 | "outputs": [ 23 | { 24 | "ename": "ModuleNotFoundError", 25 | "evalue": "No module named 'bqplot'", 26 | "output_type": "error", 27 | "traceback": [ 28 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", 29 | "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", 30 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mipywidgets\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mFloatSlider\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mHBox\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mVBox\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0;32mimport\u001b[0m \u001b[0mbqplot\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpyplot\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mplt\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", 31 | "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'bqplot'" 32 | ] 33 | } 34 | ], 35 | "source": [ 36 | "import numpy as np\n", 37 | "from scipy.stats import norm\n", 38 | "\n", 39 | "from ipywidgets import FloatSlider, HBox, VBox\n", 40 | "import bqplot.pyplot as plt" 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "execution_count": null, 46 | "metadata": {}, 47 | "outputs": [], 48 | "source": [ 49 | "x = np.linspace(-10, 10, 200)\n", 50 | "y = norm.pdf(x)\n", 51 | "\n", 52 | "# plot the gaussian density\n", 53 | "title_tmpl = 'Gaussian Density (mu = {} and sigma = {})'\n", 54 | "pdf_fig = plt.figure(title=title_tmpl.format(0, 1))\n", 55 | "pdf_line = plt.plot(x, y, 'm', stroke_width=3)" 56 | ] 57 | }, 58 | { 59 | "cell_type": "code", 60 | "execution_count": null, 61 | "metadata": {}, 62 | "outputs": [], 63 | "source": [ 64 | "# use two sliders to represent mu and sigma\n", 65 | "mu_slider = FloatSlider(description='mu', value=0, min=-5, max=5, step=.1)\n", 66 | "sigma_slider = FloatSlider(description='sigma', value=1, min=0.1, max=5, step=.1)\n", 67 | "\n", 68 | "slider_layout = HBox([mu_slider, sigma_slider])" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": null, 74 | "metadata": { 75 | "collapsed": true 76 | }, 77 | "outputs": [], 78 | "source": [ 79 | "def update_density(change):\n", 80 | " new_mu = mu_slider.value\n", 81 | " new_sigma = sigma_slider.value\n", 82 | " # update the y attribute of the plot with the new pdf\n", 83 | " # computed using new mu and sigma values\n", 84 | " pdf_line.y = norm.pdf(x, new_mu, new_sigma)\n", 85 | " \n", 86 | " # also update the fig title\n", 87 | " pdf_fig.title = title_tmpl.format(new_mu, new_sigma)\n", 88 | "\n", 89 | "# register the above callback with the 'value' trait of the sliders\n", 90 | "mu_slider.observe(update_density, 'value')\n", 91 | "sigma_slider.observe(update_density, 'value')" 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": null, 97 | "metadata": {}, 98 | "outputs": [], 99 | "source": [ 100 | "# now put all the widgets together into a simple dashboard\n", 101 | "# the plot should update now when the slider values are updated!\n", 102 | "final_layout = VBox([pdf_fig, slider_layout])\n", 103 | "final_layout" 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": null, 109 | "metadata": { 110 | "collapsed": true 111 | }, 112 | "outputs": [], 113 | "source": [] 114 | } 115 | ], 116 | "metadata": { 117 | "kernelspec": { 118 | "display_name": "Python 3", 119 | "language": "python", 120 | "name": "python3" 121 | }, 122 | "language_info": { 123 | "codemirror_mode": { 124 | "name": "ipython", 125 | "version": 3 126 | }, 127 | "file_extension": ".py", 128 | "mimetype": "text/x-python", 129 | "name": "python", 130 | "nbconvert_exporter": "python", 131 | "pygments_lexer": "ipython3", 132 | "version": "3.6.4" 133 | } 134 | }, 135 | "nbformat": 4, 136 | "nbformat_minor": 2 137 | } 138 | -------------------------------------------------------------------------------- /country-indicators/index.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 3, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "name": "stderr", 10 | "output_type": "stream", 11 | "text": [ 12 | "/Users/pascal/.virtualenvs/full36/lib/python3.6/importlib/_bootstrap.py:219: RuntimeWarning: numpy.dtype size changed, may indicate binary incompatibility. Expected 96, got 88\n", 13 | " return f(*args, **kwds)\n" 14 | ] 15 | } 16 | ], 17 | "source": [ 18 | "import pandas as pd\n", 19 | "import matplotlib.pyplot as plt\n", 20 | "import ipywidgets as widgets\n", 21 | "from IPython.display import HTML\n", 22 | "\n", 23 | "plt.ioff()" 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": 4, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "DATA_URL = 'https://gist.githubusercontent.com/chriddyp/cb5392c35661370d95f300086accea51/raw/8e0768211f6b747c0db42a9ce9a0937dafcbd8b2/indicators.csv'\n", 33 | "\n", 34 | "EXPLANATION = \"\"\"\\\n", 35 | "
\n", 36 | "

Compare different development indicators.

\n", 37 | "\n", 38 | "

Select what indicators to plot in the dropdowns, and use the slider\n", 39 | "to sub-select a fraction of years to include in the plot.

\n", 40 | "\n", 41 | "

Data and idea copied from the \n", 42 | "Plotly Dash documentation.

\n", 43 | "\n", 44 | "

This example demonstrates combining matplotlib with Jupyter widgets. For more interactive plots,\n", 45 | "consider using bqplot.\n", 46 | "

\n", 47 | "\"\"\"" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": 13, 53 | "metadata": {}, 54 | "outputs": [ 55 | { 56 | "data": { 57 | "text/html": [ 58 | "\n" 76 | ], 77 | "text/plain": [ 78 | "" 79 | ] 80 | }, 81 | "execution_count": 13, 82 | "metadata": {}, 83 | "output_type": "execute_result" 84 | } 85 | ], 86 | "source": [ 87 | "\n", 88 | "HTML(\"\"\"\\\n", 89 | "\n", 115 | "\"\"\")" 116 | ] 117 | }, 118 | { 119 | "cell_type": "code", 120 | "execution_count": 14, 121 | "metadata": {}, 122 | "outputs": [], 123 | "source": [ 124 | "class App:\n", 125 | " \n", 126 | " def __init__(self, df):\n", 127 | " self._df = df\n", 128 | " available_indicators = self._df['Indicator Name'].unique()\n", 129 | " self._x_dropdown = self._create_indicator_dropdown(available_indicators, 0)\n", 130 | " self._y_dropdown = self._create_indicator_dropdown(available_indicators, 1) \n", 131 | " self._plot_container = widgets.Output()\n", 132 | " self._year_slider, year_slider_box = self._create_year_slider(\n", 133 | " min(df['Year']), max(df['Year'])\n", 134 | " )\n", 135 | " _app_container = widgets.VBox([\n", 136 | " widgets.HBox([self._x_dropdown, self._y_dropdown]),\n", 137 | " self._plot_container,\n", 138 | " year_slider_box\n", 139 | " ], layout=widgets.Layout(align_items='center', flex='3 0 auto'))\n", 140 | " self.container = widgets.VBox([\n", 141 | " widgets.HTML(\n", 142 | " (\n", 143 | " '

Development indicators

'\n", 144 | " '

Link to code

'\n", 145 | " ), \n", 146 | " layout=widgets.Layout(margin='0 0 5em 0')\n", 147 | " ),\n", 148 | " widgets.HBox([\n", 149 | " _app_container, \n", 150 | " widgets.HTML(EXPLANATION, layout=widgets.Layout(margin='0 0 0 2em'))\n", 151 | " ])\n", 152 | " ], layout=widgets.Layout(flex='1 1 auto', margin='0 auto 0 auto', max_width='1024px'))\n", 153 | " self._update_app()\n", 154 | " \n", 155 | " @classmethod\n", 156 | " def from_url(cls, url):\n", 157 | " df = pd.read_csv(url)\n", 158 | " return cls(df)\n", 159 | " \n", 160 | " def _create_indicator_dropdown(self, indicators, initial_index):\n", 161 | " dropdown = widgets.Dropdown(options=indicators, value=indicators[initial_index])\n", 162 | " dropdown.observe(self._on_change, names=['value'])\n", 163 | " return dropdown\n", 164 | " \n", 165 | " def _create_year_slider(self, min_year, max_year):\n", 166 | " year_slider_label = widgets.Label('Year range: ')\n", 167 | " year_slider = widgets.IntRangeSlider(\n", 168 | " min=min_year, max=max_year,\n", 169 | " layout=widgets.Layout(width='500px')\n", 170 | " )\n", 171 | " year_slider.observe(self._on_change, names=['value'])\n", 172 | " year_slider_box = widgets.HBox([year_slider_label, year_slider])\n", 173 | " return year_slider, year_slider_box\n", 174 | " \n", 175 | " def _create_plot(self, x_indicator, y_indicator, year_range):\n", 176 | " df = self._df[self._df['Year'].between(*year_range)]\n", 177 | " xs = df[df['Indicator Name'] == x_indicator]['Value']\n", 178 | " ys = df[df['Indicator Name'] == y_indicator]['Value']\n", 179 | " plt.figure(figsize=(10, 8))\n", 180 | " plt.xlabel(x_indicator, size=16)\n", 181 | " plt.ylabel(y_indicator, size=16)\n", 182 | " plt.gca().tick_params(axis='both', which='major', labelsize=16)\n", 183 | " plt.plot(xs, ys, 'o', alpha=0.3)\n", 184 | " \n", 185 | " def _on_change(self, _):\n", 186 | " self._update_app()\n", 187 | " \n", 188 | " def _update_app(self):\n", 189 | " x_indicator = self._x_dropdown.value\n", 190 | " y_indicator = self._y_dropdown.value\n", 191 | " year_range = self._year_slider.value\n", 192 | " self._plot_container.clear_output(wait=True)\n", 193 | " with self._plot_container:\n", 194 | " self._create_plot(x_indicator, y_indicator, year_range)\n", 195 | " plt.show()" 196 | ] 197 | }, 198 | { 199 | "cell_type": "code", 200 | "execution_count": 15, 201 | "metadata": { 202 | "scrolled": false 203 | }, 204 | "outputs": [ 205 | { 206 | "data": { 207 | "application/vnd.jupyter.widget-view+json": { 208 | "model_id": "994fcdafa95141bb8e70452d405660b3", 209 | "version_major": 2, 210 | "version_minor": 0 211 | }, 212 | "text/plain": [ 213 | "VBox(children=(HTML(value='

Development indicators