<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Jupyter Blog - Thorsten Beier</title><link href="https://jasongrout.github.io/medium-archive/pelican/" rel="alternate"/><link href="https://jasongrout.github.io/medium-archive/pelican/feeds/author-thorsten-beier.atom.xml" rel="self"/><id>https://jasongrout.github.io/medium-archive/pelican/</id><updated>2022-07-15T10:26:00+00:00</updated><subtitle>The Project Jupyter blog: news, releases, and community stories, archived from blog.jupyter.org.</subtitle><entry><title>Mamba meets JupyterLite</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2022/mamba-meets-jupyterlite/" rel="alternate"/><published>2022-07-14T11:19:00+00:00</published><updated>2022-07-15T10:26:00+00:00</updated><author><name>Thorsten Beier</name></author><id>tag:jasongrout.github.io,2022-07-14:/medium-archive/pelican/posts/2022/mamba-meets-jupyterlite/</id><summary type="html">&lt;p&gt;Introducing a mamba-based distribution for WebAssembly, and deploying scalable computing environments with JupyterLite.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2022/mamba-meets-jupyterlite/images/001-1_dbJO26hiSR8EFygX1rnqrA.webp" alt="JupyterLite logo" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;JupyterLite is a Jupyter distribution that runs entirely in the web browser without any server components. To achieve this, all language kernels must also run in the browser.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="A screenshot of JupyterLite running in the Browser. One can see as Matplotlib figure and some Pandas DataFrame code. Furthermore a p5.js kernel instance is visible." src="https://jasongrout.github.io/medium-archive/pelican/posts/2022/mamba-meets-jupyterlite/images/002-0_MoW-XpW5yQgCxinq.jpg" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;JupyterLite running in the browser as a static website&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;A significant benefit of this approach is the &lt;strong&gt;ease of deployment&lt;/strong&gt;. With JupyterLite, the only requirement to provide a live computing environment is a collection of static assets. It makes it possible to embed a console or a notebook interface on any static page or blog without having to deal with a server architecture deployment. The &lt;strong&gt;scalability&lt;/strong&gt; of this approach allowed several major projects of our ecosystem (&lt;a href="https://numpy.org"&gt;NumPy&lt;/a&gt;, &lt;a href="https://www.sympy.org/en/shell.html"&gt;SymPy&lt;/a&gt;, &lt;a href="https://pandas.pydata.org/getting_started.html"&gt;Pandas&lt;/a&gt;, &lt;a href="https://www.pymc.io/welcome.html"&gt;PyMC&lt;/a&gt;, and many more) to embed interactive examples on their websites, which are visited by millions of users monthly.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;JupyterLite is the easiest and most scalable way to embed an interactive console or notebook on a web page without any server component.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The most prominent JupyterLite kernel is the &lt;em&gt;Pyolite&lt;/em&gt; Python kernel, which is based on the &lt;a href="https://pyodide.org/en/stable/"&gt;Pyodide&lt;/a&gt; distribution for WebAssembly. Beyond the CPython interpreter, Pyodide includes many popular scientific computing packages such as NumPy, Pandas, and Matplotlib. Pyodide also provides a foreign function interface (FFI) that allows calling Python from JavaScript and vice versa.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="The JupyterLite inline console embedded on the SymPy project website" src="https://jasongrout.github.io/medium-archive/pelican/posts/2022/mamba-meets-jupyterlite/images/003-1_rKzDNlHO6LnhH1ZDyb996g.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;The JupyterLite inline console embedded on the &lt;a href="https://www.sympy.org/en/shell.html"&gt;SymPy project website&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="pyodide-and-beyond"&gt;Pyodide — and beyond&lt;/h2&gt;
&lt;p&gt;While Pyodide provides many scientific computing packages, its monolithic distribution model does not allow to specify package versions, although versions of pure python packages installed on top can be set. Our goal is to enable the &lt;strong&gt;composability of computing environments&lt;/strong&gt; allowed by package managers and to adopt the conda-forge model for large-scale software distribution crowdsourcing.&lt;/p&gt;
&lt;p&gt;Being able to pin down package versions in an environment is a strong requirement for software &lt;strong&gt;reproducibility.&lt;/strong&gt; In fact, a locked WebAssembly environment could be seen as a reproducibility &lt;strong&gt;time capsule&lt;/strong&gt;. As WebAssembly is a recognized web standard, it ought to be runnable for much longer than native binary packages: these are bound to a combination of architecture and platform and will eventually require an emulator.&lt;/p&gt;
&lt;p&gt;This is why we developed a mamba-based distribution of WebAssembly packages built with Emscripten.&lt;/p&gt;
&lt;h2 id="emscripten-forge"&gt;&lt;strong&gt;Emscripten-forge&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;The choice of the Mamba/Conda package manager was natural. Its main strength is the conda-forge community-maintained distribution, which has become the &lt;em&gt;de facto&lt;/em&gt; standard source of packages for scientific computing.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Beyond its solid technological foundations and the multi-platform nature of the conda-forge distribution, its main strength is its social model. It allowed for a crowdsourcing approach of the packaging problem, with a balance of separation of concerns between maintainer teams and across-the-board automation, plus an amazing maintainers community.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;We plan on contributing this work to the conda-forge project, so that all recipes live in the same space.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The Mamba/Conda package manager has support for many platforms and architectures such as Linux, OS X (for both x86 and arm64), and Windows. However, the &lt;strong&gt;WebAssembly&lt;/strong&gt; family of platforms is not supported yet.&lt;/p&gt;
&lt;h3 id="adding-support-for-webassembly-to-mamba-conda"&gt;Adding support for WebAssembly to mamba &amp;amp; conda&lt;/h3&gt;
&lt;p&gt;To create conda packages for the WebAssembly platform, we relied on the &lt;a href="https://emscripten.org/"&gt;Emscripten toolchain&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We defined a new target platform for conda-build and boa, namely &lt;code&gt;wasm32-unknown-emscripten&lt;/code&gt; for which we use the &lt;code&gt;emscripten-32&lt;/code&gt; shorthand name. We then associated the &lt;a href="https://emscripten.org/"&gt;Emscripten&lt;/a&gt; compiler, &lt;a href="https://github.com/emscripten-forge/recipes/tree/main/recipes/recipes/emscripten_emscripten-32"&gt;wrapped in a conda package&lt;/a&gt; as the C/C++ compiler for this new target.&lt;br&gt;
This already allowed us to build many packages, including simple libraries like &lt;code&gt;bzip2&lt;/code&gt; and &lt;code&gt;zlib&lt;/code&gt;, but also more complex packages like &lt;code&gt;Python&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;For Python extension modules we used &lt;a href="http://crossenv"&gt;&lt;code&gt;crossenv&lt;/code&gt;&lt;/a&gt; which can create virtual environments for cross-compiling, and &lt;a href="https://github.com/conda-forge/cross-python-feedstock"&gt;&lt;code&gt;cross-python&lt;/code&gt;&lt;/a&gt; which integrates &lt;a href="http://crossenv"&gt;&lt;code&gt;crossenv&lt;/code&gt;&lt;/a&gt; into conda. All the code and recipes for cross-compilation are hosted on the &lt;a href="https://github.com/emscripten-forge/recipes"&gt;emscripten-forge GitHub repository&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;We then used &lt;a href="https://github.com/emscripten-forge/recipes/blob/main/.github/workflows/build_recipes.yaml"&gt;GitHub actions&lt;/a&gt; to build packages with Emscripten and upload them to a package server.&lt;/li&gt;
&lt;li&gt;Packages are hosted on a deployment of the &lt;a href="https://github.com/mamba-org/quetz"&gt;Quetz&lt;/a&gt; open-source server.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With this, you can easily create an environment for the &lt;code&gt;emscripten-32&lt;/code&gt; target:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;micromamba create -n my-env --platform=emscripten-32 \ 
    -c https://repo.mamba.pm/emscripten-forge \ 
    -c https://repo.mamba.pm/conda-forge \
    python ipython numpy jedi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that we not only added emscripten-forge as a channel, but also &lt;a href="https://repo.mamba.pm/conda-forge"&gt;conda-forge&lt;/a&gt;. This means all noarch packages can be used.&lt;/p&gt;
