diff --git a/README.md b/README.md index 2ac156493..958bcd0de 100644 --- a/README.md +++ b/README.md @@ -14,14 +14,11 @@ Unlike the usual HTML-converted notebooks, each user connecting to the Voila tornado application gets a dedicated Jupyter kernel which can execute the callbacks to changes in Jupyter interactive widgets. -- By default, voila disallows execute requests from the front-end, disabling - the ability to execute arbitrary code. +- By default, voila disallows execute requests from the front-end, preventing + execution of arbitrary code. - By defaults, voila runs with the `strip_source` option, which strips out the input cells from the rendered notebook. -When using these default settings, the code powering the Jupyter notebook is -never sent to the front-end. - ## Installation Voila can be installed with the conda package manager @@ -66,12 +63,28 @@ jupyter serverextension enable voila --sys-prefix When running the notebook server, the voila app is accessible from the base url suffixed with `voila`. -## Example +## Examples + +The following two examples show how a standalone Jupyter notebook can be turned into a separate app, from the command-line integration. + +**Rendering a notebook including interactive widgets and rich mime-type rendering** +![voila basics](voila-basics.gif) + +**Rendering a notebook making use of a custom widget library ([bqplot](https://github.com/bloomberg/bqplot))** + +![voila bqplot](voila-bqplot.gif) + +**Showing the source code for a voila notebook** + +The sources of the Jupyter notebook can be displayed in a voila app if option `strip_sources` is set to `False`. + +![voila sources](voila-sources.gif) + +**Voila dashboards with other language kernels** -The following screencast shows the voila-rendered version of notebook -reproducing the "wealth of nation" data visualization with bqplot. +Voila is built upon Jupyter standard formats and protocols, and is agnostic to the programming language of the notebook. In this example, we present an example of a voila application powered by the C++ Jupyter kernel [xeus-cling](https://github.com/QuantStack/xeus-cling), and the [xleaflet](https://github.com/QuantStack/xleaflet) project. -![wealth of nations](voila-won.gif) +![voila cling](voila-cling.gif) ## Related projects diff --git a/environment.yml b/environment.yml index 2a93f8321..7e7a303ea 100644 --- a/environment.yml +++ b/environment.yml @@ -6,5 +6,7 @@ dependencies: - bqplot - scipy - ipympl - - voila=0.1.1 + - voila=0.1.2 - ipympl + - xleaflet=0.7.0 + - xeus-cling=0.5.1 diff --git a/notebooks/xleaflet.ipynb b/notebooks/xleaflet.ipynb new file mode 100644 index 000000000..5bb3b84e2 --- /dev/null +++ b/notebooks/xleaflet.ipynb @@ -0,0 +1,177 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Using voila with the C++ kernel and interactive widgets" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "#include \n", + "#include \n", + "\n", + "#include \"xwidgets/xoutput.hpp\"\n", + "\n", + "#include \"xleaflet/xmap.hpp\"\n", + "#include \"xleaflet/xdraw_control.hpp\"\n", + "#include \"xleaflet/xbasemaps.hpp\"\n", + "\n", + "namespace nl = nlohmann;" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "5c813cab5e09472ba3a2caa018a6c88d", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "A Jupyter widget" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "// Create map widget\n", + "auto water_color = xlf::basemap({\"OpenStreetMap\", \"France\"});\n", + "\n", + "auto map = xlf::map_generator()\n", + " .layers({water_color})\n", + " .center({47, 363})\n", + " .zoom(5)\n", + " .finalize();\n", + "\n", + "map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "// Create output widget to log draw events\n", + "xw::output out;\n", + "out" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "// Options for the draw control\n", + "nl::json polyline_options = {\n", + " {\"shapeOptions\", {\n", + " {\"color\", \"#6bc2e5\"},\n", + " {\"weight\", 8},\n", + " {\"opacity\", 1.0}\n", + " }}\n", + "};\n", + "\n", + "nl::json polygon_options = {\n", + " {\"shapeOptions\", {\n", + " {\"fillColor\", \"#6be5c3\"},\n", + " {\"color\", \"#6be5c3\"},\n", + " {\"fillOpacity\", 1.0}\n", + " }},\n", + " {\"drawError\", {\n", + " {\"color\", \"#dd253b\"},\n", + " {\"message\", \"Oups!\"}\n", + " }},\n", + " {\"allowIntersection\", false}\n", + "};\n", + "\n", + "nl::json circle_options = {\n", + " {\"shapeOptions\", {\n", + " {\"fillColor\", \"#efed69\"},\n", + " {\"fillOpacity\", 1.0},\n", + " {\"color\", \"#efed69\"}\n", + " }}\n", + "};\n", + "\n", + "nl::json rectangle_options = {\n", + " {\"shapeOptions\", {\n", + " {\"fillColor\", \"#fca45d\"},\n", + " {\"fillOpacity\", 1.0},\n", + " {\"color\", \"#fca45d\"}\n", + " }}\n", + "};" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "// Log last action\n", + "void print_draw_event(std::string action, xeus::xjson geo_json)\n", + "{\n", + " // Capturing the stdout with the output widget \n", + " auto guard = out.guard();\n", + " std::cout << action << \" a \" \n", + " << geo_json[\"geometry\"][\"type\"]\n", + " << std::endl;\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "// Add the draw control and event logger\n", + "auto draw_control = xlf::draw_control_generator()\n", + " .polyline(polyline_options)\n", + " .polygon(polygon_options)\n", + " .circle(circle_options)\n", + " .rectangle(rectangle_options)\n", + " .finalize();\n", + "\n", + "draw_control.on_draw(print_draw_event);\n", + "map.add_control(draw_control);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "C++14", + "language": "C++14", + "name": "xcpp14" + }, + "language_info": { + "codemirror_mode": "text/x-c++src", + "file_extension": ".cpp", + "mimetype": "text/x-c++src", + "name": "c++", + "version": "-std=c++14" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/voila-basics.gif b/voila-basics.gif new file mode 100644 index 000000000..473fc036a Binary files /dev/null and b/voila-basics.gif differ diff --git a/voila-bqplot.gif b/voila-bqplot.gif new file mode 100644 index 000000000..a47873bb0 Binary files /dev/null and b/voila-bqplot.gif differ diff --git a/voila-cling.gif b/voila-cling.gif new file mode 100644 index 000000000..1439f93bb Binary files /dev/null and b/voila-cling.gif differ diff --git a/voila-sources.gif b/voila-sources.gif new file mode 100644 index 000000000..25c6818b5 Binary files /dev/null and b/voila-sources.gif differ diff --git a/voila-won.gif b/voila-won.gif deleted file mode 100644 index be91c8441..000000000 Binary files a/voila-won.gif and /dev/null differ diff --git a/voila/_version.py b/voila/_version.py index ddafd361d..edb455f55 100644 --- a/voila/_version.py +++ b/voila/_version.py @@ -6,5 +6,5 @@ # The full license is in the file LICENSE, distributed with this software. # ############################################################################# -version_info = (0, 1, 1) +version_info = (0, 1, 2) __version__ = '.'.join(map(str, version_info))