&lt;h3 id="adding-new-packages-to-the-emscripten-forge-channel"&gt;Adding new packages to the emscripten-forge channel&lt;/h3&gt;
&lt;p&gt;Adding new packages is a simple procedure:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;fork the repository &lt;a href="https://github.com/emscripten-forge/recipes"&gt;https://github.com/emscripten-forge/recipes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;create a folder for your package in &lt;a href="https://github.com/emscripten-forge/recipes/tree/main/recipes/recipes_emscripten"&gt;&lt;strong&gt;recipes/recipes_emscripten/&amp;lt;my_package&amp;gt;&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;add a &lt;a href="https://github.com/emscripten-forge/recipes/blob/main/recipes/recipes_emscripten/widgetsnbextension/recipe.yaml"&gt;&lt;code&gt;recipe.yaml&lt;/code&gt;&lt;/a&gt; for your package in &lt;code&gt;recipes/recipes_emscripten/&amp;lt;your_package&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;create a pull request containing the recipe. Once the pull request is merged, the package is automatically uploaded to the &lt;code&gt;emscripten-forge&lt;/code&gt; channel.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="integration-with-jupyterlite"&gt;Integration with JupyterLite&lt;/h2&gt;
&lt;p&gt;Even though this is a general-purpose conda-based distribution for Emscripten packages, we had one particular application in mind for this first iteration: &lt;strong&gt;JupyterLite&lt;/strong&gt;. The existing Pyolite kernel is too tightly coupled with the Pyodide distribution, so we decided to go with &lt;a href="https://github.com/jupyter-xeus/xeus-python"&gt;&lt;strong&gt;xeus-python&lt;/strong&gt;&lt;/a&gt; instead.&lt;/p&gt;
&lt;p&gt;The main reason for picking &lt;a href="https://github.com/jupyter-xeus/xeus-python"&gt;xeus-python&lt;/a&gt; (over ipykernel) is that with xeus-based kernels, it is possible to override the communication layer of the kernel (switching e.g. from ZMQ to HTTP/2). In the case of JupyterLite, the implementation simply relies on direct JavaScript function calls.&lt;/p&gt;
&lt;p&gt;You can check out our &lt;a href="/posts/2021/xeus-lite/"&gt;earlier blog post&lt;/a&gt; for more details on the JupyterLite xeus-based kernels.&lt;/p&gt;
&lt;h3 id="providing-a-complete-python-development-experience"&gt;Providing a complete Python development experience&lt;/h3&gt;
&lt;p&gt;Some remaining intrinsic limitations to the WebAssembly platform need to be worked around to provide a complete experience to end-users. For example, sockets cannot be created in WebAssembly, preventing the use of the default asyncio event loop implementation. Luckily, the Pyodide authors developed a custom asyncio event-loop called &lt;a href="https://pyodide.org/en/latest/usage/api/python-api/webloop.html"&gt;WebLoop&lt;/a&gt;: it wraps the browser event loop using the Python — JavaScript foreign function interface (FFI) provided with &lt;a href="https://pyodide.org/en/stable/usage/type-conversions.html"&gt;Pyodide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pyjs:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Since it is non-trivial to extract Pyodide’s FFI and use it for other projects, we created a modern Python - JavaScript FFI from scratch. This was done with the following tricks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/pybind/pybind11"&gt;Pybind11&lt;/a&gt; is used to call Python from C++ and vice versa,&lt;/li&gt;
&lt;li&gt;&lt;a href="https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html"&gt;Embind&lt;/a&gt; is used to call JavaScript from C++ and vice versa.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When we use &lt;a href="https://github.com/pybind/pybind11"&gt;Pybind11&lt;/a&gt; and &lt;a href="https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html"&gt;Embind&lt;/a&gt; together we can call Python from JavaScript and vice versa, with C++ as a man in the middle. This not only allows us to write a simple FFI from scratch with relatively little code but also avoids calling any low-level CPython APIs and enables using high-level constructs — like &lt;a href="https://pybind11.readthedocs.io/en/stable/advanced/pycpp/object.html#calling-python-functions"&gt;&lt;code&gt;pybind11::object&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://emscripten.org/docs/api_reference/val.h.html"&gt;&lt;code&gt;emscripten::val&lt;/code&gt;&lt;/a&gt;— instead.&lt;br&gt;
The code is available in the &lt;a href="https://github.com/emscripten-forge/pyjs"&gt;pyjs&lt;/a&gt; repository. The API is very similar to Pyodide’s so that it can be used as a drop-in replacement in code, like Pyodide’s &lt;a href="https://pyodide.org/en/latest/usage/api/python-api/webloop.html"&gt;WebLoop&lt;/a&gt; implementation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Deployment:&lt;/strong&gt;The &lt;a href="https://github.com/jupyterlite/xeus-python-kernel"&gt;xeus-python-kernel&lt;/a&gt; allows conda packages to be pre-installed in the Python runtime. This can be done by passing the &lt;code&gt;XeusPythonEnv.packages&lt;/code&gt; CLI option to &lt;code&gt;jupyter lite build&lt;/code&gt;. The following command will install &lt;code&gt;NumPy&lt;/code&gt;, &lt;code&gt;Matplotlib&lt;/code&gt;, and &lt;code&gt;ipyleaflet&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;jupyter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;lite&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;XeusPythonEnv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;packages&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;\
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;numpy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;\
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;matplotlib&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;\
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;ipyleaflet&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;figure&gt;
&lt;img alt="xeus-python kernel with the ipyleaflet widget visible." src="https://jasongrout.github.io/medium-archive/pelican/posts/2022/mamba-meets-jupyterlite/images/004-1_JCiZIwwkFen5kwEA2rK4SA.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Running the xeus-python kernel with the ipyleaflet widget in JupyterLite&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;More details can be found in the &lt;a href="https://github.com/jupyterlite/xeus-python-kernel"&gt;xeus-python-kernel GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="what-about-the-future"&gt;What about the future?&lt;/h2&gt;
&lt;p&gt;This combination of JupyterLite and Mamba has the potential to open Jupyter to millions of additional users.&lt;br&gt;
Given its scalability, ease of deployment, reproducibility, and accessibility, JupyterLite will be everywhere: countries, organizations, and schools that don’t have access to sovereign cloud infrastructure will be able to deploy Jupyter-based education platforms on servers that they truly own, without endangering the data of their students or becoming too reliant on resources that they do not control.&lt;/p&gt;
&lt;h3 id="in-the-short-term-we-are-working-on-the-following-next-steps"&gt;In the short term, we are working on the following “next steps”:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mambalite:&lt;/strong&gt; To support the installation of packages at runtime. Similar to Pyodide’s pip-lite, it will allow downloading packages at runtime.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fortran:&lt;/strong&gt; Compiling Fortran code with Emscripten is currently not supported, but it is necessary for key packages like SciPy. Pyodide relies on f2c, a Fortran-to-C converter, in conjunction with a set of patches to compile Fortran code with Emscripten. We are working on a more direct approach: compiling SciPy natively with &lt;a href="https://lfortran.org/"&gt;LFortran&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Binderlite:&lt;/strong&gt; Binder converts a repository of notebooks into an executable JupyterLab environment, making code immediately reproducible by anyone, anywhere. Emscripten-forge is the missing piece to build BinderLite, a version of Binder relying on JupyterLite instances instead of vanilla JupyterLab instances.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rust/PyO3 support:&lt;/strong&gt; We are working on integrating the &lt;a href="https://blog.pyodide.org/posts/rust-pyo3-support-in-pyodide/"&gt;work of the Pyodide team&lt;/a&gt; on Rust/PyO3 support in emscripten-forge. This will be important to build Rust extension modules like &lt;code&gt;cryptography&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="credits"&gt;Credits&lt;/h2&gt;
&lt;p&gt;This was built upon the work of a much bigger crowd!&lt;/p&gt;
&lt;h3 id="the-pyodide-team"&gt;The Pyodide team&lt;/h3&gt;
&lt;p&gt;The Pyodide project was started at the Mozilla foundation by &lt;a href="https://twitter.com/MDroettboom"&gt;Michael Droettboom&lt;/a&gt; and is now maintained by &lt;a href="https://github.com/hoodmane"&gt;Hood Chatham&lt;/a&gt;, &lt;a href="https://twitter.com/RomanYurchak"&gt;Roman Yurchak&lt;/a&gt;, and &lt;a href="https://github.com/ryanking13"&gt;Gyeongjae Choi&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The foundational work of the Pyodide project pioneered the use of Python in the browser and made all of the rest possible, from JupyterLite to this work.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="the-emscripten-team"&gt;The Emscripten team&lt;/h3&gt;
&lt;p&gt;Both Pyodide and emscripten-forge are built upon the Emscripten toolchain, which provides the foundational components to be able to meaningfully run WebAssembly programs in the browser.&lt;/p&gt;
&lt;h3 id="the-jupyterlite-team"&gt;&lt;strong&gt;The JupyterLite team&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;The JupyterLite project was started by &lt;a href="https://twitter.com/jtpio"&gt;Jeremy Tuloup&lt;/a&gt;, with significant contributions from &lt;a href="https://github.com/bollwyvl"&gt;Nick Bollweg&lt;/a&gt; and &lt;a href="https://twitter.com/martinrenou"&gt;Martin Renou&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="the-mamba-org-team"&gt;The Mamba Org team&lt;/h3&gt;
&lt;p&gt;The mamba ecosystem has been instrumental in making these developments possible. We use the Quetz open-source server for hosting the packages and the Boa tool to build them. In the mamba development team, we should highlight the work of &lt;a href="https://twitter.com/wuoulf"&gt;Wolf Vollprecht&lt;/a&gt;, &lt;a href="https://twitter.com/johanmabille"&gt;Johan Mabille&lt;/a&gt;, &lt;a href="https://twitter.com/MJKlaim"&gt;Joel Lamotte&lt;/a&gt;, and &lt;a href="https://twitter.com/atrawog"&gt;Andreas Trawöger&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="the-xeus-team"&gt;The Xeus team&lt;/h3&gt;
&lt;p&gt;The xeus project was started by &lt;a href="https://twitter.com/johanmabille"&gt;Johan Mabille&lt;/a&gt; and &lt;a href="https://twitter.com/JohanMabille/"&gt;Sylvain Corlay&lt;/a&gt;. It is at the foundation of the JupyterLite integration and helped to get all the pieces together (Xeus, Mamba, Jupyter). We should especially credit the work of &lt;a href="https://twitter.com/martinRenou"&gt;Martin Renou&lt;/a&gt; and &lt;a href="https://twitter.com/thorstenbeier"&gt;Thorsten Beier&lt;/a&gt; on this integration with JupyterLite.&lt;/p&gt;
&lt;h2 id="acknowledgment"&gt;Acknowledgment&lt;/h2&gt;
&lt;p&gt;The work of Thorsten Beier, Johan Mabille, Martin Renou, Sylvain Corlay, Wolf Vollprecht, Joel Lamotte, and Andreas Trawoger at &lt;a href="https://twitter.com/QuantStack"&gt;&lt;strong&gt;QuantStack&lt;/strong&gt;&lt;/a&gt; was funded by &lt;a href="https://twitter.com/TechAtBloomberg?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor"&gt;&lt;strong&gt;Bloomberg&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="about-the-authors"&gt;About the Authors&lt;/h2&gt;
&lt;h3 id="thorsten-beier"&gt;&lt;strong&gt;Thorsten Beier&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://twitter.com/thorstenbeier"&gt;Thorsten Beier&lt;/a&gt; is a Scientific Software Engineer at &lt;a href="https://twitter.com/QuantStack"&gt;QuantStack&lt;/a&gt;. Before joining &lt;a href="https://quantstack.net/"&gt;QuantStack&lt;/a&gt;, he graduated in computer science at the University of Heidelberg and worked at the &lt;a href="https://www.embl.org/"&gt;EMBL&lt;/a&gt;. As an open-source developer, Thorsten worked on a variety of projects, from &lt;a href="https://github.com/jupyter-xeus/xeus"&gt;xeus&lt;/a&gt; and &lt;a href="https://github.com/QuantStack/xtensor"&gt;xtensor&lt;/a&gt; in C++ to &lt;a href="https://github.com/inferno-pytorch/inferno"&gt;inferno&lt;/a&gt;, &lt;a href="https://kipoi.org/"&gt;kipoi&lt;/a&gt;, &lt;a href="https://www.ilastik.org/"&gt;ilastik&lt;/a&gt;, and &lt;a href="https://github.com/uhlmanngroup/napari-splineit"&gt;napari-splineit&lt;/a&gt; in Python.&lt;/p&gt;
&lt;h3 id="martin-renou"&gt;Martin Renou&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://twitter.com/martinRenou"&gt;Martin Renou&lt;/a&gt; is a Scientific Software Engineer at &lt;a href="https://twitter.com/QuantStack"&gt;QuantStack&lt;/a&gt;. Before joining &lt;a href="http://quantstack.net/"&gt;QuantStack&lt;/a&gt;, he studied at the French Aerospace Engineering School &lt;a href="https://www.isae-supaero.fr/en"&gt;SUPAERO&lt;/a&gt;. He also worked at Logilab in Paris and Enthought in Cambridge. As an open-source developer at &lt;a href="http://quantstack.net/"&gt;QuantStack&lt;/a&gt;, Martin worked on a variety of projects, from &lt;a href="https://github.com/QuantStack/xsimd"&gt;xsimd&lt;/a&gt;, &lt;a href="https://github.com/QuantStack/xtensor"&gt;xtensor&lt;/a&gt;, and &lt;a href="https://github.com/QuantStack/xframe"&gt;xframe&lt;/a&gt; in C++ to &lt;a href="https://github.com/jupyter-widgets/ipyleaflet"&gt;ipyleaflet&lt;/a&gt; and &lt;a href="https://github.com/maartenbreddels/ipywebrtc"&gt;ipywebrtc&lt;/a&gt; in Python and JavaScript.&lt;/p&gt;
</content><category term="JupyterLite"/><category term="WebAssembly"/></entry><entry><title>Jupyter Games</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2021/jupyter-games/" rel="alternate"/><published>2021-12-14T19:38:00+00:00</published><updated>2021-12-14T19:38:00+00:00</updated><author><name>Thorsten Beier</name></author><id>tag:jasongrout.github.io,2021-12-14:/medium-archive/pelican/posts/2021/jupyter-games/</id><summary type="html">&lt;p&gt;Ipycanvas + Box2D&lt;/p&gt;
</summary><content type="html">&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/jupyter-games/images/001-1_gXbeqCDvKyaRySdAX6SnKg.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="motivation"&gt;Motivation&lt;/h2&gt;
&lt;p&gt;Making their own tiny video games can be a great way for kids to learn programming in a playful matter. While &lt;a href="https://jupyter.org/"&gt;Jupyter&lt;/a&gt; is widely used as a scientific and educational tool, &lt;a href="https://jupyter.org/"&gt;Jupyter&lt;/a&gt; is seldom used as a platform for game development. In this blog post, we show how &lt;a href="https://jupyter.org/"&gt;Jupyter&lt;/a&gt; can be used to develop tiny games based on &lt;a href="https://box2d.org/"&gt;Box2D&lt;/a&gt;. While &lt;a href="https://jupyter.org/"&gt;Jupyter&lt;/a&gt; is language agnostic and kernels exist for many programming languages, we will focus on the &lt;a href="https://www.python.org/"&gt;Python&lt;/a&gt; programming language in this blog post.&lt;/p&gt;
&lt;h2 id="mini-games"&gt;Mini-Games&lt;/h2&gt;
&lt;p&gt;When talking about video-games one might think of games such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.epicgames.com/fortnite/de/home"&gt;Fortnite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ea.com/de-de/games/battlefield"&gt;Battlefield&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ageofempires.com/"&gt;Age of Empires&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Games as the ones above are usually developed with an engine like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://unity.com/pages/unity-pro-buy-now?gclid=CjwKCAiA-9uNBhBTEiwAN3IlNHGsvz9U2GgitHO4hm4sVSHaBTi99nBotad_ht7kqABcbL00fYA0wxoC4osQAvD_BwE&amp;amp;gclsrc=aw.ds"&gt;Unity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.unrealengine.com/en-US/"&gt;Unreal Engine&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://godotengine.org/"&gt;Godot engine&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Not only do these games require complex engines to be developed, but also a whole team developing them and a lot of time and money.&lt;br&gt;
Obviously, these are not the kind of games we can and want to develop in Jupyter. We want tiny games (~ 1000 lines of code) which can be implemented by kids in a matter of a few hours rather than many days, i.e. games like &lt;a href="https://de.wikipedia.org/wiki/Pong"&gt;Pong&lt;/a&gt;, Pinball, and &lt;a href="https://www.angrybirds.com/"&gt;AngryBirds&lt;/a&gt;. In fact, we will focus on a certain class of games: 2D physics-based games, since these can be implemented very easily with the use of a 2D physics simulation engine like &lt;a href="https://box2d.org/"&gt;Box2D&lt;/a&gt; or &lt;a href="https://github.com/slembcke/Chipmunk2D"&gt;Chipmunk2D&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="box2d"&gt;Box2D&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://box2d.org/"&gt;Box2D&lt;/a&gt; is a 2D rigid body simulation library for games. &lt;a href="https://box2d.org/"&gt;Box2D&lt;/a&gt; is best explained by the demo below.&lt;/p&gt;
&lt;figure&gt;
&lt;a href="http://www.iforce2d.net/embox2d/testbed.html"&gt;&lt;img alt="A demo of Box2D compiled to JavaScript with Emscripten. Try it out (only HTTP, no HTTPS 😢 )" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/jupyter-games/images/002-1_-g4lwaLsCuTGDQUR9IBYxA.mp4" loading="lazy" data-body-image=""&gt;&lt;/a&gt;
&lt;figcaption&gt;A demo of &lt;a href="https://box2d.org/"&gt;Box2D&lt;/a&gt; compiled to &lt;a href="https://en.wikipedia.org/wiki/JavaScript"&gt;JavaScript&lt;/a&gt; with &lt;a href="https://emscripten.org/"&gt;Emscripten&lt;/a&gt;. &lt;a href="http://www.iforce2d.net/embox2d/testbed.html"&gt;Try it out&lt;/a&gt; (only HTTP, no HTTPS 😢 )&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;a href="https://box2d.org/"&gt;Box2D&lt;/a&gt; makes it very easy to implement physics-based games like &lt;a href="https://de.wikipedia.org/wiki/Angry_Birds"&gt;Angry Birds&lt;/a&gt; or &lt;a href="https://store.steampowered.com/app/22000/World_of_Goo/?l=german"&gt;World of Goo&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="box2d-debug-draw"&gt;Box2D Debug Draw&lt;/h2&gt;
&lt;h3 id="debugdraw"&gt;DebugDraw&lt;/h3&gt;
&lt;p&gt;Box2D has an abstract class &lt;em&gt;DebugDraw&lt;/em&gt; with a handful of methods to draw simple primitives. The API is given by the following:&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Box2D DebugDraw API" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/jupyter-games/images/003-1_WjriahGPOAl9g4GlMRJlVw.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Box2D DebugDraw API&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img alt="The ipycanvas based Box2D debug draw in action" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/jupyter-games/images/004-1_63aIvo4SQdeqUbVppf_WUA.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;The ipycanvas based &lt;a href="https://box2d.org/"&gt;Box2D&lt;/a&gt; debug draw in action&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Implementing this abstract class allows you to draw the physics for your UI back-end. Box2D is shipped with a &lt;a href="https://www.glfw.org/"&gt;glfw&lt;/a&gt; based DebugDraw implementation. For Python one can implement a &lt;a href="https://www.pygame.org/news"&gt;pygame&lt;/a&gt; or &lt;a href="https://kivy.org/#home"&gt;kivy&lt;/a&gt; based &lt;em&gt;DebugDraw&lt;/em&gt; implementation. For a finished product, one wants to replace the debug-draw-based renderings with custom shiny rendering routines. But using only debug-draw-based renderings is more than enough to quickly test game ideas and play around with &lt;a href="https://box2d.org/"&gt;Box2D&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="liquidfun"&gt;LiquidFun&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://google.github.io/liquidfun/"&gt;LiquidFun&lt;/a&gt; is a 2D rigid-body and fluid simulation library for games written in C++ based upon &lt;a href="http://box2d.org/"&gt;Box2D&lt;/a&gt;. &lt;a href="https://google.github.io/liquidfun/"&gt;LiquidFun&lt;/a&gt; is best explained by the demo below:&lt;/p&gt;
&lt;figure&gt;
&lt;a href="https://google.github.io/liquidfun/"&gt;&lt;img alt="A demo of LiquidFun compiled to JavaScript with Emscripten which runs in the browser. Try it out!" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/jupyter-games/images/005-1_uPfz8srjXR24dtFm8wVBQg.mp4" loading="lazy" data-body-image=""&gt;&lt;/a&gt;
&lt;figcaption&gt;A demo of LiquidFun compiled to JavaScript with &lt;a href="https://emscripten.org/"&gt;Emscripten&lt;/a&gt; which runs in the browser. &lt;a href="https://google.github.io/liquidfun/"&gt;Try it out!&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="more-than-just-games"&gt;More than just Games&lt;/h2&gt;
&lt;p&gt;Even though &lt;a href="http://box2d.org/"&gt;Box2D&lt;/a&gt; is advertised as a 2D physics engine for games, &lt;a href="http://box2d.org/"&gt;Box2D&lt;/a&gt; can also be used for educational purposes:&lt;br&gt;
The YouTube channel &lt;a href="https://www.youtube.com/c/iforce2d/videos?view=0&amp;amp;sort=da&amp;amp;flow=grid"&gt;iforce2d&lt;/a&gt; has done some impressive things with &lt;a href="http://box2d.org/"&gt;Box2D&lt;/a&gt; like a Box2D-based &lt;a href="https://youtu.be/8kZRpouZ3OQ?t=1228"&gt;combustion engine&lt;/a&gt; and a &lt;a href="https://youtu.be/zhFVMxus3No?t=155"&gt;wind tunnel&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;a href="https://youtu.be/8kZRpouZ3OQ?t=1228"&gt;&lt;img alt="Box2D based combustion engine by the youtuber iforce2d" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/jupyter-games/images/006-1_0AABOZ_YoDUqcyOVlCT-SA.mp4" loading="lazy" data-body-image=""&gt;&lt;/a&gt;
&lt;figcaption&gt;Box2D based &lt;a href="https://youtu.be/8kZRpouZ3OQ?t=1228"&gt;combustion engine&lt;/a&gt; by the youtuber &lt;a href="https://www.youtube.com/channel/UCTXOorupCLqqQifs2jbz7rQ"&gt;iforce2d&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img alt="Box2D based wind tunnel by the youtuber iforce2d" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/jupyter-games/images/007-1_rVDzJqp1EHI9UzzgkPzlqw.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Box2D based &lt;a href="https://youtu.be/zhFVMxus3No?t=155"&gt;wind tunnel&lt;/a&gt; by the youtuber &lt;a href="https://www.youtube.com/channel/UCTXOorupCLqqQifs2jbz7rQ"&gt;iforce2d&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="box2d-python"&gt;Box2D Python&lt;/h2&gt;
&lt;p&gt;Box2D has bindings for many languages and can be compiled to &lt;a href="https://webassembly.org/"&gt;Wasm&lt;/a&gt;. Several Box2D demos exist:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.iforce2d.net/embox2d/testbed.html"&gt;http://www.iforce2d.net/embox2d/testbed.html&lt;/a&gt; (only HTTP, no HTTPS 😢 )&lt;/li&gt;
&lt;li&gt;&lt;a href="https://birchlabs.co.uk/liquidfun-wasm/"&gt;https://birchlabs.co.uk/liquidfun-wasm/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://google.github.io/liquidfun/"&gt;https://google.github.io/liquidfun/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We are particularly interested in using Box2D / LiquidFun from Python.&lt;br&gt;
Here we have the following possibilities:&lt;/p&gt;
&lt;h3 id="pybox2d"&gt;pybox2d&lt;/h3&gt;
&lt;p&gt;With &lt;a href="https://github.com/pybox2d/pybox2d"&gt;pybox2d&lt;/a&gt;, Box2D has matured and robust &lt;a href="https://github.com/pybox2d/pybox2d"&gt;Python bindings&lt;/a&gt; with extensive &lt;a href="https://github.com/pybox2d/pybox2d/wiki/manual"&gt;documentation&lt;/a&gt;. Unfortunately, &lt;a href="https://github.com/pybox2d/pybox2d"&gt;pybox2d&lt;/a&gt; has a few shortcomings:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It only works with an old version of Box2D.&lt;/li&gt;
&lt;li&gt;There is no support for LiquidFun.&lt;/li&gt;
&lt;li&gt;pybox2d is mostly unmaintained.&lt;/li&gt;
&lt;li&gt;The Python bindings are generated with &lt;a href="http://www.swig.org/"&gt;SIWG&lt;/a&gt; (not really a shortcoming, but I personally strongly prefer &lt;a href="https://github.com/pybind/pybind11"&gt;pybind11&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="pyb2d"&gt;pyb2d&lt;/h3&gt;
&lt;p&gt;A disclaimer first, I am the author of the &lt;a href="https://github.com/pyb2d/pyb2d"&gt;pyb2d&lt;/a&gt; Box2D Python bindings. The motivation for creating &lt;a href="https://github.com/pyb2d/pyb2d"&gt;pyb2d&lt;/a&gt; was having Box2D / LiquidFun bindings created with &lt;a href="https://github.com/pybind/pybind11"&gt;pybind11&lt;/a&gt;. While pyb2d works with the brand-new 2.4.1 release of Box2D, has support for LiquidFun and &lt;a href="https://github.com/pybind/pybind11"&gt;pybind11&lt;/a&gt; has been used for generating the Python bindings, there are also some downsides:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/pyb2d/pyb2d"&gt;pyb2d&lt;/a&gt; has fewer examples compared to &lt;a href="https://github.com/pybox2d/pybox2d"&gt;pybox2d&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pyb2d/pyb2d"&gt;pyb2d&lt;/a&gt; is not as mature and robust as &lt;a href="https://github.com/pybox2d/pybox2d"&gt;pybox2d&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pyb2d/pyb2d"&gt;pyb2d&lt;/a&gt; is not yet as well documented as &lt;a href="https://github.com/pybox2d/pybox2d"&gt;pybox2d&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A particularly useful feature of &lt;a href="https://github.com/pyb2d/pyb2d"&gt;pyb2d&lt;/a&gt; is its &lt;em&gt;BatchDebugDraw&lt;/em&gt; implementation: While we could implement the above mentioned debug draw API directly in Python, this would have a few drawbacks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There is a certain overhead when calling C++ from Python and vice versa. When our game contains a lot of shapes, for instance circles, we would have to call &lt;em&gt;drawCircle&lt;/em&gt; very often and have a lot of calls from C++ to Python and vice versa.&lt;/li&gt;
&lt;li&gt;Some back-ends provide &lt;em&gt;batch-drawing&lt;/em&gt; capabilities such that we can draw multiple primitives at once. For instance, drawing 100 circles at different locations with a single function call where the function arguments are NumPy nd-arrays with the centers/radii of the circles. Using such a batch API can lead to tremendous speedups.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
&lt;img alt="The python batch debug draw API of pyb2d" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/jupyter-games/images/008-1_He7B_NhepkHeNjPEfziwjw.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;The python batch debug draw API of pyb2d&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;To address these issues pyb2d provides a &lt;em&gt;BatchDebugDraw&lt;/em&gt; implementation where we first collect all the individual calls like &lt;em&gt;drawCircle&lt;/em&gt;, &lt;em&gt;drawSegment, drawPolygon etc.&lt;/em&gt; We store the arguments of these calls in NumPy arrays. After collecting all the shapes we call the Python API with functions like &lt;em&gt;draw_circles, draw_segments, draw_polygons,&lt;/em&gt; etc. where all the shapes are passed to Python in a single function call. On the Python side, one can pass these batched draw instructions to a &lt;em&gt;batch-drawing&lt;/em&gt; API of the UI backed. (Spoiler: We will use the batch drawing API of ipycanvas for the Jupyter pyb2d integration.)&lt;/p&gt;
&lt;h2 id="jupyter-box2d-integration-requirements"&gt;Jupyter Box2D Integration: Requirements&lt;/h2&gt;
&lt;p&gt;To have a platform to develop tiny games from within Jupyter we need at least the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A Canvas: We need a surface/canvas on which we can draw the content of the games.&lt;/li&gt;
&lt;li&gt;Input Devices: Games would be boring without any user input. We need access to input devices like the mouse, the keyboard or even game-pads.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="ipycanvas-ipywidgets-ipyevents"&gt;Ipycanvas, Ipywidgets, Ipyevents&lt;/h2&gt;
&lt;p&gt;Jupyter has a huge ecosystem of extensions. For the Jupyter Box2D integration, we just need to pick the appropriate Jupyter extensions: &lt;a href="https://ipycanvas.readthedocs.io/en/latest/"&gt;Ipycanvas&lt;/a&gt; gives us access to the &lt;a href="https://developer.mozilla.org/de/docs/Web/API/Canvas_API"&gt;HTML Canvas&lt;/a&gt; from within Python kernels in Jupyter. This serves as the drawable surface for our games. &lt;a href="https://ipywidgets.readthedocs.io/en/latest/"&gt;Ipywidets&lt;/a&gt; and &lt;a href="https://github.com/mwcraig/ipyevents"&gt;Ipyevents&lt;/a&gt; give us access to input devices like game-pads, the keyboard, and the mouse.&lt;/p&gt;
&lt;h2 id="ipycanvas"&gt;Ipycanvas&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/jupyter-games/images/009-1_KlqFuAvQ6Hd9-pPo4hthgA.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://ipycanvas.readthedocs.io/en/latest/"&gt;Ipycanvas&lt;/a&gt; is a lightweight library developed by &lt;a href="https://twitter.com/martinRenou"&gt;Martin Renou&lt;/a&gt; exposing the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API"&gt;browser’s Canvas API&lt;/a&gt; to Jupyter. It allows drawing simple primitives directly from Python like text, lines, polygons, arcs, images, etc. With &lt;a href="https://ipycanvas.readthedocs.io/en/latest/animations.html"&gt;a few tricks&lt;/a&gt;, ipycanvas is fast enough to draw smooth animations. This even works when the server and the client are not on the same machines (when we run ipycanvas on &lt;a href="https://camo.githubusercontent.com/581c077bdbc6ca6899c86d0acc6145ae85e9d80e6f805a1071793dbe48917982/68747470733a2f2f6d7962696e6465722e6f72672f62616467655f6c6f676f2e737667"&gt;MyBinder&lt;/a&gt; for example).&lt;/p&gt;
&lt;figure&gt;
&lt;a href="https://camo.githubusercontent.com/581c077bdbc6ca6899c86d0acc6145ae85e9d80e6f805a1071793dbe48917982/68747470733a2f2f6d7962696e6465722e6f72672f62616467655f6c6f676f2e737667"&gt;&lt;img alt="Conways game of life in ipycanvas, try it out!" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/jupyter-games/images/010-1_v8D4SUV9rkTKQ6nnL6Yfsg.mp4" loading="lazy" data-body-image=""&gt;&lt;/a&gt;
&lt;figcaption&gt;Conways game of life in ipycanvas, &lt;a href="https://camo.githubusercontent.com/581c077bdbc6ca6899c86d0acc6145ae85e9d80e6f805a1071793dbe48917982/68747470733a2f2f6d7962696e6465722e6f72672f62616467655f6c6f676f2e737667"&gt;try it out!&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="an-ipycanvas-based-debugdraw"&gt;An Ipycanvas-based DebugDraw:&lt;/h3&gt;
&lt;p&gt;The first step of integrating pyb2d in Jupyter notebooks is implementing an ipycanvas based &lt;em&gt;DebugDraw&lt;/em&gt;. We recently released a &lt;a href="https://github.com/martinRenou/ipycanvas/releases/tag/0.10.0"&gt;new version&lt;/a&gt; of ipycanvas which provides an extended batch API to draw things very fast. We utilize this batch API when implementing the above mention batch-debug-draw API.&lt;/p&gt;
&lt;h3 id="handling-events-in-jupyter"&gt;Handling events in Jupyter:&lt;/h3&gt;
&lt;p&gt;We can use &lt;a href="https://github.com/mwcraig/ipyevents"&gt;Ipyevents&lt;/a&gt; for the event handling in Jupyter. Obviously, we want to handle the events &lt;em&gt;while&lt;/em&gt; our game is running. To achieve this within a Jupyter-notebook we need to run our game-loop in a dedicated thread and listen for events in the main thread.&lt;/p&gt;
&lt;h3 id="adding-buttons"&gt;Adding Buttons:&lt;/h3&gt;
&lt;p&gt;We want to have a few buttons to &lt;em&gt;start&lt;/em&gt;, &lt;em&gt;pause&lt;/em&gt; and &lt;em&gt;reset&lt;/em&gt; the Box2D based games. We can add these with &lt;a href="https://ipywidgets.readthedocs.io/en/latest/"&gt;ipywidgets&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="putting-it-all-together"&gt;Putting it all together&lt;/h2&gt;
&lt;p&gt;With all the above we can put together a pyb2d based Python Box2D integration in Jupyter. As a proof of concept we implemented a few mini-games:&lt;/p&gt;
&lt;h3 id="billiard"&gt;Billiard:&lt;/h3&gt;
&lt;p&gt;A very simple billiard game. &lt;a href="https://mybinder.org/v2/gh/pyb2d/pyb2d/main?urlpath=/lab/tree/examples/jupyter_integration.ipynb"&gt;Try it on binder!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/jupyter-games/images/011-1_ZkV-0GDc_0Kxdbc6CHzB0w.mp4" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;h3 id="angry-shapes"&gt;Angry Shapes:&lt;/h3&gt;
&lt;p&gt;An &lt;a href="https://www.angrybirds.com/"&gt;Angry Birds&lt;/a&gt;-like game implemented with pyb2d. &lt;a href="https://mybinder.org/v2/gh/pyb2d/pyb2d/main?urlpath=/lab/tree/examples/jupyter_integration.ipynb"&gt;Try it on binder!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://mybinder.org/v2/gh/pyb2d/pyb2d/main?urlpath=/lab/tree/examples/jupyter_integration.ipynb"&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/jupyter-games/images/012-1_cIqICNLl2CTGoW5vdmyr-w.mp4" alt="" loading="lazy" data-body-image=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="world-of-goo-homage"&gt;World of Goo homage:&lt;/h3&gt;
&lt;p&gt;A &lt;a href="https://store.steampowered.com/app/22000/World_of_Goo/"&gt;World of Goo&lt;/a&gt; homage implemented with pyb2d. &lt;a href="https://mybinder.org/v2/gh/pyb2d/pyb2d/main?urlpath=/lab/tree/examples/jupyter_integration.ipynb"&gt;Try it on binder!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://mybinder.org/v2/gh/pyb2d/pyb2d/main?urlpath=/lab/tree/examples/jupyter_integration.ipynb"&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/jupyter-games/images/013-1_Mr_2vTFlIfad2Wsbz6gmTQ.mp4" alt="" loading="lazy" data-body-image=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="rocket"&gt;Rocket:&lt;/h3&gt;
&lt;p&gt;Fly a rocket controlled with the keyboard, but avoid the black hole! &lt;a href="https://mybinder.org/v2/gh/pyb2d/pyb2d/main?urlpath=/lab/tree/examples/jupyter_integration.ipynb"&gt;Try it on binder!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://mybinder.org/v2/gh/pyb2d/pyb2d/main?urlpath=/lab/tree/examples/jupyter_integration.ipynb"&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/jupyter-games/images/014-1_8f05EGZrQyBxZr-Byn_vxg.mp4" alt="" loading="lazy" data-body-image=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="compatibility"&gt;Compatibility&lt;/h2&gt;
&lt;p&gt;All the pyb2d examples shown above can also be run in a &lt;a href="https://www.pygame.org/news"&gt;pygame&lt;/a&gt; window or a &lt;a href="https://kivy.org/#home"&gt;kivy&lt;/a&gt; window since pyb2d also provides back-ends for these. But even when one prefers to experiment with &lt;a href="https://www.pygame.org/news"&gt;pygame&lt;/a&gt;, the Jupyter back-end can still be interesting since one can put the testbed-examples on &lt;a href="https://mybinder.org/"&gt;MyBinder&lt;/a&gt; and have them accessible in a convenient fashion.&lt;/p&gt;
&lt;h2 id="caveats"&gt;Caveats&lt;/h2&gt;
&lt;p&gt;The Jupyter integration of pyb2d gives usable frame rates, even when run through &lt;a href="https://mybinder.org/"&gt;MyBinder&lt;/a&gt;. But nevertheless, a &lt;a href="https://www.pygame.org/news"&gt;pygame&lt;/a&gt; based back-end usually leads to a better frame rate and smoother gameplay.&lt;/p&gt;
&lt;h2 id="outlook-sneak-preview"&gt;Outlook / Sneak preview&lt;/h2&gt;
&lt;p&gt;We currently work on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Adding more examples and better documentation to pyb2d.&lt;/li&gt;
&lt;li&gt;Improve the performance of the Jupyter integration.&lt;/li&gt;
&lt;li&gt;Add pyb2d to &lt;a href="https://jupyterlite.readthedocs.io/en/latest/"&gt;JupyterLite&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Implement remote multiplayer-based gaming via the collaborative mode of JupyterLab.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
&lt;img alt="Sneak-preview: Via the collaborative mode of JupyterLab we can connect to the notebook from two machines and play billiard against each other." src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/jupyter-games/images/015-1_9gJsZRQ9CUEd2Uz_I_BBJw.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Sneak-preview: Via the collaborative mode of JupyterLab we can connect to the notebook from two machines and play billiard against each other.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="acknowledgments"&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;I would like to thank &lt;a href="https://twitter.com/martinRenou"&gt;Martin Renou&lt;/a&gt; for his help with ipycanvas.&lt;/p&gt;
&lt;h2 id="about-the-author"&gt;About the author&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://quantstack.net/thorsten.html"&gt;Thorsten Beier&lt;/a&gt; is a Scientific Software Engineer at &lt;a href="https://quantstack.net/"&gt;QuantStack&lt;/a&gt;. Before joining &lt;a href="https://quantstack.net/"&gt;QuantStack&lt;/a&gt;, he graduated in computer science at the University of Heidelberg and worked at the &lt;a href="https://www.embl.org/"&gt;EMBL&lt;/a&gt;. As an open-source developer, Thorsten worked on a variety of projects, from &lt;a href="https://github.com/DerThorsten/nifty"&gt;nifty&lt;/a&gt; and &lt;a href="https://github.com/ukoethe/vigra"&gt;vigra&lt;/a&gt; in C++ to &lt;a href="https://github.com/inferno-pytorch/inferno"&gt;inferno&lt;/a&gt;, &lt;a href="https://kipoi.org/"&gt;kipoi&lt;/a&gt;, and &lt;a href="https://www.ilastik.org/"&gt;ilastik&lt;/a&gt; in Python.&lt;/p&gt;
</content><category term="education"/><category term="widgets"/></entry><entry><title>Xeus-Lite</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2021/xeus-lite/" rel="alternate"/><published>2021-10-25T09:40:00+00:00</published><updated>2021-10-25T09:40:00+00:00</updated><author><name>Thorsten Beier</name></author><id>tag:jasongrout.github.io,2021-10-25:/medium-archive/pelican/posts/2021/xeus-lite/</id><summary type="html">&lt;p&gt;JupyterLite + Xeus = ❤️️&lt;/p&gt;
</summary><content type="html">&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/xeus-lite/images/001-1_PUlJi6czJovO90t-Dsgt5g.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;JupyterLite is a &lt;a href="https://jupyter.org/"&gt;JupyterLab&lt;/a&gt; distribution that runs entirely in the web browser, backed by in-browser language kernels. &lt;a href="https://github.com/jupyter-xeus/xeus"&gt;Xeus&lt;/a&gt; is C++ library for writing &lt;a href="https://jupyter.org/"&gt;Jupyter&lt;/a&gt; kernels. In this blogpost we show how these two can work together.&lt;/p&gt;
&lt;h2 id="jupyterlite"&gt;JupyterLite&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/xeus-lite/images/002-1_dbJO26hiSR8EFygX1rnqrA.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;With vanilla Jupyter, kernels are running in separate processes. The communication between the kernels and the client is achieved with &lt;a href="https://zeromq.org/"&gt;ZeroMQ&lt;/a&gt;. In contrast to this, JupyterLite runs entirely in the browser, including the language kernels. The following kernels are already implemented in the JupyterLite framework:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;JavaScript Kernel&lt;/li&gt;
&lt;li&gt;P5 Kernel: Since P5 is a JavaScript library, it is easy to provide a P5 kernel running in the browser.&lt;/li&gt;
&lt;li&gt;A Python kernel based on &lt;a href="https://github.com/pyodide/pyodide"&gt;pyodide&lt;/a&gt; called pyolite: While the two JavaScript based kernels are trivial to implement as in-browser kernels, &lt;a href="https://github.com/pyodide/pyodide"&gt;pyodide&lt;/a&gt; is a Python interpreter compiled to WebAssembly via Emscripten. Not only Python itself has been compiled to WebAssembly, but also the whole Scientific Stack including packages like: Numpy, Scipy, Pandas and many more. An overview of packages can be found &lt;a href="https://github.com/pyodide/pyodide/tree/main/packages"&gt;here&lt;/a&gt;. Furthermore any pure Python package can be installed from within pyolite.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since JupyterLite runs entirely in the browser, it is &lt;a href="https://jupyterlite.github.io/demo/lab/index.html"&gt;very easy to try it out&lt;/a&gt;!&lt;/p&gt;
&lt;h2 id="xeus"&gt;Xeus&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://xeus.readthedocs.io/en/latest/?badge=latest"&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/xeus-lite/images/003-1_c-fyt4I1GOXnrq3tkexaGA.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/jupyter-xeus/xeus"&gt;Xeus&lt;/a&gt; is C++ library for writing &lt;a href="https://jupyter.org/"&gt;Jupyter&lt;/a&gt; kernels. It is not a kernel but a library that simplifies the process of writing kernels. &lt;a href="https://github.com/jupyter-xeus/xeus"&gt;Xeus&lt;/a&gt; implements the &lt;a href="https://jupyter-client.readthedocs.io/en/stable/messaging.html"&gt;Jupyter messaging protocol&lt;/a&gt;, so that kernel authors only need to implement a handful of methods related to the actual interpreter, like executing pieces of code and auto-completing.&lt;br&gt;
With the help of Xeus, it is very easy to write Jupyter kernels . In fact, &lt;a href="https://github.com/jupyter-xeus/xeus"&gt;Xeus&lt;/a&gt; has already been used for making several &lt;a href="https://jupyter.org/"&gt;l&lt;/a&gt;anguage kernels:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/QuantStack/xeus-cling"&gt;xeus-cling&lt;/a&gt; is a Xeus-based C++ kernel.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jupyter-xeus/xeus-python"&gt;xeus-python&lt;/a&gt; is a Xeus-based Python kernel.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jupyter-xeus/xeus-lua"&gt;xeus-lua&lt;/a&gt; is a Xeus-based Lua kernel.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jupyter-xeus/xeus-sql"&gt;xeus-sql&lt;/a&gt; / &lt;a href="https://github.com/jupyter-xeus/xeus-sqlite"&gt;xeus-sqlite&lt;/a&gt; are Xeus-based kernel for SQL / SQLite databases.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jupyter-xeus/xeus-robot"&gt;xeus-robot&lt;/a&gt; is a Jupyter kernel for the &lt;a href="https://robotframework.org/"&gt;Robot Framework&lt;/a&gt; .&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gitlab.com/lfortran/lfortran/-/merge_requests/514"&gt;LFortran&lt;/a&gt; is a modern interactive Fortran compiler with a Xeus-based Jupyter kernel.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since it is very easy to write Xeus based kernels for Jupyter, we also want to leverage Xeus for writing JupyterLite kernels. This has been the main motivation for &lt;a href="/posts/2021/xeus-2-0/"&gt;Xeus 2.0&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="xeus-architecture"&gt;Xeus Architecture&lt;/h2&gt;
&lt;p&gt;Xeus is has three extension points as depicted below&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/xeus-lite/images/004-1_CTgb-wk-_TMWVhDzB-Yx7g.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;em&gt;&lt;strong&gt;Server&lt;/strong&gt;&lt;/em&gt; is the middleware component responsible for receiving and sending messages to the Jupyter client. The default server it is built upon ZeroMQ and handles the concurrency model of the application.&lt;br&gt;
As we will see later, a custom server is needed to connect Xeus with JupyterLite.&lt;/li&gt;
&lt;li&gt;The &lt;em&gt;&lt;strong&gt;Interpreter&lt;/strong&gt;&lt;/em&gt; provides the interface that kernel authors must implement.&lt;/li&gt;
&lt;li&gt;The &lt;em&gt;&lt;strong&gt;Debugger&lt;/strong&gt;&lt;/em&gt; provides the interface that can to be implemented when the kernel shall have &lt;a href="/posts/2020/a-visual-debugger-for-jupyter/"&gt;debug capabilities&lt;/a&gt;, but we do not yet support this for Xeus-JupyterLite-Kernels.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="jupyterlite-xeus-kernels"&gt;JupyterLite Xeus-Kernels&lt;/h2&gt;
&lt;p&gt;Traditionally, the Jupyter kernel and the Client to the Jupyter kernel run in separate processes as depicted below:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/xeus-lite/images/005-1_jHLLHjTjNWlV0e38GjvACw.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;The communication between the kernels and the client (ie the Jupyter-server) are done with inter-process communication via &lt;a href="https://zeromq.org/"&gt;ZeroMQ&lt;/a&gt;. But with JupyterLite the &lt;a href="https://jupyterlite.readthedocs.io/en/latest/"&gt;kernel runs directly in the browser&lt;/a&gt;. In that case, ZeroMQ is not required anymore to communicate with the frontend. This was the motivation for &lt;a href="/posts/2021/xeus-2-0/"&gt;Xeus 2.0&lt;/a&gt;, where it is possible to build Xeus without ZeroMQ. To implement JupyterLite Kernels with Xeus, we need to implement a custom Server which handles the &lt;a href="https://emscripten.org/"&gt;Emscripten&lt;/a&gt;/&lt;a href="https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html"&gt;Embind&lt;/a&gt;-based communication layer&lt;/p&gt;
&lt;p&gt;The overall architecture is best described with the picture below: The C++ Xeus-Kernel is compiled to WebAssembly with &lt;a href="https://emscripten.org/"&gt;Emscripten&lt;/a&gt; / &lt;a href="https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html"&gt;Embind&lt;/a&gt;. The WebAssembly compiled code runs in a dedicated WebWorker thread. The WebWorker communicates via Message Passing with a thin layer of TypeScript which implements the &lt;a href="https://github.com/jupyterlite/jupyterlite/blob/d94d472fcdfb5ce760820a6a9cd2c6ea6fc84014/packages/kernel/src/tokens.ts#L45"&gt;IKernel&lt;/a&gt; API of JupyterLite. The communication between JupyterLite and the JupyterLite k ernel is done entirely in JavaScript.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/xeus-lite/images/006-1_AwkYyHKDxj0_EYitMAxZ5Q.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;The C++ code needed to compile an existing xeus-kernel to WebAssembly is very minimal:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/xeus-lite/images/007-1_Qdv9gVF_oO9n2nLffY35SQ.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;Furthermore one needs a thin layer of TypeScript / JavaScript to implement the JupyterLite &lt;a href="https://github.com/jupyterlite/jupyterlite/blob/d94d472fcdfb5ce760820a6a9cd2c6ea6fc84014/packages/kernel/src/tokens.ts#L45"&gt;IKernel API&lt;/a&gt;. A good example of this code is given in the &lt;a href="https://github.com/jupyterlite/xeus-lua-kernel"&gt;JupyterLite Xeus-Lua repository&lt;/a&gt;. While most of the repositories code is boilerplate, one needs to provide a simple &lt;a href="https://github.com/DerThorsten/jupyterlite_xeus_lua/blob/main/Dockerfile"&gt;Dockerfile&lt;/a&gt; which compiles the Xeus-Kernel to WebAssembly.&lt;/p&gt;
&lt;h2 id="xeus-lua"&gt;Xeus-Lua&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/jupyter-xeus/xeus-lua"&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/xeus-lite/images/008-1_XjZ84G9Ftb3krekpiqBuiw.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We recently released a &lt;a href="/posts/2021/from-jupyter-to-the-moon/"&gt;Xeus based Lua kernel.&lt;/a&gt; Even though its worthwhile to have Xeus-Lua kernel for vanilla Jupyter, the main purpose of Xeus-Lua was to experiment with Xeus-based JupyterLite kernels.&lt;br&gt;
We choose Lua as the first language to try out Xeus-based JupyterLite kernels since Lua is easy to compile to WebAssembly.&lt;br&gt;
A JupyterLite instance with Xeus-Lua included can be found &lt;a href="https://jupyterlite.github.io/demo/lab/"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Xeus-Lua has built in support for interactive widgets" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/xeus-lite/images/009-1_Iwg6iPSZmr5o1ZozOlJXDQ.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Xeus-Lua has built in support for interactive widgets&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="xeus-wren"&gt;Xeus-Wren&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/DerThorsten/xeus-wren"&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/xeus-lite/images/010-1_AaO7Or9i6ZDmYR3PNGXh9Q.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Wren is relatively new “&lt;a href="https://wren.io/"&gt;Classy Little scripting Language&lt;/a&gt;” created by the author of the great book &lt;a href="https://craftinginterpreters.com/"&gt;“Crafting Interpreters”&lt;/a&gt;. Wren can be described with the following:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://wren.io/"&gt;Think Smalltalk in a Lua-sized package with a dash of Erlang and wrapped up in a familiar, modern syntax.&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We choose Wren as a second language to experiment with Xeus + JupyterLite since it is small, simple to compile to WebAssembly and easy to embed in C++. A JupyterLite instance with Xeus-Wren included can be found &lt;a href="https://jupyterlite.github.io/demo/lab?path=xeus-wren%2Fiwren.ipynb"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Xeus-Wren has built in support for displaying data of various MIME-types" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/xeus-lite/images/011-1_b-X9cmzXfq7NIXeEwfEzow.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Xeus-Wren has built in support for displaying data of various MIME-types&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="outlook"&gt;Outlook&lt;/h2&gt;
&lt;p&gt;There are many languages which can be compiled to WebAssembly like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Julia: &lt;a href="https://github.com/Keno/julia-wasm"&gt;https://github.com/Keno/julia-wasm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Octave: &lt;a href="https://news.ycombinator.com/item?id=22926120"&gt;https://news.ycombinator.com/item?id=22926120&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;C++: &lt;a href="https://github.com/binji/wasm-clang"&gt;https://github.com/binji/wasm-clang&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Python: &lt;a href="https://github.com/pyodide/pyodide"&gt;https://github.com/pyodide/pyodide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also databases as sqlite can be compiled to WebAssembly:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Sqlite: &lt;a href="https://github.com/sql-js/sql.js/"&gt;https://github.com/sql-js/sql.js/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Our goal is to provide Xeus-based JupyterLite kernels for these projects to make the JupyterLite ecosystem even more powerful.&lt;/p&gt;
&lt;h2 id="acknowledgements"&gt;Acknowledgements&lt;/h2&gt;
&lt;p&gt;We like to thank&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://twitter.com/jtpio"&gt;Jeremy Tuloup&lt;/a&gt;, &lt;a href="https://twitter.com/mad_tandon"&gt;Madhur Tandon&lt;/a&gt;, &lt;a href="https://twitter.com/martinrenou"&gt;Martin Renou&lt;/a&gt;, and &lt;a href="https://github.com/bollwyvl"&gt;Nicholas Bollweg&lt;/a&gt; for their work on JupyterLite.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/johanmabille"&gt;Johan Mabille&lt;/a&gt; for Xeus and his help implementing the Xeus-Emscripten server.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="about-the-author"&gt;About the Author&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://twitter.com/thorstenbeier"&gt;Thorsten Beier&lt;/a&gt; is a Scientific Software Engineer at &lt;a href="https://quantstack.net/"&gt;QuantStack&lt;/a&gt;. Before joining &lt;a href="https://quantstack.net/"&gt;QuantStack&lt;/a&gt;, he graduated in computer science at the University of Heidelberg and worked at the &lt;a href="https://www.embl.org/"&gt;EMBL&lt;/a&gt;. As an open source developer, Thorsten worked on a variety of projects, from &lt;a href="https://github.com/DerThorsten/nifty"&gt;nifty&lt;/a&gt; and &lt;a href="https://github.com/ukoethe/vigra"&gt;vigra&lt;/a&gt; in C++ to &lt;a href="https://github.com/inferno-pytorch/inferno"&gt;inferno&lt;/a&gt;, &lt;a href="https://kipoi.org/"&gt;kipoi&lt;/a&gt; and &lt;a href="https://www.ilastik.org/"&gt;ilastik&lt;/a&gt; in Python.&lt;/p&gt;
</content><category term="kernels"/><category term="WebAssembly"/><category term="xeus"/></entry><entry><title>From Jupyter to the Moon</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2021/from-jupyter-to-the-moon/" rel="alternate"/><published>2021-09-24T12:24:00+00:00</published><updated>2021-09-24T12:24:00+00:00</updated><author><name>Thorsten Beier</name></author><id>tag:jasongrout.github.io,2021-09-24:/medium-archive/pelican/posts/2021/from-jupyter-to-the-moon/</id><summary type="html">&lt;p&gt;A new Jupyter kernel for Lua based on Xeus&lt;/p&gt;
</summary><content type="html">&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/from-jupyter-to-the-moon/images/001-1_Or2bu8twFwywgACqLOE9AA.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Jupyter architecture in a nutshell" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/from-jupyter-to-the-moon/images/002-0_jvG9j3sKufQRiuLl.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;&lt;a href="https://jupyter.org/"&gt;Jupyter&lt;/a&gt; architecture in a nutshell&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;A key principle in Jupyter’s design is &lt;em&gt;&lt;strong&gt;language agnosticism&lt;/strong&gt;&lt;/em&gt;, and one of the main extension points of the Jupyter ecosystem is the &lt;em&gt;&lt;strong&gt;kernel&lt;/strong&gt;&lt;/em&gt;, the part of the architecture responsible for executing the user’s code.&lt;/p&gt;
&lt;p&gt;In the end, a Jupyter kernel is merely an executable implementing a well-defined inter-process communication protocol.&lt;/p&gt;
&lt;p&gt;A reference implementation of the kernel is ipykernel, which provides the default Python kernel, and utilities to build other language kernels. Another reference implementation of the protocol is &lt;a href="https://github.com/jupyter-xeus/xeus"&gt;Xeus&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="xeus"&gt;Xeus&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/jupyter-xeus/xeus"&gt;Xeus&lt;/a&gt; is C++ library for writing &lt;a href="https://jupyter.org/"&gt;Jupyter&lt;/a&gt; kernels. It is not a kernel but a library that simplifies the process of writing kernels. &lt;a href="https://github.com/jupyter-xeus/xeus"&gt;Xeus&lt;/a&gt; implements the &lt;a href="https://jupyter-client.readthedocs.io/en/stable/messaging.html"&gt;Jupyter messaging protocol&lt;/a&gt;, so that kernel authors only need to implement a handful of methods related to the actual interpreter, like executing pieces of code and auto-completing. There is a long &lt;a href="https://github.com/dbohdan/embedded-scripting-languages"&gt;list of scripting languages&lt;/a&gt; which can be embedded in C/C++. With the help of Xeus, it is very easy to write kernels for such languages. In fact, &lt;a href="https://github.com/jupyter-xeus/xeus"&gt;Xeus&lt;/a&gt; has already been used for making several &lt;a href="https://jupyter.org/"&gt;l&lt;/a&gt;anguage kernels:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/QuantStack/xeus-cling"&gt;xeus-cling&lt;/a&gt; is a Xeus-based C++ kernel.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jupyter-xeus/xeus-python"&gt;xeus-python&lt;/a&gt; is a Xeus-based Python kernel.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jupyter-xeus/xeus-sql"&gt;xeus-sql&lt;/a&gt; / &lt;a href="https://github.com/jupyter-xeus/xeus-sqlite"&gt;xeus-sqlite&lt;/a&gt; are Xeus-based kernel for SQL / SQLite databases.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jupyter-xeus/xeus-robot"&gt;xeus-robot&lt;/a&gt; is a Jupyter kernel for the &lt;a href="https://robotframework.org/"&gt;Robot Framework&lt;/a&gt; .&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gitlab.com/lfortran/lfortran/-/merge_requests/514"&gt;LFortran&lt;/a&gt; is a modern interactive Fortran compiler with a Xeus-based Jupyter kernel.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="xwidgets"&gt;xwidgets&lt;/h2&gt;
&lt;p&gt;The &lt;a href="https://github.com/jupyter-xeus/xwidgets"&gt;xwidget&lt;/a&gt; library is a C++ implementation of the &lt;a href="https://ipywidgets.readthedocs.io/en/latest/"&gt;Jupyter Interactive Widget protocol&lt;/a&gt;. Xwidgets were initially developed for xeus-cling, the Xeus C++ kernel, but any Xeus-based kernel can reuse these components.&lt;/p&gt;
&lt;h2 id="a-xeus-based-lua-kernel"&gt;A xeus-based Lua kernel&lt;/h2&gt;
&lt;p&gt;Today, I am pleased to announce the release of &lt;a href="https://github.com/jupyter-xeus/xeus-lua"&gt;xeus-lua&lt;/a&gt;, a new &lt;a href="https://jupyter.org/"&gt;Jupyter&lt;/a&gt; kernel for &lt;a href="https://www.lua.org/"&gt;Lua&lt;/a&gt; based on &lt;a href="https://github.com/jupyter-xeus/xeus"&gt;Xeus&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/from-jupyter-to-the-moon/images/003-0_xQYvimlGgIZuuZC2.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;h2 id="lua"&gt;Lua&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.lua.org/"&gt;Lua&lt;/a&gt;, which means “Moon” in Portuguese, is a lightweight embeddable scripting language written in C. While Python is one of the leading scripting languages for scientific application, &lt;a href="https://www.lua.org/"&gt;Lua&lt;/a&gt; is the leading scripting language used in games / game engines. The &lt;a href="https://en.wikipedia.org/wiki/Category:Lua_(programming_language)-scripted_video_games"&gt;list of video games using Lua&lt;/a&gt; is long and includes triple-a games like Crisys and Farcry. Not only games rely on Lua, but &lt;a href="https://en.wikipedia.org/wiki/List_of_applications_using_Lua"&gt;also applications like Adobe Photoshop Lightroom&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="sol2"&gt;Sol2&lt;/h2&gt;
&lt;figure&gt;
&lt;img alt="With the Sol2 library, Lua can be embedded into C++ in a very elegant way." src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/from-jupyter-to-the-moon/images/004-0_qDdOEdX0PhOKNTMJ.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;With the &lt;a href="https://github.com/ThePhD/sol2"&gt;Sol2&lt;/a&gt; library, Lua can be embedded into C++ in a very elegant way.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;While Lua itself can be embedded in a C++ application quite easy, it is even easier when using &lt;a href="https://github.com/ThePhD/sol2"&gt;Sol2&lt;/a&gt;. &lt;a href="https://github.com/ThePhD/sol2"&gt;Sol2&lt;/a&gt; is a C++ library that simplifies the usage of Lua from C++. Furthermore &lt;a href="https://github.com/ThePhD/sol2"&gt;Sol2&lt;/a&gt; can be used to expose C++ classes to Lua, in a similar fashion as &lt;a href="https://github.com/pybind/pybind11"&gt;pybind11&lt;/a&gt; can be used to expose C++ classes to Python.&lt;/p&gt;
&lt;h2 id="xeus-lua"&gt;Xeus-lua&lt;/h2&gt;
&lt;figure&gt;
&lt;img alt="The compulsory “Hello, World!” from xeus-lua. This blog-post would be incomplete without it." src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/from-jupyter-to-the-moon/images/005-0_Rw3rs6Cdj5FEfAQf.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;The compulsory “Hello, World!” from xeus-lua. This blog-post` would be incomplete without it.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;I am pleased to announce &lt;a href="https://github.com/jupyter-xeus/xeus-lua"&gt;xeus-lua,&lt;/a&gt; a new Jupyter kernel for the Lua language based on &lt;a href="https://github.com/jupyter-xeus/xeus"&gt;Xeus&lt;/a&gt;. Using &lt;a href="https://github.com/ThePhD/sol2"&gt;Sol2&lt;/a&gt; and &lt;a href="https://github.com/jupyter-xeus/xeus"&gt;Xeus&lt;/a&gt;, it was very easy to implement a feature rich kernel using modern C++. With the help of &lt;a href="https://github.com/ThePhD/sol2"&gt;Sol2&lt;/a&gt;, it was trivial to expose the xwidgets classes to Lua such that we can use the widgets within &lt;a href="https://github.com/jupyter-xeus/xeus-lua"&gt;xeus-lua&lt;/a&gt; notebooks.&lt;/p&gt;
&lt;h2 id="but-why-a-lua-kernel"&gt;But why a Lua kernel?&lt;/h2&gt;
&lt;p&gt;While &lt;a href="https://www.lua.org/"&gt;Lua&lt;/a&gt; might not be the hippest language in 2021, there are multiple reasons while I choose to implement such a &lt;a href="https://www.lua.org/"&gt;Lua&lt;/a&gt; kernel, and why such a kernel can be useful:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Writing a &lt;a href="https://github.com/jupyter-xeus/xeus"&gt;Xeus&lt;/a&gt;-based kernel is the best way to learn and familiarize oneself with the &lt;a href="https://github.com/jupyter-xeus"&gt;xeus ecosystem&lt;/a&gt;. And since Lua is so easy to build and embed, Lua and Xeus are perfect match. Implementing this kernel gave me great insights into Xeus and Jupyter itself.&lt;/li&gt;
&lt;li&gt;Learning &lt;a href="https://www.lua.org/"&gt;Lua&lt;/a&gt; with &lt;a href="https://github.com/jupyter-xeus/xeus-lua"&gt;xeus-lua&lt;/a&gt; is fun! Before writing &lt;a href="https://github.com/jupyter-xeus/xeus-lua"&gt;xeus-lua&lt;/a&gt;, I had zero Lua experience. While implementing xeus-lua I learned &lt;a href="https://www.lua.org/"&gt;Lua&lt;/a&gt; from within Jupyter by playing around with xwidgets from within Lua — this was a very joyful experience.&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://github.com/jupyter-xeus/xeus-lua"&gt;xeus-lua&lt;/a&gt; implementation might serve as reference for future kernel authors. In particular the &lt;a href="https://github.com/jupyter-xeus/xeus-lua/blob/main/src/xwidgets.cpp"&gt;integration of xwidgets in xeus-lua&lt;/a&gt; might be useful for future implementations.&lt;/li&gt;
&lt;li&gt;Since Lua is so easy to build, &lt;a href="https://github.com/jupyter-xeus/xeus-lua"&gt;xeus-lua&lt;/a&gt; can be built for WebAssembly and will be integrated in &lt;a href="https://jupyterlite.readthedocs.io/en/latest/"&gt;JupyterLite&lt;/a&gt; — &lt;strong&gt;stay tuned!&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="features"&gt;Features&lt;/h2&gt;
&lt;p&gt;Obviously &lt;a href="https://github.com/jupyter-xeus/xeus-lua"&gt;xeus-lua&lt;/a&gt; supports the execution of code.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Simple code execution" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/from-jupyter-to-the-moon/images/006-0_AzW845V1EKlvxO2j.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Simple code execution&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Streams are redirected to the notebooks output&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Redirection of streams" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/from-jupyter-to-the-moon/images/007-0_A-2SpNknQua_D73o.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Redirection of streams&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Errors messages are shown in the notebooks output&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Error Handling" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/from-jupyter-to-the-moon/images/008-0_yMSCAFt70y43daKm.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Error Handling&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Input streams are redirected to the notebooks input system&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="User Input" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/from-jupyter-to-the-moon/images/009-0_Pfa9ASycXFejuZKp.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;User Input&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Statements can be auto-completed with a press of tab&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Code Completion" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/from-jupyter-to-the-moon/images/010-0_dQfGwr6PtuQaSUAb.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Code Completion&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Data of different sources as Latex, JSON and html can be displayed.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Display Data" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/from-jupyter-to-the-moon/images/011-0_tHhXDPzcThHTqor5.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Display Data&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Interactive widgets can be added to the notebook!&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Widgets" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/from-jupyter-to-the-moon/images/012-0_066MCiSNqv21zJOS.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Widgets&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;We can feed the widgets with data!&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Binary buffers for widgets" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/from-jupyter-to-the-moon/images/013-0_ArP2iU5tKYDHvvZd.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Binary buffers for widgets&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Try It Out&lt;/p&gt;
&lt;p&gt;You can try it right now with &lt;a href="https://mybinder.org/"&gt;binder&lt;/a&gt;, without the need of installing anything on your computer, just by clicking on &lt;a href="https://mybinder.org/v2/gh/jupyter-xeus/xeus-lua/main?urlpath=/lab/tree/notebooks/game_of_life.ipynb"&gt;&lt;strong&gt;this link&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://mybinder.org/v2/gh/jupyter-xeus/xeus-lua/main?urlpath=/lab/tree/notebooks/game_of_life.ipynb"&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/from-jupyter-to-the-moon/images/014-0_NiFI9An8ZGVDSYyG.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="other-lua-kernels"&gt;Other Lua kernels&lt;/h2&gt;
&lt;p&gt;There are several &lt;a href="https://www.lua.org/"&gt;Lua&lt;/a&gt; kernels available:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/tomstitt/lupyter"&gt;lupyter&lt;/a&gt;: A Python based implementation of a Lua Jupyter kernel. The heavy lifting is done in a C-extension.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/guysv/ilua"&gt;ILua&lt;/a&gt;: A feature rich implementation. Ilua is implemented in Python and does the communication with Lua via IPC.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/pakozm/IPyLua"&gt;IPyLua&lt;/a&gt;: IPyLua is a pure Lua implementation.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While these implementations are feature rich and work well, none of the above supports interactive widgets. Since &lt;a href="https://github.com/jupyter-xeus/xeus-lua"&gt;xeus-lua&lt;/a&gt; is based on X&lt;a href="https://github.com/jupyter-xeus/xeus"&gt;eus&lt;/a&gt;, we can reuse components from the Xeus ecosystem like &lt;a href="https://github.com/jupyter-xeus/xwidgets"&gt;xwidgets&lt;/a&gt; with minimal effort.&lt;/p&gt;
&lt;h2 id="acknowledgments"&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;We are grateful to &lt;a href="https://twitter.com/juliettetaka?lang=en"&gt;Juliette Taka&lt;/a&gt; for the illustration.&lt;/p&gt;
&lt;h2 id="about-the-author"&gt;About the Author&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://quantstack.net/thorsten.html"&gt;Thorsten Beier&lt;/a&gt; is a Scientific Software Engineer at &lt;a href="https://quantstack.net/"&gt;QuantStack&lt;/a&gt;. Before joining &lt;a href="https://quantstack.net/"&gt;QuantStack&lt;/a&gt;, he graduated in computer science at the University of Heidelberg and worked at the &lt;a href="https://www.embl.org/"&gt;EMBL&lt;/a&gt;. As an open source developer, Thorsten worked on a variety of projects, from &lt;a href="https://github.com/DerThorsten/nifty"&gt;nifty&lt;/a&gt;, and &lt;a href="https://github.com/ukoethe/vigra"&gt;vigra&lt;/a&gt; in C++ to &lt;a href="https://github.com/inferno-pytorch/inferno"&gt;inferno&lt;/a&gt;, &lt;a href="https://kipoi.org/"&gt;kipoi&lt;/a&gt; and &lt;a href="https://www.ilastik.org/"&gt;ilastik&lt;/a&gt; in Python.&lt;/p&gt;
</content><category term="kernels"/><category term="xeus"/></entry></feed>