<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Jupyter Blog - Martin Renou</title><link href="https://jasongrout.github.io/medium-archive/pelican/" rel="alternate"/><link href="https://jasongrout.github.io/medium-archive/pelican/feeds/author-martin-renou.atom.xml" rel="self"/><id>https://jasongrout.github.io/medium-archive/pelican/</id><updated>2026-08-24T16:09:00+00:00</updated><subtitle>The Project Jupyter blog: news, releases, and community stories, archived from blog.jupyter.org.</subtitle><entry><title>JupyterGIS 0.16: New visualization capabilities, collaborative Story Maps, and more</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2026/jupytergis-0-16-new-visualization-capabilities/" rel="alternate"/><published>2026-08-24T16:09:00+00:00</published><updated>2026-08-24T16:09:00+00:00</updated><author><name>Martin Renou</name></author><id>tag:jasongrout.github.io,2026-08-24:/medium-archive/pelican/posts/2026/jupytergis-0-16-new-visualization-capabilities/</id><summary type="html">&lt;p&gt;Read this article in Notebook.link, as a live story-map! https://notebook.link/@martinRenou/jupytergis-announcement&lt;/p&gt;
</summary><content type="html">&lt;blockquote&gt;
&lt;p&gt;Read this article in Notebook.link, as a live story-map! &lt;a href="https://notebook.link/@martinRenou/jupytergis-announcement"&gt;https://notebook.link/@martinRenou/jupytergis-announcement&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="/posts/2026/expanding-geospatial-workflows-in-jupytergis-stac/"&gt;Earlier this year, we introduced STAC browsing and Story Maps in JupyterGIS&lt;/a&gt;, making it easier to discover geospatial datasets and communicate results without leaving Jupyter.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/geojupyter/jupytergis/releases/tag/v0.16.0"&gt;JupyterGIS 0.16&lt;/a&gt; continues in the same direction. This release adds support for new geospatial formats, tighter integration with the scientific Python ecosystem, a redesigned Story Map editor, and a more expressive way to style geographic data.&lt;/p&gt;
&lt;h2 id="story-maps-are-getting-a-new-look"&gt;Story Maps are getting a new look!&lt;/h2&gt;
&lt;p&gt;Story Maps in JupyterGIS let you build a scrollable presentation around your map. A Story Map is made up of a sequence of segments that can combine Markdown content with map views, so you can guide the reader through a geographic story as they scroll.&lt;/p&gt;
&lt;p&gt;Each segment can define its own map state, including the current map location, visible layers, and layer styling. This means that the map can change as the reader moves through the story: layers can appear or disappear, the view can move to a new location, and symbology can change to highlight different aspects of the data.&lt;/p&gt;
&lt;h3 id="story-maps-have-received-a-significant-update-in-this-release"&gt;Story Maps have received a significant update in this release.&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Read this article in Notebook.link, as a live story-map! &lt;a href="https://notebook.link/@martinRenou/jupytergis-announcement"&gt;https://notebook.link/@martinRenou/jupytergis-announcement&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure&gt;
&lt;img alt="The Story-map associated to this release annoucement. It contains Text, images, and map views with associated layer states." src="https://jasongrout.github.io/medium-archive/pelican/posts/2026/jupytergis-0-16-new-visualization-capabilities/images/001-1_gyuKfOzFSbmRhH9LVBTJiA.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;The Story-map associated to this release annoucement. It contains Text, images, and map views with associated layer states.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="a-better-story-maps-editing-experience"&gt;A better Story Maps editing experience&lt;/h2&gt;
&lt;p&gt;We’ve also made substantial improvements to the Story Map editing experience.&lt;/p&gt;
&lt;p&gt;The editor has been redesigned around Jupyter’s &lt;strong&gt;real-time collaboration infrastructure, allowing multiple people to edit the same Story Map simultaneously&lt;/strong&gt;. Changes appear immediately for everyone, making it much easier to prepare presentations, reports, or educational material as a team.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Collaboratively edit the Story Map markdown." src="https://jasongrout.github.io/medium-archive/pelican/posts/2026/jupytergis-0-16-new-visualization-capabilities/images/002-1_yLMypnIGkeKXrR1BfXgvHg.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Collaboratively edit the Story Map markdown.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The editor now gives you a much better sense of what the final story will look like while you are working on it. Markdown sections can be previewed directly in the editor, and a new Story Map preview makes it possible to see the complete presentation without leaving the editing workflow. This makes it easier to write, arrange, and refine a story while keeping an eye on the final result. We’ve also introduced a new layout that is better suited for long-form content. In addition to guided geographic narratives, Story Maps can now be used to create richer articles combining text, maps, images, and other interactive content.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="New Story Map editor: Set story segment viewport, preview markdown, set layers properties for the story segment." src="https://jasongrout.github.io/medium-archive/pelican/posts/2026/jupytergis-0-16-new-visualization-capabilities/images/003-1_1eO0MShCVn71uIhAkC61ZA.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;New Story Map editor: Set story segment viewport, preview markdown, set layers properties for the story segment.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="openeo-layers"&gt;OpenEO layers&lt;/h2&gt;
&lt;p&gt;More and more geospatial workflows rely on remote processing instead of downloading datasets locally. openEO provides a common API to describe these processing pipelines as process graphs that are executed by a backend.&lt;/p&gt;
&lt;p&gt;JupyterGIS can now display &lt;strong&gt;openEO&lt;/strong&gt; process graphs directly as map layers. Instead of exporting intermediate results before visualizing them, you can connect an openEO backend and inspect the output of your processing pipeline directly in the map.&lt;/p&gt;
&lt;p&gt;The visualization is tile-based and lazy: JupyterGIS only requests the data needed for the current map view and zoom level. This makes it possible to explore large remote sensing workflows interactively, without materializing the full result locally.&lt;/p&gt;
&lt;p&gt;JupyterGIS can make use of any openEO server that supports tiling, such as &lt;a href="https://sentinel-hub.github.io/titiler-openeo"&gt;titiler-openeo&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;openeo&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;jupytergis&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;GISDocument&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;openeo.processes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;process&lt;/span&gt;

&lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openeo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SERVER_URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;authenticate_basic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;BASIC_AUTH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;BASIC_AUTH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;cube&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;&amp;quot;sentinel-2-global-mosaics&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;bands&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;B03&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;B08&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;temporal_extent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;2022-04-15&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;2022-12-31&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;cube&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cube&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reduce_dimension&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;dimension&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;t&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;reducer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;first&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;cube&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cube&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;10000.0&lt;/span&gt;

&lt;span class="c1"&gt;# NDWI = (GREEN - NIR) / (GREEN + NIR)&lt;/span&gt;
&lt;span class="n"&gt;ndwi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cube&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ndvi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;red&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;ndwi_vis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ndwi&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

&lt;span class="n"&gt;ndwi_png&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ndwi_vis&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;linear_scale_range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;input_min&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;input_max&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;output_min&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;output_max&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ndwi_png&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save_result&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;PNG&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GISDocument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;latitude&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;40.75&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;longitude&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mf"&gt;73.95&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;zoom&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ready&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_openeo_tile_layer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;doc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;figure&gt;
&lt;img alt="Define a process graph to compute a NDWI, using the Python API of OpenEO and JupyterGIS. It is then lazily evaluated on a per-tile basis while the user pans/zooms on the map." src="https://jasongrout.github.io/medium-archive/pelican/posts/2026/jupytergis-0-16-new-visualization-capabilities/images/004-1_L5MrEnxXuvIkT5rVl0dahw.jpg" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Define a process graph to compute a NDWI, using the Python API of OpenEO and JupyterGIS. It is then lazily evaluated on a per-tile basis while the user pans/zooms on the map.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;In addition to defining openEO process graphs from the scripting Python API, JupyterGIS provides an advanced openEO process graph editor, allowing you to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;connect to an openEO tile server&lt;/li&gt;
&lt;li&gt;define the graph graphically, with boxes and arrows&lt;/li&gt;
&lt;li&gt;load data collections and define processes with a drag-and-drop UI&lt;/li&gt;
&lt;li&gt;directly edit the JSON content&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
&lt;img alt="Editing an openEO process graph from the JupyterGIS front-end" src="https://jasongrout.github.io/medium-archive/pelican/posts/2026/jupytergis-0-16-new-visualization-capabilities/images/005-1_3AGsNcwe384V1P4-ZkzcYw.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Editing an openEO process graph from the JupyterGIS front-end&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Another interesting aspect of openEO is that process graphs have a well-defined, declarative JSON representation. Because of this structured format, &lt;strong&gt;they are a natural target for LLM-assisted workflows&lt;/strong&gt;. Users can describe the analysis they want in natural language, have an LLM generate or refine the corresponding process graph (e.g. using jupyterlite-ai), and immediately visualize the result in JupyterGIS. Combined with the lazy, tile-based rendering, this makes it possible to quickly iterate on processing pipelines without waiting for complete datasets to be exported or downloaded.&lt;/p&gt;
&lt;h2 id="lazy-visualization-of-xarray-datasets-with-jupyter-tiler"&gt;Lazy visualization of Xarray datasets with jupyter-tiler&lt;/h2&gt;
&lt;p&gt;JupyterGIS now integrates with the new &lt;a href="https://jupyter-tiler.readthedocs.io"&gt;jupyter-tiler&lt;/a&gt; package, making it straightforward to visualize Xarray datasets from Python.&lt;/p&gt;
&lt;p&gt;Datasets can come from anywhere: they may already exist in your notebook, or they can be loaded on demand from a STAC catalog using stackstac. Once you have an Xarray object, JupyterGIS can display it in the map without requiring an export to another format.&lt;/p&gt;
&lt;p&gt;Rendering happens lazily, generating only the tiles needed for the current view. This makes it possible to explore datasets that are much larger than memory while keeping navigation responsive.&lt;/p&gt;
&lt;p&gt;The result is a smoother workflow from data loading, to analysis, to visualization, all within the same notebook.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_data_array_layer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;NDSI Layer&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;data_array&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ndsi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;colormap_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;viridis&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;colormap_range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;figure&gt;
&lt;img alt="Visualizing an Xarray dataset in JupyterGIS." src="https://jasongrout.github.io/medium-archive/pelican/posts/2026/jupytergis-0-16-new-visualization-capabilities/images/006-1_GsxLjpQu33wvCx8KZxBUWA.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Visualizing an Xarray dataset in JupyterGIS.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;This feature requires the optional dependency jupyter-tiler to be installed.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;jupyter-tiler
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="a-more-expressive-symbology-model"&gt;A more expressive symbology model&lt;/h2&gt;
&lt;p&gt;Styling geographic data often requires combining multiple visual properties to communicate patterns effectively.&lt;/p&gt;
&lt;p&gt;JupyterGIS 0.16 introduces a &lt;strong&gt;new symbology model inspired by the Grammar of Graphics.&lt;/strong&gt; Instead of relying on a fixed set of styling options, visual properties such as color, size, and opacity can be defined in a more flexible and composable way.&lt;/p&gt;
&lt;p&gt;This makes it easier to build everything from simple thematic maps to more advanced visualizations while keeping styling definitions consistent and reproducible.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="A symbology example: apply a Viridis color map to the circle colors, a linear scale to the radius of circles, and a fixed stroke color." src="https://jasongrout.github.io/medium-archive/pelican/posts/2026/jupytergis-0-16-new-visualization-capabilities/images/007-1_SU9Ll713eVozkjVQNQNmMA.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;&lt;em&gt;A symbology example: apply a Viridis color map to the circle colors, a linear scale to the radius of circles, and a fixed stroke color.&lt;/em&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="geozarr-and-geopackage-support"&gt;GeoZarr and GeoPackage support&lt;/h2&gt;
&lt;p&gt;This release also expands the range of formats that JupyterGIS can open directly.&lt;/p&gt;
&lt;p&gt;Support for GeoZarr makes it possible to work with cloud-native multidimensional geospatial datasets, while GeoPackage support improves interoperability with existing GIS software and common data exchange workflows.&lt;/p&gt;
&lt;h2 id="new-collaborative-editing-capabilities"&gt;New Collaborative Editing Capabilities&lt;/h2&gt;
&lt;p&gt;JupyterGIS 0.16 also brings collaborative editing to vector layers. When working on a shared JupyterGIS document, multiple users can now edit the same vector data at the same time.&lt;/p&gt;
&lt;p&gt;Features can be created, moved, and edited collaboratively, with changes synchronized in real time between users. This makes it possible to work together on tasks such as digitizing features, annotating a map, or refining a dataset without having to exchange files or manually merge changes.&lt;/p&gt;
&lt;p&gt;Combined with the collaborative Story Map editor, this makes collaboration a more integral part of JupyterGIS: users can work together on the data itself, and then use the same shared document to explore and communicate their results.&lt;/p&gt;
&lt;h2 id="a-new-r-api"&gt;A new R API&lt;/h2&gt;
&lt;p&gt;JupyterGIS 0.16 also introduces an R client, bringing JupyterGIS to R users through the new &lt;a href="https://github.com/geojupyter/r-jupytergis"&gt;&lt;code&gt;r-jupytergis&lt;/code&gt;&lt;/a&gt; package. The R client provides bindings for interacting with JupyterGIS widgets from an R notebook, using the same JavaScript front-end as the Python client.&lt;/p&gt;
&lt;p&gt;The main interface is the &lt;code&gt;GISDocument&lt;/code&gt; widget, which can be used to create and manipulate JupyterGIS documents directly from R. This makes it possible to build geospatial workflows in R while using the same interactive map interface available to Python users.&lt;/p&gt;
&lt;p&gt;The R client also uses the same underlying collaborative infrastructure as the Python client, including the Yrs CRDT library. This means that R users can participate in the same collaborative JupyterGIS workflows rather than working in a separate environment.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;GISDocument&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;france_hiking.jGIS&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;layer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="nf"&gt;add_raster_layer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;https://mt1.google.com/vt/lyrs=y&amp;amp;x={x}&amp;amp;y={y}&amp;amp;z={z}&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Google Satellite&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;attribution&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Google&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;opacity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0.6&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="bug-fixes-and-performance-improvements"&gt;Bug fixes and performance improvements&lt;/h2&gt;
&lt;p&gt;As usual, this release also includes many smaller improvements throughout the project.&lt;/p&gt;
&lt;p&gt;We’ve fixed a number of bugs, improved performance in several parts of the application, and continued polishing both the user interface and the Python API.&lt;/p&gt;
&lt;p&gt;JupyterGIS continues to evolve as a collaborative GIS environment that fits naturally within the Jupyter ecosystem. Whether your workflow starts from a notebook, a STAC catalog, an openEO backend, or a local dataset, the goal remains the same: make it easier to move between analysis, visualization, and communication without switching tools.&lt;/p&gt;
&lt;h2 id="acknowledgements"&gt;Acknowledgements&lt;/h2&gt;
&lt;p&gt;This work on JupyterGIS by &lt;a href="https://quantstack.net/"&gt;QuantStack&lt;/a&gt; was funded by &lt;a href="https://www.esa.int/"&gt;the European Space Agency (ESA)&lt;/a&gt; for the Story-maps development, the R API, openEO layers support and the collaborative labelling. Additionally, QuantStack was funded by &lt;a href="https://cnes.fr/"&gt;the French National Centre for Space Studies (CNES)&lt;/a&gt; for the lazy visualization of xarray datasets.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="contributors-to-this-release"&gt;Contributors to this release&lt;/h2&gt;
&lt;p&gt;By order of &lt;a href="https://github-activity.readthedocs.io/en/latest/use/#how-does-this-tool-define-contributions-in-the-reports"&gt;number of contributions&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/arjxn-py"&gt;&lt;strong&gt;Arjun Verma&lt;/strong&gt;&lt;/a&gt; is a Developer at QuantStack. He worked on the server-side geoprocessing infrastructure and on the openEO editor in the JupyterGIS front-end.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/martinRenou"&gt;&lt;strong&gt;Martin Renou&lt;/strong&gt;&lt;/a&gt; is a Technical Director at QuantStack and a maintainer of JupyterGIS. For this release, Martin coordinated and guided much of the development, and worked on the integration of openEO layers.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/gjmooney"&gt;&lt;strong&gt;Gregory Mooney&lt;/strong&gt;&lt;/a&gt; is a Developer at QuantStack and a long-time contributor to JupyterGIS. He led much of the work on the new Story Map editor and its collaborative editing capabilities.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/MMesch"&gt;&lt;strong&gt;Matthias Meschede&lt;/strong&gt;&lt;/a&gt; is Chief Operating Officer at QuantStack. He introduced the new Grammar of Graphics-inspired symbology model, bringing a more expressive and composable approach to styling geographic data.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/mfisher87"&gt;&lt;strong&gt;Matt Fisher&lt;/strong&gt;&lt;/a&gt; is the Community Manager of &lt;a href="https://github.com/geojupyter"&gt;GeoJupyter&lt;/a&gt;. He contributed to many of the discussions around the release and helped shape several of the design decisions across the project.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/nakul-py"&gt;&lt;strong&gt;Nakul Verma&lt;/strong&gt;&lt;/a&gt; is an open-source contributor to JupyterGIS. He contributed numerous bug fixes and improvements throughout the release, and introduced support for Vega expressions in the new symbology system.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/AntoinePrv"&gt;&lt;strong&gt;Antoine Prouvost&lt;/strong&gt;&lt;/a&gt; is a Developer at QuantStack. He led the initial work on the R API for JupyterGIS, building its first skeleton and establishing the foundations for the &lt;code&gt;r-jupytergis&lt;/code&gt; package.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/SandrineP"&gt;&lt;strong&gt;Sandrine Pataut&lt;/strong&gt;&lt;/a&gt; is a Developer at QuantStack. She worked on bringing many of JupyterGIS’s features to the R API, helping make the new client more complete and useful for R users.&lt;/p&gt;
&lt;p&gt;We are grateful to everyone who contributed code, reviews, ideas, discussions, and feedback to this release. JupyterGIS continues to benefit from an increasingly diverse community of contributors, and we look forward to seeing what comes next!&lt;/p&gt;
</content><category term="geoscience"/><category term="JupyterGIS"/><category term="science"/></entry><entry><title>Collaborative editing for GIS workflows with Jupyter and QGIS</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2025/real-time-collaboration-and-collaborative-editing-for/" rel="alternate"/><published>2025-02-26T18:50:00+00:00</published><updated>2025-07-16T19:41:00+00:00</updated><author><name>Martin Renou</name></author><id>tag:jasongrout.github.io,2025-02-26:/medium-archive/pelican/posts/2025/real-time-collaboration-and-collaborative-editing-for/</id><summary type="html">&lt;p&gt;The QGIS open-source project is a cornerstone in the geosciences ecosystem, providing robust tools for spatial data analysis and…&lt;/p&gt;
</summary><content type="html">&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2025/real-time-collaboration-and-collaborative-editing-for/images/001-1__WoRjRDGSKbaUY6b4TsndA.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;The QGIS open-source project is a cornerstone in the geosciences ecosystem, providing robust tools for spatial data analysis and visualisation. While QGIS excels in empowering researchers and engineers, the evolving landscape of geospatial research demands enhanced collaboration and accessibility, prompting a shift towards web-based technologies.&lt;/p&gt;
&lt;h2 id="collaboration-in-jupyter"&gt;Collaboration in Jupyter&lt;/h2&gt;
&lt;p&gt;Collaboration has long been a key requirement for data science and scientific computing workflows, but Jupyter Notebooks historically lacked built-in real-time collaboration features.&lt;/p&gt;
&lt;p&gt;To bridge this gap, the &lt;a href="https://github.com/jupyterlab/jupyter-collaboration"&gt;&lt;strong&gt;jupyter-collaboration&lt;/strong&gt;&lt;/a&gt; project has focused on integrating multi-user editing capabilities directly into JupyterLab and Jupyter Notebook. This effort builds on foundational work in conflict-free replicated data types (CRDTs), leveraging technologies like &lt;a href="https://github.com/yjs/yjs"&gt;&lt;strong&gt;Yjs&lt;/strong&gt;&lt;/a&gt;, and required integration into the Notebook document model and WebSocket-based architecture.&lt;/p&gt;
&lt;figure&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/0e8IQ76sulI" title="0" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;figcaption&gt;
&lt;p&gt;Making Notebook code suggestions in collaboration mode with &lt;a href="https://github.com/jupyterlab-contrib/jupyter-suggestions"&gt;https://github.com/jupyterlab-contrib/jupyter-suggestions&lt;/a&gt;&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;This approach did not only enable collaborative editing of notebooks, but also opened the door for collaboration on other editing UIs. This was done e.g. in &lt;a href="https://github.com/jupytercad/JupyterCAD"&gt;&lt;strong&gt;JupyterCAD&lt;/strong&gt;&lt;/a&gt;, a 3D parametric modeler that allows multiple users to collaboratively design and manipulate CAD models within JupyterLab.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Read more about JupyterCAD here &lt;a href="/posts/2025/announcing-jupytercad-3-0/"&gt;https://blog.jupyter.org/announcing-jupytercad-3-0-d8f4b7b0a719&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/Zu0AT6IRA98" title="JupyterCAD suggestions" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;figcaption&gt;
&lt;p&gt;Collaboration in JupyterCAD&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="introducing-jupytergis"&gt;Introducing JupyterGIS&lt;/h2&gt;
&lt;p&gt;Today, we are excited to announce &lt;a href="https://github.com/geojupyter/jupytergis"&gt;JupyterGIS&lt;/a&gt;, a web-based, collaborative, and extensible interface for GIS, leveraging the JupyterLab application framework and integrating seamlessly with the Jupyter notebook interface.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/geojupyter/jupytergis"&gt;JupyterGIS&lt;/a&gt; provides the following key features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a JupyterLab extension for collaborative editing of geospatial data files: with COG, Shapefile, GeoJSON data source support,&lt;/li&gt;
&lt;li&gt;support for &lt;strong&gt;importing, exporting and collaborating with QGIS files,&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;advanced analysis and editing features with an &lt;strong&gt;identify tool&lt;/strong&gt; and a &lt;strong&gt;symbology panel&lt;/strong&gt; approaching what QGIS provides,&lt;/li&gt;
&lt;li&gt;easily &lt;strong&gt;share and deploy GIS projects&lt;/strong&gt; using JupyterLite.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: JupyterGIS is not an official Jupyter subproject.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="gis-features"&gt;GIS features&lt;/h2&gt;
&lt;h3 id="raster-and-vector-layers"&gt;Raster and vector layers&lt;/h3&gt;
&lt;p&gt;JupyterGIS allows you to create multiple types of raster and vector layers, including local or remote GeoTIFFs, GeoJSON, shapefiles, and tile services.&lt;/p&gt;
&lt;p&gt;You can select from a set of pre-defined tile services in our gallery, or you can provide your own source.&lt;/p&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/4_voiMm2zPk" title="1" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;h3 id="identify-tool-and-filtering"&gt;Identify tool and filtering&lt;/h3&gt;
&lt;p&gt;Akin to QGIS, we provide an identify tool and filtering capabilities, helping you to inspect your datasource.&lt;/p&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/Cs500f7eQMA" title="2" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;h3 id="symbology"&gt;Symbology&lt;/h3&gt;
&lt;p&gt;The symbology of a layer refers to its visual representation on the map, helping you to analyze your data comfortably. JupyterGIS provides a similar feature for its raster and vector layers.&lt;/p&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/nyFPZCShyxs" title="3" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;h3 id="spatio-temporal-data"&gt;Spatio-temporal data&lt;/h3&gt;
&lt;p&gt;You can easily animate and analyze your spatio-temporal data.&lt;/p&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/y6OSPdlW_kU" title="4" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;h3 id="python-api"&gt;Python API&lt;/h3&gt;
&lt;p&gt;Even though you can do most operations from the UI, JupyterGIS also provides a Python API enabling scripting capabilities, which can be used to process data and operate on JupyterGIS documents programmatically from a Jupyter notebook.&lt;/p&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/gUn1JHg1y4Y" title="5" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;h2 id="collaborative-features"&gt;Collaborative features&lt;/h2&gt;
&lt;p&gt;Building upon our previous work to enable collaborative editing in JupyterCAD, we developed a shared document model to support multi-user workflows in JupyterGIS.&lt;/p&gt;
&lt;p&gt;Everything is shared between collaborators, from layers data to symbology and filtering rules.&lt;/p&gt;
&lt;p&gt;We also provide some collaboration features like the ability to see other collaborators’ cursors, follow collaborators’ viewports, add geolocated Google Docs-like comment conversations, and see what layer features collaborators are identifying.&lt;/p&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/FzHYYCvWyu0" title="6" width="560" height="315" style="aspect-ratio: 560 / 315" loading="lazy" allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;
&lt;h2 id="try-it"&gt;Try it!&lt;/h2&gt;
&lt;p&gt;You can directly try &lt;a href="https://github.com/geojupyter/jupytergis"&gt;JupyterGIS&lt;/a&gt; in your browser, without installing anything, thanks to &lt;a href="https://github.com/jupyterlite/jupyterlite"&gt;JupyterLite&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://jupytergis.readthedocs.io/en/latest/lite/lab/index.html?path=france_hiking.jGIS/"&gt;https://jupytergis.readthedocs.io/en/latest/lite/lab/index.html&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="documentation"&gt;Documentation&lt;/h2&gt;
&lt;p&gt;Check out the Python API reference and tutorials on how to get started in our documentation:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://jupytergis.readthedocs.io/"&gt;https://jupytergis.readthedocs.io&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="whats-next"&gt;What’s next?&lt;/h2&gt;
&lt;p&gt;We are excited to welcome new contributors and see the &lt;a href="https://github.com/geojupyter/jupytergis"&gt;JupyterGIS&lt;/a&gt; community grow. Here are some exciting developments on our radar for the future:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Support for more data source types.&lt;/li&gt;
&lt;li&gt;Processing tools,&lt;/li&gt;
&lt;li&gt;Support for suggestions by collaborators, similar to the inline suggestions feature of JupyterCAD,&lt;/li&gt;
&lt;li&gt;An improved and more featureful Python API,&lt;/li&gt;
&lt;li&gt;A better coverage of QGIS features.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="how-can-you-support-our-work"&gt;How can you support our work?&lt;/h2&gt;
&lt;p&gt;Your support is important, if you would like to help us build more exciting tools around JupyterGIS, do not hesitate to contact us &lt;a href="https://jupyter.zulipchat.com/#narrow/channel/471314-geojupyter"&gt;on the public geojupyter Zulip channel!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Additionally, you can join us for the bi-weekly GeoJupyter hackathon on Wednesday &lt;a href="https://geojupyter.org/calendar.html"&gt;https://geojupyter.org/calendar.html&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="acknowledgments"&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;This work on JupyterGIS by &lt;a href="https://quantstack.net/"&gt;QuantStack&lt;/a&gt; and &lt;a href="https://www.simula.no/"&gt;Simula Research Lab&lt;/a&gt; (Simula) &lt;a href="/posts/2024/jupytergis/"&gt;was funded by the European Space Agency (ESA) for our proposal “&lt;em&gt;Real-time collaboration and collaborative editing for GIS workflows with Jupyter and QGIS&lt;/em&gt;.”&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We are also grateful to &lt;a href="https://dse.berkeley.edu"&gt;The Eric and Wendy Schmidt Center for Data Science &amp;amp; Environment (DSE) at UC Berkeley&lt;/a&gt; for funding the work of Matt Fisher on the project.&lt;/p&gt;
&lt;p&gt;Finally, this wouldn’t have been possible without the foundational work on &lt;a href="https://github.com/jupytercad/JupyterCAD"&gt;JupyterCAD&lt;/a&gt; initiated by &lt;a href="https://github.com/trungleduc"&gt;Duc Trung Le&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="about-the-jupytergis-contributors"&gt;About the JupyterGIS contributors&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2025/real-time-collaboration-and-collaborative-editing-for/images/002-1_FvjrRTQuLq-RcpISEHyB8w.jpg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.linkedin.com/in/meriem-ben-ismail-163042230/"&gt;Meriem Ben Ismail&lt;/a&gt; is a Scientific Software Developer at &lt;a href="https://quantstack.net"&gt;QuantStack&lt;/a&gt;. She just completed her Software Engineering degree at &lt;a href="https://insat.rnu.tn"&gt;INSAT&lt;/a&gt; (National Institute of Applied Sciences and Technology in Tunisia) and her six-month internship as an open-source scientific software engineer at &lt;a href="https://quantstack.net"&gt;QuantStack&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2025/real-time-collaboration-and-collaborative-editing-for/images/003-1_XiLiEd21JkqLBa_SjgN4gg.jpg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.linkedin.com/in/nicolas-brichet-a26369150/"&gt;Nicolas Brichet&lt;/a&gt; is a Scientific Software Developer at QuantStack. He holds a master’s degree in robotics from the University of Montpellier. Prior to joining Quantstack, Nicolas worked for almost fourteen years in French research institutes (INRAE and CNRS), as software developer for scientific research. He also worked on different parts of the data lifecycle, such as data acquisition, analysis, and storage.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2025/real-time-collaboration-and-collaborative-editing-for/images/004-1_wLk7y0bKAluKt1Du2r2MfA.jpg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.linkedin.com/in/david-brochart-4208721/"&gt;David Brochart&lt;/a&gt; is a Technical Director at QuantStack. David used to work in the semiconductor industry as a digital circuit designer, mostly using FPGAs. He studied telecommunications at the French “Telecom Bretagne” engineering school, with major in digital circuit design. David also worked as a researcher in hydrology at Irstea, a French scientific research institute, where he heavily used the Python scientific stack.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2025/real-time-collaboration-and-collaborative-editing-for/images/005-1_zPpzRreH5i7dnvg6L9DK_A.jpg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/mfisher87"&gt;Matt Fisher&lt;/a&gt; is a Research Software Engineer and Community Manager at &lt;a href="https://dse.berkeley.edu"&gt;Schmidt Center for Data Science &amp;amp; Environment&lt;/a&gt;. Matt is passionate about open science, community-owned software, teaching and learning, accessibility, and inclusion. It is his treasured privilege to support researchers and educators in their missions by working on projects like &lt;a href="https://qgreenland.org"&gt;QGreenland&lt;/a&gt; and &lt;a href="https://github.com/geojupyter/jupytergis"&gt;JupyterGIS!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2025/real-time-collaboration-and-collaborative-editing-for/images/006-1_J4D8_KdSR60tPA_TVAhURA.jpeg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.linkedin.com/in/annefouilloux/"&gt;Anne Fouilloux&lt;/a&gt;, a Senior Research Engineer, specializes in Open Science, FAIR data, and Big Data analytics. With a PhD in Atmospheric Physics, she has contributed to Pangeo and EOSC (European Open Science Cloud), focusing on data management, Earth system modeling, and scalable computing. A strong advocate for Open Science, she advances data accessibility and interoperability to drive scientific innovation.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2025/real-time-collaboration-and-collaborative-editing-for/images/007-1_z2By7q9wyJvunxZNezKHxg.jpg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.linkedin.com/in/gjmooney/"&gt;Greg Mooney&lt;/a&gt; is a Scientific Computing Developer at &lt;a href="https://quantstack.net"&gt;QuantStack&lt;/a&gt;. He received a Bachelors degree in Software Engineering from &lt;a href="https://www.asu.edu/"&gt;Arizona State University (ASU).&lt;/a&gt; Before joining QuantStack, he worked as an Aegis Computer Network Technician, working on the network infrastructure connecting various sensor systems onboard naval vessels.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2025/real-time-collaboration-and-collaborative-editing-for/images/008-1_rliFUY5GuF6sqKnjho66EQ.jpg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://twitter.com/martinRenou"&gt;Martin Renou&lt;/a&gt; is a Technical Director at &lt;a href="https://quantstack.net/"&gt;QuantStack&lt;/a&gt; and a maintainer of &lt;a href="https://jupyter.org/"&gt;Project Jupyter&lt;/a&gt;. Among other projects Martin is a core team member of the ipywidgets project and maintains many Jupyter widget packages such as &lt;a href="https://github.com/jupyter-widgets/ipyleaflet"&gt;ipyleaflet&lt;/a&gt;, &lt;a href="https://github.com/bloomberg/ipydatagrid"&gt;ipydatagrid&lt;/a&gt;, &lt;a href="https://github.com/QuantStack/ipygany"&gt;ipygany&lt;/a&gt;, &lt;a href="https://github.com/martinRenou/ipycanvas"&gt;ipycanvas&lt;/a&gt;, and &lt;a href="https://github.com/bqplot/bqplot"&gt;bqplot&lt;/a&gt;. He is a co-creator of the &lt;a href="https://github.com/voila-dashboards/voila/"&gt;Voilà&lt;/a&gt; dashboarding system, and the &lt;a href="https://github.com/jupyter-xeus/xeus-python"&gt;xeus-python&lt;/a&gt; kernel.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2025/real-time-collaboration-and-collaborative-editing-for/images/009-1_0_qw_xXLELz_8gHUB-3JZw.jpg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/arjxn-py"&gt;Arjun Verma&lt;/a&gt; is a Scientific Software Development Intern at &lt;a href="https://quantstack.net/"&gt;QuantStack&lt;/a&gt;. He is also a final year undergraduate student at Cluster Innovation Centre, University of Delhi. He loves 3D &amp;amp; GIS and also contributes to &lt;a href="https://github.com/jupytercad/JupyterCAD"&gt;JupyterCAD&lt;/a&gt; and is one of the maintainers of &lt;a href="https://pybamm.org/"&gt;PyBaMM&lt;/a&gt; where he has also been &lt;a href="https://summerofcode.withgoogle.com/"&gt;GSoC&lt;/a&gt; contributor and mentor.&lt;/p&gt;
</content><category term="geoscience"/><category term="science"/></entry><entry><title>Inspector JupyterLab</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2022/inspector-jupyterlab/" rel="alternate"/><published>2022-04-11T11:50:00+00:00</published><updated>2022-04-21T09:37:00+00:00</updated><author><name>Martin Renou</name></author><id>tag:jasongrout.github.io,2022-04-11:/medium-archive/pelican/posts/2022/inspector-jupyterlab/</id><summary type="html">&lt;p&gt;JupyterLab provides multiple ways to improve your coding workflow: code highlighting, code completion, theming, debugger with rich variable…&lt;/p&gt;
</summary><content type="html">&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2022/inspector-jupyterlab/images/001-1_pRzjLlwQIIMhJmx2G_3-Mw.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;JupyterLab provides multiple ways to improve your coding workflow: code highlighting, code completion, theming, debugger with rich variable rendering and more.&lt;/p&gt;
&lt;h2 id="the-jupyterlab-inspector"&gt;The JupyterLab inspector&lt;/h2&gt;
&lt;p&gt;The JupyterLab inspector is one of the ways to enhance your coding experience, it is a UI panel that provides &lt;strong&gt;contextual help&lt;/strong&gt; while you are typing:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2022/inspector-jupyterlab/images/002-1_zSExeL4Doygxl-o3lnStuQ.mp4" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;You can open the inspector using the &lt;strong&gt;Ctrl + I&lt;/strong&gt; shortcut (or &lt;strong&gt;⌘ + I&lt;/strong&gt; on Mac).&lt;/p&gt;
&lt;p&gt;With the Python kernel (ipykernel or xeus-python), this contextual help normally contains a text representation generated using the &lt;code&gt;inspect&lt;/code&gt; Python module and the docstrings associated to an object. But there is a way to make it much nicer!&lt;/p&gt;
&lt;h2 id="go-go-gadget-docrepr"&gt;Go-Go-Gadget Docrepr&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://github.com/spyder-ide/docrepr"&gt;Docrepr&lt;/a&gt; is a Python package which &lt;strong&gt;renders docstrings into HTML&lt;/strong&gt; using &lt;a href="https://www.sphinx-doc.org/"&gt;Sphinx&lt;/a&gt;, maintained by the Spyder team. IPython allows to use docrepr for code inspection, making it the perfect combination for a nice rendering of the contextual help in the inspector!&lt;/p&gt;
&lt;p&gt;Thanks to the recent work on the &lt;a href="https://github.com/jupyterlab/jupyterlab_pygments"&gt;jupyterlab-pygments&lt;/a&gt; extension, the docrepr output even &lt;strong&gt;respect the current JupyterLab theme&lt;/strong&gt; for syntax highlighting!&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2022/inspector-jupyterlab/images/003-1_OtluradnAZEDP_Cpe7x-hQ.mp4" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;h3 id="installation"&gt;Installation&lt;/h3&gt;
&lt;p&gt;First you will need to install the package (either with pip or mamba)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pip install docrepr jupyterlab_pygments
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Or:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mamba install -c conda-forge docrepr jupyterlab_pygments
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In order for IPython to use docrepr, you will need to execute the following in your Notebook (&lt;em&gt;e.g.&lt;/em&gt; in the first cell):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;ip = get_ipython()
ip.sphinxify_docstring = True
ip.enable_html_pager = True
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This also can be set in your IPython configuration file located in &lt;code&gt;~/.ipython/profile_default/ipython_config.py&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;c = get_config()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;c.InteractiveShell.sphinxify_docstring = True
c.InteractiveShell.enable_html_pager = True
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You are all set! The JupyterLab inspector will now render HTML representations of the contextual help.&lt;/p&gt;
&lt;h2 id="acknowledgments"&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;Docrepr has a long history, it originates from the Sphinxify tool of the Sage project that was created back in 2009 by &lt;a href="https://twitter.com/timdumol"&gt;Tim Dumol&lt;/a&gt;. In 2010 &lt;a href="https://twitter.com/ccordoba12?lang=en"&gt;Carlos Córdoba&lt;/a&gt; used it to power Spyder’s help pane and in 2015 he extracted that code and created the docrepr Python package, so that other projects could benefit from it. It was later integrated in IPython by &lt;a href="https://twitter.com/SylvainCorlay"&gt;Sylvain Corlay&lt;/a&gt;. In 2021 &lt;a href="https://github.com/CAM-Gerlach"&gt;C.A.M. Gerlach&lt;/a&gt;, &lt;a href="https://github.com/fasiha"&gt;Ahmed Fasih&lt;/a&gt; and myself updated the package to support the latest Sphinx version.&lt;/p&gt;
&lt;p&gt;My work on this project 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://www.techatbloomberg.com/"&gt;&lt;strong&gt;Bloomberg&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="about-the-author"&gt;About the Author&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2022/inspector-jupyterlab/images/004-0_Rb8PCWI-Ozz0Fhxy.jpg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;My name is &lt;a href="https://twitter.com/martinRenou"&gt;Martin Renou&lt;/a&gt;, I am a Scientific Software Engineer at &lt;a href="https://quantstack.net/"&gt;&lt;strong&gt;QuantStack&lt;/strong&gt;&lt;/a&gt;. Before joining QuantStack, I studied at the aerospace engineering school &lt;a href="https://www.isae-supaero.fr/en"&gt;SUPAERO&lt;/a&gt; in Toulouse, France. I also worked at Logilab in Paris, France and Enthought in Cambridge, UK. As an open-source developer at QuantStack, I work on a variety of projects, from &lt;a href="https://github.com/QuantStack/xtensor"&gt;xtensor&lt;/a&gt; and &lt;a href="https://github.com/QuantStack/xeus-python/"&gt;xeus-python&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/bqplot/bqplot"&gt;bqplot&lt;/a&gt; in Python and JavaScript/TypeScript, I am also the author of several JupyterLab extensions.&lt;/p&gt;
</content><category term="documentation"/><category term="JupyterLab"/></entry><entry><title>Abracadabra! Bringing the magics to xeus-python</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2021/abracadabra-bringing-the-magics-to-xeus-python/" rel="alternate"/><published>2021-02-18T13:30:00+00:00</published><updated>2021-02-18T14:06:00+00:00</updated><author><name>Martin Renou</name></author><id>tag:jasongrout.github.io,2021-02-18:/medium-archive/pelican/posts/2021/abracadabra-bringing-the-magics-to-xeus-python/</id><summary type="html">&lt;p&gt;Last year, we set ourselves to implement a visual debugger for JupyterLab. This endeavor required major developments in the JupyterLab…&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Last year, we set ourselves to implement a &lt;strong&gt;visual debugger for JupyterLab&lt;/strong&gt;. This endeavor required major developments in the JupyterLab front-end, in core-Jupyter protocols, and on the kernel side (the part of the Jupyter infrastructure responsible for executing the code).&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/jupyter-xeus/xeus-python"&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/abracadabra-bringing-the-magics-to-xeus-python/images/001-0_B0kK-zNJr0Suisyv.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For kernel-side development, we decided to start with the &lt;a href="/posts/2019/a-new-python-kernel-for-jupyter/"&gt;&lt;strong&gt;xeus-python&lt;/strong&gt; kernel&lt;/a&gt;, a lightweight implementation of a Jupyter kernel for the Python programming language. Based on &lt;a href="https://github.com/jupyter-xeus/xeus"&gt;&lt;strong&gt;xeus&lt;/strong&gt;&lt;/a&gt;, xeus-python has a flexible concurrency model that was required to &lt;em&gt;e.g.&lt;/em&gt; add breakpoints while executing code.&lt;/p&gt;
&lt;p&gt;Unfortunately, xeus-python did not provide all ipykernel features (magics, Matplotlib support, &lt;em&gt;etc.&lt;/em&gt;). Furthermore, many notebooks depend on IPython, as they import it explicitely or make use of the IPython configuration system.&lt;/p&gt;
&lt;p&gt;Today, we are proud to announce that xeus-python supports 100% of the IPython magics! This was achieved by leveraging the core IPython package. This is getting us closer to feature parity with ipykernel.&lt;/p&gt;
&lt;h2 id="magics"&gt;Magics&lt;/h2&gt;
&lt;p&gt;xeus-python now supports all magics that IPython provides and even user-defined magics!&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Support for builtin IPython magics and user-defined magics" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/abracadabra-bringing-the-magics-to-xeus-python/images/002-1_PTiGVyDsazc_ziz6Bk4EnA.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Support for builtin IPython magics and user-defined magics&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="matplotlib"&gt;Matplotlib&lt;/h2&gt;
&lt;p&gt;Most Matplotlib back-ends are now supported by xeus-python, allowing you to show static plots with the inline back-end or interactive plots with &lt;a href="https://github.com/matplotlib/ipympl"&gt;ipympl&lt;/a&gt; in your Notebook:&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Matplotlib inline back-end and ipympl interactive back-end" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/abracadabra-bringing-the-magics-to-xeus-python/images/003-1_cmnPUKlhHHwUf8PZhNQx2g.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Matplotlib inline back-end and ipympl interactive back-end&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="extending"&gt;Extending&lt;/h2&gt;
&lt;p&gt;IPython has a rich configuration system that you can tweak in order to get an enhanced Notebook experience. Xeus-python now supports any configuration you setup for IPython:&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Automatically import NumPy in the IPython settings" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/abracadabra-bringing-the-magics-to-xeus-python/images/004-1_bB5hiXIbVAlV3kX9KJfLfg.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Automatically import NumPy in the IPython settings&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="visual-debugging"&gt;Visual Debugging&lt;/h2&gt;
&lt;p&gt;The latest JupyterLab version introduced a visual debugger in its interface. xeus-python was the first Jupyter kernel to add support for it!&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Stepping into Python code in JupyterLab with the visual debugger" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/abracadabra-bringing-the-magics-to-xeus-python/images/005-1_efZAtaJQqeirAZoEqbxvdw.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Stepping into Python code in JupyterLab with the visual debugger&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;xeus-python is not the only Jupyter kernel that supports debugging anymore: &lt;a href="https://github.com/jupyter-xeus/xeus-robot"&gt;xeus-robot&lt;/a&gt; is a xeus-based Jupyter kernel for the &lt;a href="https://robotframework.org/"&gt;RobotFramework&lt;/a&gt; language that supports the JupyterLab visual debugger.&lt;/p&gt;
&lt;h2 id="try-it-online"&gt;Try it online&lt;/h2&gt;
&lt;p&gt;Thanks to &lt;a href="https://mybinder.org/"&gt;MyBinder&lt;/a&gt;, you can try it out without the need of installing anything on your computer. Just follow this link:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://mybinder.org/v2/gh/jupyter-xeus/xeus-python/stable?urlpath=/lab/tree/notebooks/xeus-python.ipynb"&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/abracadabra-bringing-the-magics-to-xeus-python/images/006-0_2sBOFFsk_322apCe.jpg" alt="" loading="lazy" data-body-image=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="installation"&gt;Installation&lt;/h2&gt;
&lt;p&gt;You can install the latest xeus-python version using mamba or conda:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mamba install xeus-python -c conda-forge
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Or&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;conda install xeus-python -c conda-forge
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can also compile it yourself, instructions can be found in the repository:&lt;br&gt;
&lt;a href="https://github.com/jupyter-xeus/xeus-python"&gt;https://github.com/jupyter-xeus/xeus-python&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="acknowledgments"&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;My work on &lt;a href="https://github.com/QuantStack/xeus"&gt;xeus&lt;/a&gt; and &lt;a href="https://github.com/QuantStack/xeus-python"&gt;xeus-python&lt;/a&gt; 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://www.techatbloomberg.com/"&gt;&lt;strong&gt;Bloomberg&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="about-the-author"&gt;About the Author&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/abracadabra-bringing-the-magics-to-xeus-python/images/007-0_5XdymjYwzZe-hvy8.jpg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;My name is &lt;a href="https://twitter.com/martinRenou"&gt;Martin Renou&lt;/a&gt;, I am a Scientific Software Engineer at &lt;a href="https://quantstack.net/"&gt;&lt;strong&gt;QuantStack&lt;/strong&gt;&lt;/a&gt;. Before joining QuantStack, I studied at the aerospace engineering school &lt;a href="https://www.isae-supaero.fr/en"&gt;SUPAERO&lt;/a&gt; in Toulouse, France. I also worked at Logilab in Paris, France and Enthought in Cambridge, UK. As an open-source developer at QuantStack, I work on a variety of projects, from &lt;a href="https://github.com/QuantStack/xtensor"&gt;xtensor&lt;/a&gt; and &lt;a href="https://github.com/QuantStack/xeus-python/"&gt;xeus-python&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/bqplot/bqplot"&gt;bqplot&lt;/a&gt; in Python and JavaScript/TypeScript.&lt;/p&gt;
</content><category term="IPython"/><category term="kernels"/><category term="xeus"/></entry><entry><title>Robotic Process Automation with JupyterLab</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2021/robotic-process-automation-with-jupyterlab/" rel="alternate"/><published>2021-01-18T10:36:00+00:00</published><updated>2021-01-18T10:36:00+00:00</updated><author><name>Martin Renou</name></author><id>tag:jasongrout.github.io,2021-01-18:/medium-archive/pelican/posts/2021/robotic-process-automation-with-jupyterlab/</id><summary type="html">&lt;p&gt;Introducing a new Jupyter kernel for Robot Framework&lt;/p&gt;
</summary><content type="html">&lt;p&gt;&lt;em&gt;Introducing a new Jupyter kernel for Robot Framework&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Robotic Process Automation (RPA) differs from classical automation tools in that the actions to automate can be developed by observing a user perform a task in a graphical user interface, across multiple applications.&lt;/p&gt;
&lt;p&gt;It is a means to lower the entry barrier of process automation and enable the use of tools that don’t provide a programmatic interface.&lt;/p&gt;
&lt;p&gt;Most typically, RPA developers will use a mixed approach between textual programming and performing actions manually. The resulting programs are typically called software &lt;em&gt;robots&lt;/em&gt;. Therefore, interactive computing tools like Jupyter are a natural environment for RPA, as the interactive nature of Jupyter allows for quick iterations and trial-and-errors when developing such robots.&lt;/p&gt;
&lt;p&gt;While many RPA tools are commercial software, &lt;a href="https://robotframework.org/"&gt;Robot Framework&lt;/a&gt; and the tooling developed by &lt;a href="https://robocorp.com/"&gt;Robocorp&lt;/a&gt; provide an open-source RPA programming language, with a high-level syntax, extensible with Python plugins. It has a rich ecosystem of libraries and tools that are developed as separate projects.&lt;/p&gt;
&lt;h2 id="robot-framework-and-project-jupyter"&gt;Robot Framework and Project Jupyter&lt;/h2&gt;
&lt;p&gt;Today, we are happy to announce the first release of &lt;a href="https://github.com/jupyter-xeus/xeus-robot"&gt;&lt;strong&gt;xeus-robot&lt;/strong&gt;&lt;/a&gt;, a Jupyter kernel for &lt;a href="https://robotframework.org/"&gt;Robot Framework&lt;/a&gt; based on &lt;a href="https://github.com/jupyter-xeus/xeus"&gt;xeus&lt;/a&gt;, supporting the new JupyterLab 3.0 visual debugger, auto-completion, and much more!&lt;/p&gt;
&lt;p&gt;But before we dive into xeus-robot, we should recognize the earlier work by &lt;a href="https://github.com/bollwyvl"&gt;Nick Bollweg&lt;/a&gt; and &lt;a href="https://github.com/datakurre"&gt;Asko Soukka&lt;/a&gt;, who developed two Jupyter kernels for Robot Framework, &lt;a href="https://github.com/gtri/irobotframework"&gt;irobotframework&lt;/a&gt;, and &lt;a href="https://github.com/robots-from-jupyter/robotkernel"&gt;robotkernel&lt;/a&gt;, and gave an &lt;a href="https://www.youtube.com/watch?v=rbYF_RmiAR8"&gt;amazing talk&lt;/a&gt; together at &lt;a href="https://robocon.io/"&gt;RoboCon&lt;/a&gt; in 2019!&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The motivation for us to reboot this effort with a kernel based on xeus was to enable the &lt;strong&gt;JupyterLab Visual Debugger&lt;/strong&gt; for this kernel. This requires a different concurrency model than that of ipykernel, which underlies both irobotframework and robotkernel. In the end, we were able to provide the same features and more, including e.g. code completion in Python cells, debugging etc.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="diving-into-xeus-robot"&gt;Diving into Xeus-robot&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/robotic-process-automation-with-jupyterlab/images/001-1_3HNfLnwDpXNZ6n6HPD2lXQ.webp" alt="Xeus robot logo" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/jupyter-xeus/xeus-robot"&gt;xeus-robot&lt;/a&gt; is a reboot of the already existing robotkernel, based on xeus.&lt;/p&gt;
&lt;p&gt;Like most language kernels, &lt;a href="https://github.com/jupyter-xeus/xeus-robot"&gt;xeus-robot&lt;/a&gt; supports code completion, inspection, error handling, etc. It also allows using Python cells to define custom robot keywords in Python, those Python cells support code completion as well.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Code completion in Robot framework" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/robotic-process-automation-with-jupyterlab/images/002-1_OPqkYEI78eT1dj5P6WEeXg.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Code Completion in Robot Framework&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;By using the libraries robotframework-seleniumlibrary and robotframework-seleniumscreenshots, you can even complete the selection of elements on the page you are currently testing!&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="RPA code completion" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/robotic-process-automation-with-jupyterlab/images/003-1_Z-aWN6goZH_1YcabAYj2fQ.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Code completion with an action of the user in the UI.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The &lt;code&gt;%%python&lt;/code&gt; cell magic makes it possible to extend Robotframework with Python modules in the notebook.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Robot Framework extenions in Python" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/robotic-process-automation-with-jupyterlab/images/004-1_TSiSmKHJOGE0PQ_c7alv1w.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Extending RobotFramework with Python, and code completion in Python cells&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Widget-based UIs are provided to test Robotframework “keywords”.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Robot Framework and Jupyter widgets" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/robotic-process-automation-with-jupyterlab/images/005-1_nyXQAQivNvV23xvS_1KCYQ.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Testing Robot Framework “keywords” with Jupyter widgets&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Last but not least, xeus-robot comes with full support for the JupyterLab Visual Debugger! After the xeus-python kernel, it is the second Jupyter kernel to support the Jupyter Debugger Protocol! We hope that many more will come.&lt;/p&gt;
&lt;p&gt;You can set breakpoints, step in defined keywords (the equivalent of functions), inspect variables, and see the callstack, as shown below.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="JupyterLab Visual Debugger" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/robotic-process-automation-with-jupyterlab/images/006-1_EFxI8mzCwYwnK9DB_xGxTQ.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;The JupyterLab Visual Debugger in action with Robot Framework&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="installing-xeus-robot"&gt;Installing xeus-robot&lt;/h2&gt;
&lt;p&gt;Xeus-robot is available for all platforms on conda-forge, and can be installed with conda or mamba.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mamba install xeus-robot -c conda-forge
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The &lt;code&gt;jupyterlab-robotmode&lt;/code&gt; package, which provides JupyterLab syntax highlighting for Robot Framework will also be installed as a dependency.&lt;/p&gt;
&lt;p&gt;For your conda installation, we recommend starting from &lt;strong&gt;mambaforge&lt;/strong&gt; or &lt;strong&gt;miniforge&lt;/strong&gt; which are available for download &lt;a href="https://github.com/conda-forge/miniforge"&gt;&lt;strong&gt;here&lt;/strong&gt;&lt;/a&gt;, and default to the conda-forge channel (making the &lt;code&gt;-c conda-forge&lt;/code&gt; argument unnecessary).&lt;/p&gt;
&lt;h2 id="try-it-online"&gt;Try it online&lt;/h2&gt;
&lt;p&gt;Thanks to &lt;a href="https://mybinder.org/"&gt;MyBinder&lt;/a&gt;, you can try it out without the need of installing anything on your computer. Just follow this link:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://mybinder.org/v2/gh/jupyter-xeus/xeus-robot/stable?urlpath=/lab/tree/notebooks/xrobot.ipynb"&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/robotic-process-automation-with-jupyterlab/images/007-0_TQpdhVZSAnE-XOrm.jpg" alt="&amp;quot;Launch binder&amp;quot; badge" loading="lazy" data-body-image=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="acknowledgments"&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://robocorp.com/"&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/robotic-process-automation-with-jupyterlab/images/008-1_E9XGge6uWrbmvndUoZ1Qug.webp" alt="Robocorp logo" loading="lazy" data-body-image=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The work on xeus-robot by &lt;a href="https://twitter.com/QuantStack"&gt;QuantStack&lt;/a&gt; was funded by &lt;a href="https://robocorp.com/"&gt;Robocorp&lt;/a&gt;, and is part of their initiative to create an open-source RPA ecosystem. Beyond the xeus-robot kernel, Robocorp also funds the integration of Robot Framework with &lt;a href="https://marketplace.visualstudio.com/items?itemName=robocorp.robocorp-code"&gt;Visual Studio Code&lt;/a&gt;, &lt;a href="https://rpaframework.org/"&gt;RPA Framework&lt;/a&gt;, and other development to push the Robot Framework project forward.&lt;/p&gt;
&lt;p&gt;The implementation of the debugger in xeus-robot relies on &lt;a href="https://github.com/robocorp/robotframework-lsp"&gt;robotframework-lsp&lt;/a&gt; by &lt;a href="https://twitter.com/fabiofz"&gt;Fabio Zadrozny&lt;/a&gt; and we want to thank him for his help in integrating it in xeus-robot.&lt;/p&gt;
&lt;h2 id="about-the-authors"&gt;About the authors&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/robotic-process-automation-with-jupyterlab/images/009-1_zwPmx9pH4pkXOxowHQOsuQ.jpeg" alt="Martin Renou" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Martin Renou&lt;/strong&gt; is a scientific software developer at QuantStack. He is the creator of the xeus-python and xeus-robot kernels.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/robotic-process-automation-with-jupyterlab/images/010-1_YQZupQRMB6JJfhM_byi2KA.jpeg" alt="Johan Mabille" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Johan Mabille&lt;/strong&gt; is a scientific software developer at QuantStack. He is a co-author of the xeus project, and developed the debugger extensions to xeus-python and xeus-robot. He also co-authored the front-end for the JupyterLab visual debugger.&lt;/p&gt;
</content><category term="JupyterLab"/></entry><entry><title>ipygany: Jupyter into the third dimension</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2020/ipygany-jupyter-into-the-third-dimension/" rel="alternate"/><published>2020-10-14T09:51:00+00:00</published><updated>2020-11-01T12:42:00+00:00</updated><author><name>Martin Renou</name></author><id>tag:jasongrout.github.io,2020-10-14:/medium-archive/pelican/posts/2020/ipygany-jupyter-into-the-third-dimension/</id><summary type="html">&lt;p&gt;Scientific visualization in the Jupyter Notebook&lt;/p&gt;
</summary><content type="html">&lt;p&gt;&lt;em&gt;Scientific visualization in the Jupyter notebook&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/ipygany-jupyter-into-the-third-dimension/images/001-1_IB4Bf4aEC5RXJJ1gY1zGFw.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;From Paraview to Mayavi, there are multiple solutions for data analysis on 3D meshes on the desktop. Most of these tools provide high-level APIs that can be driven with a scripting language like Python. For example, one could control Paraview from a Jupyter Notebook. But this is not ideal as it relies on a desktop application for the rendering, which prevents using tools like &lt;a href="https://mybinder.org/"&gt;MyBinder&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Nowadays, most scientists run their computation on the cloud, and they need tools for interacting and analyzing with their data.&lt;/p&gt;
&lt;p&gt;There are already some solutions that are more integrated into Jupyter:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/maartenbreddels/ipyvolume"&gt;ipyvolume&lt;/a&gt; is a WebGL-based 3D plotting library for Jupyter. It has many features including multi-volume rendering.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/K3D-tools/K3D-jupyter"&gt;K3D-jupyter&lt;/a&gt; helps you create 3D plots backed by WebGL with high-level API (surfaces, isosurfaces, voxels, mesh, cloud points, vtk objects, volume renderer, colormaps, etc).&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/InsightSoftwareConsortium/itkwidgets"&gt;itkwidgets&lt;/a&gt; is a tool for visualizing images, point sets, and meshes in 2D and 3D in Jupyter. It works by doing the rendering on the back-end and by streaming the frames to the front-end.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Kitware/ipyvtk-simple"&gt;ipyvtk-simple&lt;/a&gt; is a Jupyter library for interfacing with any Python vtkRenderWindow. It relies on &lt;a href="https://github.com/martinRenou/ipycanvas"&gt;ipycanvas&lt;/a&gt; for streaming the frames to the front-end.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We needed a Paraview-like experience for Jupyter. We could provide this experience by relying on the vtk library in Python, but this means that every time you want to apply a new filter like warp-by-scalar, the Python back-end needs to send the filtered mesh to the front-end for display. This is far from ideal, as it might be hundreds of megabytes to download for every roundtrip to the back-end.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;itkwidgets&lt;/code&gt; and &lt;code&gt;ipyvtk-simple&lt;/code&gt; fix this issue by not sending the mesh to the page, instead, the rendering is done on the back-end and streamed to the user. This solution is, in a way, similar to using Paraview using a vnc solution. It works fine as long as you have a fast and low latency connection to the Jupyter server, and this solution scales properly with the mesh size, as the amount of data sent to the user is the same whether you analyze a fine or a coarse mesh.&lt;/p&gt;
&lt;p&gt;Solutions like ipyvolume and K3D-jupyter can be backed by the Python vtk library (or by &lt;a href="https://github.com/pyvista/pyvista"&gt;PyVista&lt;/a&gt;), but again, this means doing the mesh filtering in Python and sending the filtered meshes to the page for every change.&lt;/p&gt;
&lt;p&gt;Today we are proud to announce &lt;a href="https://github.com/QuantStack/ipygany"&gt;&lt;strong&gt;ipygany&lt;/strong&gt;&lt;/a&gt;! ipygany is a &lt;strong&gt;Jupyter widget&lt;/strong&gt; that aims at bringing a &lt;strong&gt;Paraview-like experience to the webpage&lt;/strong&gt;. With ipygany, you only send your mesh data to the front-end once, and effects such as mesh warping, contour computation, threshold filtering are directly done in the front-end and most-typically with the GPU.&lt;/p&gt;
&lt;h3 id="introducing-ipygany"&gt;Introducing ipygany&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/QuantStack/ipygany"&gt;ipygany&lt;/a&gt; is a new interactive widgets library that allows you to visualize and analyze volumetric data in the Jupyter Notebook.&lt;/p&gt;
&lt;p&gt;Whether your data comes from a VTK file or NumPy arrays, ipygany allows you to dynamically load your data, display them in the Notebook, and apply different kinds of visual effects on it.&lt;/p&gt;
&lt;p&gt;ipygany provides a set of effects inspired by Paraview:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;IsoColor&lt;/strong&gt;: apply color-mapping to your mesh.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Warp&lt;/strong&gt;: deform your mesh given a 3-D input data (e.g. displacement data on a beam)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WarpByScalar&lt;/strong&gt;: deform your mesh given a 1-D input data (e.g. terrain elevation)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Threshold&lt;/strong&gt;: only visualize mesh parts inside a range of data (e.g. &lt;em&gt;222 K≤ temperature ≤ 240 K&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IsoSurface:&lt;/strong&gt; only visualize the surface where the mesh respects a data value (e.g. &lt;em&gt;pressure == 3 bar&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;Glyph effects like &lt;strong&gt;PointCloud&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Water&lt;/strong&gt; visualization&lt;/li&gt;
&lt;li&gt;And there’s more to come!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Most of those effects are computed on the &lt;strong&gt;GPU&lt;/strong&gt; &lt;strong&gt;only&lt;/strong&gt;! Which makes them &lt;strong&gt;really fast&lt;/strong&gt;. For example, changing the deformation factor of the Warp effect only sends one floating-point number to the GPU, and the GPU will know how to re-render the mesh (using shaders) according to the new factor value, this update is virtually &lt;strong&gt;instantaneous&lt;/strong&gt;. Changing the warp factor value is technically as fast as moving the camera position, it only requires rendering a new frame.&lt;/p&gt;
&lt;p&gt;We strive to use efficient algorithms for better performances, especially for computation that cannot be done with the GPU.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="WarpByScalar: completely computed on the GPU" src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/ipygany-jupyter-into-the-third-dimension/images/002-1_44MjnyyY7En1fSyg3ZjUbg.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;WarpByScalar: completely computed on the GPU&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Effects can be easily combined for highlighting important parts in your mesh. For example, you can easily cut your mesh using the Threshold effect then apply a Warp effect for visualizing a deformation on the result.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Combining a Threshold with a Warp" src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/ipygany-jupyter-into-the-third-dimension/images/003-1_Y0vnsdwZ80L651FIcu9SUA.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Combining a Threshold with a Warp&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;All those effects are interactive widgets, they are stateful objects that you can dynamically update from Python or using widgets like sliders, text inputs, etc.&lt;/p&gt;
&lt;p&gt;Your mesh is also an interactive widget: &lt;strong&gt;you can dynamically update your data&lt;/strong&gt;, which is very useful when your data changes through time.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Visualizing an animation from two viewpoints" src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/ipygany-jupyter-into-the-third-dimension/images/004-1_hAGP5bJQ-2xN7w0dLprXig.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Visualizing an animation from two viewpoints&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;If you work with fluid dynamics, we even provide refractive/reflective effects and water caustics computation for nice looking visualization:&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="If you do Water simulation, ipygany also allows you to render you water with reflective/refractive effects and it even computes light caustics!" src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/ipygany-jupyter-into-the-third-dimension/images/005-1_au2ruI66bs1gx3AY3qtvlQ.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;If you do Water simulation, ipygany also allows you to render you water with reflective/refractive effects and it even computes light caustics!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="installation"&gt;Installation&lt;/h3&gt;
&lt;p&gt;You can install ipygany with conda or &lt;a href="https://github.com/mamba-org/mamba"&gt;mamba&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mamba install -c conda-forge ipygany
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Or&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;conda install -c conda-forge ipygany
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Or you can install it with pip:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pip install ipygany
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you use JupyterLab you’ll need to install the labextension (not needed with the coming JupyterLab v3):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;jupyter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;labextension&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;@jupyter&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;widgets&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;jupyterlab&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;manager&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ipygany&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="documentation"&gt;Documentation&lt;/h3&gt;
&lt;p&gt;You can find the documentation following this link:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://ipygany.readthedocs.io/"&gt;https://ipygany.readthedocs.io&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="try-it-online"&gt;Try it online&lt;/h3&gt;
&lt;p&gt;Thanks to &lt;a href="https://mybinder.org/"&gt;MyBinder&lt;/a&gt;, you can try it out without the need of installing anything on your computer. Just follow this link:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://mybinder.org/v2/gh/QuantStack/ipygany/stable?filepath=examples"&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/ipygany-jupyter-into-the-third-dimension/images/006-1_T9WU53MjGAIX6i9XYsnL1w.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="acknowledgement"&gt;Acknowledgement&lt;/h3&gt;
&lt;p&gt;This work is led at &lt;a href="https://twitter.com/QuantStack"&gt;QuantStack&lt;/a&gt; and founded by &lt;a href="https://www.erdc.usace.army.mil/About/"&gt;ERDC&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="about-the-author"&gt;About the Author&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/ipygany-jupyter-into-the-third-dimension/images/007-0_kREnDs33Zid5X4QE.jpg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;My name is &lt;a href="https://twitter.com/martinRenou"&gt;Martin Renou&lt;/a&gt;, I am a Scientific Software Engineer at &lt;a href="https://quantstack.net/"&gt;&lt;strong&gt;QuantStack&lt;/strong&gt;&lt;/a&gt;. Before joining QuantStack, I studied at the aerospace engineering school &lt;a href="https://www.isae-supaero.fr/en"&gt;SUPAERO&lt;/a&gt; in Toulouse, France. I also worked at Logilab in Paris, France and Enthought in Cambridge, UK. As an open-source developer at QuantStack, I work on a variety of projects, from &lt;a href="https://github.com/QuantStack/xtensor"&gt;xtensor&lt;/a&gt; and &lt;a href="https://github.com/QuantStack/xeus-python/"&gt;xeus-python&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/bqplot/bqplot"&gt;bqplot&lt;/a&gt; in Python and Javascript/TypeScript.&lt;/p&gt;
</content><category term="visualization"/></entry><entry><title>ipycanvas: A Python Canvas for Jupyter</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2019/ipycanvas-a-python-canvas-for-jupyter/" rel="alternate"/><published>2019-10-25T12:48:00+00:00</published><updated>2022-04-08T08:29:00+00:00</updated><author><name>Martin Renou</name></author><id>tag:jasongrout.github.io,2019-10-25:/medium-archive/pelican/posts/2019/ipycanvas-a-python-canvas-for-jupyter/</id><summary type="html">&lt;p&gt;As you may already know, the Jupyter Notebook and JupyterLab are Browser-based applications. Browsers are incredibly powerful, they allow…&lt;/p&gt;
</summary><content type="html">&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/ipycanvas-a-python-canvas-for-jupyter/images/001-1_LHrtcPJMCWVMgsvNR6tR6w.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;As you may already know, the Jupyter Notebook and JupyterLab are Browser-based applications. &lt;strong&gt;Browsers are incredibly powerful&lt;/strong&gt;, they allow you to swap rich and interactive graphical interfaces containing buttons, sliders, maps, 2D and 3D plots and even video games in your webpages!&lt;/p&gt;
&lt;p&gt;All this power is readily made available to the Python ecosystem by &lt;strong&gt;Jupyter interactive widgets&lt;/strong&gt; libraries. Whether you want to create simple controls using &lt;a href="https://github.com/jupyter-widgets/ipywidgets/"&gt;ipywidgets&lt;/a&gt;, display interactive data on a 2D map with &lt;a href="https://github.com/jupyter-widgets/ipyleaflet"&gt;ipyleaflet&lt;/a&gt;, plot 2D data using &lt;a href="https://github.com/bloomberg/bqplot/"&gt;bqplot&lt;/a&gt; or plot volumic data with &lt;a href="https://github.com/maartenbreddels/ipyvolume"&gt;ipyvolume&lt;/a&gt;, all of this is made possible thanks to the &lt;strong&gt;open-source&lt;/strong&gt; community.&lt;/p&gt;
&lt;p&gt;One powerful tool in the Browser is the &lt;strong&gt;HTML5 Canvas&lt;/strong&gt; element, it allows you to draw 2D or 3D graphics on the webpage. There are two available APIs for the Canvas, the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API"&gt;Canvas API&lt;/a&gt; which focuses on 2D graphics, and the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API"&gt;WebGL API&lt;/a&gt; which uses hardware acceleration for 3D graphics.&lt;/p&gt;
&lt;p&gt;After some discussions with my work colleague &lt;a href="https://twitter.com/wuoulf"&gt;Wolf Vollprecht&lt;/a&gt;, we came to the conclusion that it would be a great idea to directly expose the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API"&gt;Canvas API&lt;/a&gt; to IPython, without making any modification to it. And that’s how we came up with &lt;a href="https://github.com/martinRenou/ipycanvas"&gt;ipycanvas&lt;/a&gt;!&lt;/p&gt;
&lt;h2 id="ipycanvas-exposing-the-canvas-api-to-ipython"&gt;ipycanvas: Exposing the Canvas API to IPython&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/ipycanvas-a-python-canvas-for-jupyter/images/002-1_-Q6-aW2mJjMfsxmieaGomw.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/martinRenou/ipycanvas"&gt;ipycanvas&lt;/a&gt; exposes the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API"&gt;Canvas API&lt;/a&gt; to IPython, making it possible to &lt;strong&gt;draw anything you want on a Jupyter Notebook&lt;/strong&gt; directly in Python! Anything is possible, you can draw custom heatmaps from NumPy arrays, you can implement your own 2D video-game, or you can create yet another IPython plotting library!&lt;/p&gt;
&lt;p&gt;ipycanvas provides a low-level API that allows you to draw simple primitives like lines, polygons, arcs, text, images… Once you’re familiar with the API, you’re only limited by your own imagination!&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/ipycanvas-a-python-canvas-for-jupyter/images/003-1_80VJXjNns82TZUcLURNplg.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Draw image from NumPy array (left), implementation of the Game Of Life (right)" src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/ipycanvas-a-python-canvas-for-jupyter/images/004-1_jjBIO9JslYo7LfIyTpfjxQ.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Draw image from NumPy array (left), implementation of the Game Of Life (right)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/ipycanvas-a-python-canvas-for-jupyter/images/005-1_QeQxhuDRL1AwXokdsQ2fhQ.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Draw millions of particles (left), draw custom sprites (right)" src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/ipycanvas-a-python-canvas-for-jupyter/images/006-1_6SqrCHH4YsJUY4nrDTU7fw.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Draw millions of particles (left), draw custom sprites (right)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/ipycanvas-a-python-canvas-for-jupyter/images/007-1_PtctDM0B6OT604tRFV2WtA.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Make your own plotting library for Jupyter fully in Python!" src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/ipycanvas-a-python-canvas-for-jupyter/images/008-1_rCvw3tMgRVixKn_wUAHEAQ.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Make your own plotting library for Jupyter fully in Python!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Using &lt;a href="https://twitter.com/astronomatty"&gt;Matt Craig&lt;/a&gt;’s &lt;a href="https://github.com/mwcraig/ipyevents"&gt;ipyevents&lt;/a&gt; library, you can add mouse and key events to the Canvas and react to user interactions.&lt;/p&gt;
&lt;p&gt;If you have a GamePad around, you can also use the built-in &lt;a href="https://ipywidgets.readthedocs.io/en/stable/examples/Widget%20List.html#Controller"&gt;Controller&lt;/a&gt; widget and make your own video-game in a Jupyter Notebook!&lt;/p&gt;
&lt;h3 id="documentation"&gt;Documentation&lt;/h3&gt;
&lt;p&gt;Check-out the ipycanvas documentation for more information: &lt;a href="https://ipycanvas.readthedocs.io/en/latest/?badge=latest"&gt;ipycanvas.readthedocs.io&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="github-repository"&gt;Github repository&lt;/h3&gt;
&lt;p&gt;Give it a star on Github if you like it! &lt;a href="https://github.com/martinRenou/ipycanvas/"&gt;github.com/martinRenou/ipycanvas&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="try-it-online"&gt;Try it online!&lt;/h3&gt;
&lt;p&gt;You can try it without the need of installing anything on your computer just by clicking on the image below:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://mybinder.org/v2/gh/martinRenou/ipycanvas/stable?filepath=examples"&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/ipycanvas-a-python-canvas-for-jupyter/images/009-0_gt0KurDRJ50ZIIvf.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="installation"&gt;Installation&lt;/h3&gt;
&lt;p&gt;Note that you first need to have Jupyter installed on your computer. You can install ipycanvas using pip:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pip install ipycanvas&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Or using conda:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;conda install -c conda-forge ipycanvas&lt;/code&gt;&lt;/p&gt;
&lt;h2 id="about-the-author"&gt;About the author&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://twitter.com/martinRenou"&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/ipycanvas-a-python-canvas-for-jupyter/images/010-1_GH0Cfo-a2zZuJFrJyKrebA.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;My name is &lt;a href="https://twitter.com/martinRenou"&gt;Martin Renou&lt;/a&gt;, I am a Scientific Software Engineer at &lt;a href="http://quantstack.net/"&gt;QuantStack&lt;/a&gt;. Before joining &lt;a href="http://quantstack.net/"&gt;QuantStack&lt;/a&gt;, I studied at the aerospace engineering school &lt;a href="https://www.isae-supaero.fr/en"&gt;SUPAERO&lt;/a&gt; in Toulouse, France. I also worked at Logilab in Paris and Enthought in Cambridge, UK. As an open-source developer at QuantStack, I worked on a variety of projects, from &lt;a href="https://github.com/QuantStack/xtensor"&gt;xtensor&lt;/a&gt; and &lt;a href="https://github.com/QuantStack/xeus-python/"&gt;xeus-python&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="visualization"/><category term="widgets"/></entry><entry><title>A new Python kernel for Jupyter</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2019/a-new-python-kernel-for-jupyter/" rel="alternate"/><published>2019-01-09T09:16:00+00:00</published><updated>2019-09-30T07:04:00+00:00</updated><author><name>Martin Renou</name></author><id>tag:jasongrout.github.io,2019-01-09:/medium-archive/pelican/posts/2019/a-new-python-kernel-for-jupyter/</id><summary type="html">&lt;p&gt;Project Jupyter aims at providing a consistent set of tools for interactive computing workflows across multiple programming languages…&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Project Jupyter aims at providing a consistent set of tools for interactive computing workflows across multiple programming languages. Jupyter projects are popular at all stages of a research project from the exploration phase to the communication of results and teaching.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/a-new-python-kernel-for-jupyter/images/001-1_ySP_XtCM_MMBawtlOOixag.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;br&gt;
&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/a-new-python-kernel-for-jupyter/images/002-1_u5Y0cs48UCc5bmGXP2rTIA.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;The flagship project of Jupyter, the Notebook, and its modernized version, JupyterLab are web applications allowing the creation of documents including prose, executable code, and interactive visualizations.&lt;/p&gt;
&lt;p&gt;The kernel is the part of the backend responsible for executing code written by the user in the web application. For example, in the case of a Python notebook, execution of the code is typically handled by &lt;a href="https://github.com/ipython/ipykernel"&gt;ipykernel&lt;/a&gt;, the reference implementation.&lt;/p&gt;
&lt;h2 id="history"&gt;History&lt;/h2&gt;
&lt;p&gt;Initially, the &lt;a href="https://ipython.org/"&gt;IPython&lt;/a&gt; project included everything from the notebook web application to the kernel and server implementation. Later on, the language-agnostic parts (the notebook format, messaging protocol, qtconsole, notebook web application) were split into separate projects with a clearer scope, together forming &lt;em&gt;Project Jupyter&lt;/em&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="The Big Split(TM) of IPython" src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/a-new-python-kernel-for-jupyter/images/003-1_PlpiXwbaiHo8VtTqcFyzGA.jpeg" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;The Big Split(TM) of IPython&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Splitting &lt;a href="https://ipython.org/"&gt;IPython&lt;/a&gt; into multiple packages was a good decision in that it brought a clear separation of concerns between the projects. The &lt;a href="https://github.com/ipython/ipykernel"&gt;ipykernel&lt;/a&gt; project was elected as the reference implementation of the Jupyter kernel protocol.&lt;/p&gt;
&lt;p&gt;This came at a cost since &lt;a href="https://github.com/ipython/ipykernel"&gt;ipykernel&lt;/a&gt; brought all the history and technical debt of &lt;a href="https://ipython.org/"&gt;IPython&lt;/a&gt; with it. Besides, Python is not a natural language for a base implementation. As a result, R and Julia kernels don’t use the reference implementation but use their own implementation of the protocol.&lt;/p&gt;
&lt;p&gt;Furthermore, the standard implementation of the Jupyter Interactive Widgets lies in the Python package &lt;a href="https://github.com/jupyter-widgets/ipywidgets"&gt;ipywidgets&lt;/a&gt;. That means that once you, as a kernel developer, implemented the Jupyter kernel protocol, you would still need to make your own backend for the interactive widgets if you want widgets support (and you should want it, honestly…).&lt;/p&gt;
&lt;p&gt;To prevent this useless duplication of effort, which harms sustainability, we set ourselves to implement a solid reusable implementation of the Jupyter kernel protocol, &lt;a href="https://github.com/QuantStack/xeus"&gt;xeus&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="c-implementation-of-the-kernel-protocol"&gt;C++ implementation of the kernel protocol&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/a-new-python-kernel-for-jupyter/images/004-1_OWq9aDu1wOvYig3AalBvFg.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/QuantStack/xeus"&gt;Xeus&lt;/a&gt; is a C++ implementation of the Jupyter kernel protocol. It is not a kernel by itself but a library that helps kernel authoring. &lt;a href="https://github.com/QuantStack/xeus"&gt;Xeus&lt;/a&gt; is very helpful when developing a kernel for a language that has a C or a C++API (Python, Lua, SQL, etc.). It takes the cumbersome task of implementing the &lt;a href="https://jupyter-client.readthedocs.io/en/stable/messaging.html"&gt;Jupyter messaging protocol&lt;/a&gt; for you so you just can focus on the core interpreter tasks: executing code, inspecting, completing, etc.&lt;/p&gt;
&lt;p&gt;C++ is a good choice for a standard implementation of the protocol, it is a common denominator of most of the languages out there, it has a massive developer community and is widely adopted in the industry for performance middleware applications.&lt;/p&gt;
&lt;p&gt;With &lt;a href="https://github.com/QuantStack/xeus"&gt;xeus&lt;/a&gt;, it is also very easy to reimplement core logic (server, kernel, history management etc.), if need be, by simply inheriting from &lt;a href="https://github.com/QuantStack/xeus"&gt;xeus&lt;/a&gt; library classes.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/QuantStack/xeus"&gt;Xeus&lt;/a&gt; is already known for being used as a base for the C++ kernel &lt;a href="https://github.com/QuantStack/xeus-cling"&gt;xeus-cling&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="a-xeus-based-c-kernel"&gt;A xeus-based C++ Kernel&lt;/h2&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/a-new-python-kernel-for-jupyter/images/005-1_vrE1i_8405140XOHfx77LA.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/QuantStack/xeus-cling"&gt;Xeus-cling&lt;/a&gt; is a &lt;a href="https://github.com/QuantStack/xeus"&gt;xeus&lt;/a&gt;-based C++ kernel for the Jupyter Notebook. It’s very useful for teaching or learning C++. C++ has never been this interactive, thanks to the combined power of Jupyter, &lt;a href="https://github.com/QuantStack/xeus"&gt;xeus&lt;/a&gt;, and &lt;a href="https://github.com/root-project/cling"&gt;cling&lt;/a&gt;. And even more impressive than executing interpreted C++, it supports interactive widgets, thanks to the &lt;a href="https://github.com/QuantStack/xwidgets"&gt;xwidgets&lt;/a&gt; project.&lt;/p&gt;
&lt;p&gt;Just like &lt;a href="https://github.com/QuantStack/xeus"&gt;xeus&lt;/a&gt; is a C++ implementation of the Jupyter kernel protocol, &lt;a href="https://github.com/QuantStack/xwidgets"&gt;xwidgets&lt;/a&gt; is a C++ implementation of the Jupyter Interactive Widgets protocol, and it can be used as a base for other implementations.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/a-new-python-kernel-for-jupyter/images/006-1_kA8toRCXwwnPmrsSIT7vhw.webp" alt="" loading="lazy" data-body-image=""&gt;&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/QuantStack/xeus-cling/stable?filepath=notebooks/xcpp.ipynb"&gt;&lt;strong&gt;this link&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Interactive C++ in the Jupyter Notebook" src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/a-new-python-kernel-for-jupyter/images/007-1_OJYy6QP8HSEPUQHhyyCOcQ.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Interactive C++ in the Jupyter Notebook&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="a-xeus-based-python-kernel"&gt;A xeus-based Python kernel&lt;/h2&gt;
&lt;p&gt;Today, I am pleased to announce a new Python kernel based on &lt;a href="https://github.com/QuantStack/xeus"&gt;xeus&lt;/a&gt;: &lt;a href="https://github.com/QuantStack/xeus-python"&gt;xeus-python&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/a-new-python-kernel-for-jupyter/images/008-1_YIXmS4xfX9MxQ6dHZLU8-g.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/QuantStack/xeus-python"&gt;Xeus-python&lt;/a&gt; supports error formatting, rich display, interactive widgets, input requests, code completion, code inspection, etc.&lt;/p&gt;
&lt;p&gt;Thanks to &lt;a href="https://github.com/QuantStack/xeus"&gt;xeus&lt;/a&gt; and &lt;a href="https://github.com/pybind/pybind11"&gt;pybind11&lt;/a&gt;, it was very straightforward to have a first simple version of a Python kernel written in C++. It took a couple of months to have the features listed above, with a relatively small amount of code (&amp;lt; 3000 lines of C++) and a good coverage of &lt;a href="https://github.com/ipython/ipykernel"&gt;ipykernel&lt;/a&gt;’s features.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Simple code execution" src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/a-new-python-kernel-for-jupyter/images/009-1_2hHrN4ucrKKv68BJU9hRXQ.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Simple code execution&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img alt="Error formatting" src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/a-new-python-kernel-for-jupyter/images/010-1_ewhjr2dkosifi7Qky1A83g.gif" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Error formatting&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img alt="Code completion" src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/a-new-python-kernel-for-jupyter/images/011-1_LgaJ9RcNs0YZK7qaySX4NQ.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Code completion&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure&gt;
&lt;img alt="Ipywidgets support" src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/a-new-python-kernel-for-jupyter/images/012-1_3XxIdWaB7HRmRDY_PzOGaQ.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Ipywidgets support&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Just like with &lt;a href="https://github.com/QuantStack/xeus-cling"&gt;xeus-cling&lt;/a&gt;, you can try it online without the need of installing anything on your computer following &lt;a href="https://mybinder.org/v2/gh/QuantStack/xeus-python/stable?filepath=notebooks/xeus-python.ipynb"&gt;&lt;strong&gt;this link&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="why-another-python-kernel"&gt;Why another Python kernel?&lt;/h2&gt;
&lt;p&gt;Obviously, &lt;a href="https://github.com/QuantStack/xeus-python"&gt;xeus-python&lt;/a&gt; does not cover 100% of the features of &lt;a href="https://github.com/ipython/ipykernel"&gt;ipykernel&lt;/a&gt;. For examples, &lt;a href="https://ipython.org/"&gt;IPython&lt;/a&gt; magics are not supported yet by &lt;a href="https://github.com/QuantStack/xeus-python"&gt;xeus-python&lt;/a&gt;. However:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/QuantStack/xeus-python"&gt;xeus-python&lt;/a&gt; is a lot lighter than &lt;a href="https://github.com/ipython/ipykernel"&gt;ipykernel&lt;/a&gt; and &lt;a href="https://ipython.org/"&gt;IPython&lt;/a&gt; combined, which makes it a lot easier to implement new features on top of it. Our next goal is to augment the protocol to implement a Python debugger in JupyterLab.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/QuantStack/xeus"&gt;xeus&lt;/a&gt;-based kernels are more versatile in that one can overload e.g. the concurrency model. This is something that &lt;a href="https://www.kitware.com/"&gt;Kitware&lt;/a&gt;’s &lt;a href="https://github.com/Slicer/SlicerJupyter"&gt;SlicerJupyter&lt;/a&gt; project takes advantage of to integrate with the Qt event loop of their Qt-based desktop application.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="acknowledgments"&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;The development of &lt;a href="https://github.com/QuantStack/xeus"&gt;xeus&lt;/a&gt;, &lt;a href="https://github.com/QuantStack/xwidgets"&gt;xwidgets&lt;/a&gt;, &lt;a href="https://github.com/QuantStack/xeus-python"&gt;xeus-python&lt;/a&gt;, and related packages are led by &lt;a href="https://twitter.com/QuantStack"&gt;QuantStack&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://quantstack.net/"&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/a-new-python-kernel-for-jupyter/images/013-1_1YuyD-AQ0fzVOStuxhChWw.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This development is sponsored by &lt;a href="https://www.techatbloomberg.com/"&gt;&lt;strong&gt;Bloomberg&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="about-the-author"&gt;About the Author&lt;/h2&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="http://quantstack.net/"&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="C++"/><category term="kernels"/></entry><entry><title>Interpreted C++ for GIS with Jupyter</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2018/interpreted-c-for-gis-with-jupyter/" rel="alternate"/><published>2018-04-24T08:35:00+00:00</published><updated>2019-09-30T07:04:00+00:00</updated><author><name>Martin Renou</name></author><id>tag:jasongrout.github.io,2018-04-24:/medium-archive/pelican/posts/2018/interpreted-c-for-gis-with-jupyter/</id><summary type="html">&lt;p&gt;The recent release of the Jupyter kernel for C++, based on the Cling interpreter enabled a number of new workflows for the users of the C++…&lt;/p&gt;
</summary><content type="html">&lt;figure&gt;
&lt;img alt="A live interactive map in a C++ Jupyter notebook" src="https://jasongrout.github.io/medium-archive/pelican/posts/2018/interpreted-c-for-gis-with-jupyter/images/001-1_FzUw4j635uJgWHZzc8_QiQ.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;A live interactive map in a C++ Jupyter notebook&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The &lt;a href="/posts/2017/interactive-workflows-for-c-with-jupyter/"&gt;recent release&lt;/a&gt; of the Jupyter kernel for C++, based on the Cling interpreter enabled a number of new workflows for the users of the C++ programming language.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2018/interpreted-c-for-gis-with-jupyter/images/002-1_vrE1i_8405140XOHfx77LA.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;Features of the &lt;a href="https://github.com/QuantStack/xeus-cling"&gt;xeus-cling&lt;/a&gt; C++ kernel for Project Jupyter include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Showing quick-help pages for functions and classes of the STL and user-defined types, by prefixing them with a question mark:&lt;/em&gt;&lt;br&gt;
For example, typing &lt;code&gt;?std::vector&lt;/code&gt; results in a pager displaying the page from &lt;a href="http://en.cppreference.com/w/"&gt;cppreference&lt;/a&gt; on &lt;code&gt;std::vector&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
&lt;img alt="Quick-help page for classes and functions of the STL" src="https://jasongrout.github.io/medium-archive/pelican/posts/2018/interpreted-c-for-gis-with-jupyter/images/003-1_B77yBeBtyeIs3CqA2jlxKg.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Quick-help page for classes and functions of the STL&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Making use of the rich display features of the Jupyter stack, for user-defined types.&lt;/em&gt;&lt;br&gt;
This can be enabled simply by overloading &lt;code&gt;mime_bundle_repr&lt;/code&gt; in the namespace of the class for which we wish to have a rich representation in the front-end. The overload is picked up by the display system through argument-dependent lookup (ADL).&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
&lt;img alt="Using Jupyter’s rich display mechanism in C++" src="https://jasongrout.github.io/medium-archive/pelican/posts/2018/interpreted-c-for-gis-with-jupyter/images/004-1_GZkL0WWGqeuBDrs-INUkgg.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Using Jupyter’s rich display mechanism in C++&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Another aspect of the newly released C++ kernel is the implementation of the Jupyter widgets protocol, enabling bi-directional communication between the front-end and the kernel.&lt;/em&gt;The &lt;a href="https://github.com/QuantStack/xwidgets/"&gt;xwidgets&lt;/a&gt; package, built upon xeus provides a complete implementation of the protocol, together with the implementation of most of the controls available in the reference &lt;a href="https://github.com/jupyter-widgets/ipywidgets"&gt;ipywidgets&lt;/a&gt; Python package.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
&lt;img alt="Bidirectional communication with the front-end using Jupyter interactive widgets" src="https://jasongrout.github.io/medium-archive/pelican/posts/2018/interpreted-c-for-gis-with-jupyter/images/005-1_GDwfwdQyqprIcHbXCCkDhA.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Bidirectional communication with the front-end using Jupyter interactive widgets&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;More than a limited set of base controls, Jupyter widgets are a framework upon which one can build arbitrarily complex interactions. A large number of interactive widget libraries has been built upon ipywidgets. Popular examples include &lt;a href="https://github.com/jupyter-widgets/pythreejs"&gt;pythreejs&lt;/a&gt; (a Jupyter-threejs bridge), &lt;a href="https://github.com/bloomberg/bqplot"&gt;bqplot&lt;/a&gt; (an interactive plotting library for Jupyter), and &lt;a href="https://github.com/jupyter-widgets/ipyleaflet"&gt;ipyleaflet&lt;/a&gt; (a Jupyter-leafletjs bridge) allowing rich interactive maps in the Jupyter notebook.&lt;/p&gt;
&lt;p&gt;A common trait of most of these packages is that most of the logic is implemented in the front-end, while the back-end only involves synchronization of data attributes.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A fully-specified communication protocol and a thin back-end architecture facilitate the job of kernel authors willing to bring the power of these visualization libraries to their language of choice.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Hence, we have taken on the endeavor of providing a C++ implementation of the most popular Jupyter interactive widget libraries. These packages can be used in the C++ kernel, as well as in compiled application making use of the Jupyter kernel protocol.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2018/interpreted-c-for-gis-with-jupyter/images/006-1_U88dDupn4NP1MVVvE30Twg.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;Today, we are proud to announce the first release of &lt;code&gt;xleaflet&lt;/code&gt;, the C++ counterpart to the popular &lt;code&gt;ipyleaflet&lt;/code&gt; package, and which makes use of the same front-end component.&lt;/p&gt;
&lt;p&gt;You can get started by simply creating a map inline in the Jupyter notebook.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Specifying a center location and zoom level&lt;/li&gt;
&lt;li&gt;Specifying the tile layers to be displayed among the predefined base maps&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
&lt;img alt="A simple map with a specified center and zoom level, displaying the default tiles" src="https://jasongrout.github.io/medium-archive/pelican/posts/2018/interpreted-c-for-gis-with-jupyter/images/007-1_BcnHhEfFYFPgBdQ6eyeKrA.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;A simple map with a specified center and zoom level, displaying the default tiles&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;A number of other attributes can be set in the map widget. To mimic named parameters, all widgets of &lt;code&gt;xwidgets&lt;/code&gt; and &lt;code&gt;xleaflet&lt;/code&gt; are provided with a generator class which can be used to initialize attributes using method-chaining syntax.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Making use of the generator class to specify any number of attributes of the map upon construction" src="https://jasongrout.github.io/medium-archive/pelican/posts/2018/interpreted-c-for-gis-with-jupyter/images/001-1_FzUw4j635uJgWHZzc8_QiQ.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Making use of the generator class to specify any number of attributes of the map upon construction&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;In addition to the base map feature, a broad number of features of the leaflet JavaScript library are exposed to the C++ backend directly. This includes markers, marker clusters, image overlays, a variety of controls.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Using the marker widget" src="https://jasongrout.github.io/medium-archive/pelican/posts/2018/interpreted-c-for-gis-with-jupyter/images/008-1_BA8-dMRaOf4ikrYqBLnIjA.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Using the marker widget&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Whenever an attribute of a widget is modified in the front-end or in the back-end, the other side will properly reflect the data change.&lt;/p&gt;
&lt;p&gt;For example, setting &lt;code&gt;marker.location&lt;/code&gt; to a new value in the previous example will actually move the marker on the map. Reversely, if the &lt;code&gt;draggable&lt;/code&gt; attribute was set to &lt;code&gt;true&lt;/code&gt;, whenever the marker position changes in the front-end, the value is reflected in the C++ model.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Observer on the marker position" src="https://jasongrout.github.io/medium-archive/pelican/posts/2018/interpreted-c-for-gis-with-jupyter/images/009-1_Acd0sgShjoe40M-Ust-aKQ.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Observer on the marker position&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Another example is the support of the GeoJSON format, which allows one to load a JSON file locally and display its content on the map.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Support for the GeoJSON format" src="https://jasongrout.github.io/medium-archive/pelican/posts/2018/interpreted-c-for-gis-with-jupyter/images/010-1_ok5lH9V9NUwxMy-I5sey8A.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Support for the GeoJSON format&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;blockquote&gt;
&lt;p&gt;The bidirectional communication between the front-end and the C++ back-end makes it easier for the end user to create interactive web applications without having to write any JavaScript.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Using the rich features of xleaflet, one can start building fully-fledged GIS application in C++.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2018/interpreted-c-for-gis-with-jupyter/images/011-1_E2blHOSA9Gah1DZe1t8tKA.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;If you are interested in trying xleaflet right now in your web browser, we provided a &lt;a href="https://mybinder.org/"&gt;binder&lt;/a&gt; for you.&lt;/p&gt;
&lt;p&gt;Simply click on the following binder link and start playing with interactive GIS in C++ in your web browser:&lt;/p&gt;
&lt;figure&gt;
&lt;a href="https://mybinder.org/v2/gh/QuantStack/xleaflet/0.2.0?filepath=notebooks"&gt;&lt;img alt="Click on the image to launch the live demo." src="https://jasongrout.github.io/medium-archive/pelican/posts/2018/interpreted-c-for-gis-with-jupyter/images/012-1_DodrT-K2jBSmbAbEhmfbEg.webp" loading="lazy" data-body-image=""&gt;&lt;/a&gt;
&lt;figcaption&gt;Click on the image to launch the live demo.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Check out the &lt;a href="http://xleaflet.readthedocs.io"&gt;documentation&lt;/a&gt; for more detailed information about xleaflet.&lt;/p&gt;
&lt;h3 id="aknowledgements"&gt;Aknowledgements&lt;/h3&gt;
&lt;p&gt;The software presented in this post was built upon the work of a large number of people including the &lt;strong&gt;Jupyter&lt;/strong&gt; team, the &lt;strong&gt;Cling&lt;/strong&gt; developers, the developers of &lt;strong&gt;xeus&lt;/strong&gt; and &lt;strong&gt;xwidgets&lt;/strong&gt;, and the developers of &lt;a href="http://leafletjs.com/"&gt;&lt;strong&gt;leafletjs&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We are especially grateful to &lt;a href="https://twitter.com/SylvainCorlay"&gt;Sylvain Corlay&lt;/a&gt;, &lt;a href="https://twitter.com/lgouarin"&gt;Loic Gouarin&lt;/a&gt;, &lt;a href="https://twitter.com/JohanMabille"&gt;Johan Mabille&lt;/a&gt;, and &lt;a href="https://github.com/wolfv"&gt;Wolf Vollprecht&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The development of xeus, xwidgets and related packages at &lt;a href="https://twitter.com/QuantStack"&gt;QuantStack&lt;/a&gt; is sponsored by &lt;a href="http://www.techatbloomberg.com"&gt;&lt;strong&gt;Bloomberg&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="about-the-author"&gt;About the Author&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://twitter.com/martinRenou"&gt;Martin Renou&lt;/a&gt; is a Scientific Software developer at &lt;a href="https://github.com/QuantStack/"&gt;QuantStack&lt;/a&gt;. Prior to joining QuantStack, Martin studied at the &lt;a href="https://www.isae-supaero.fr/en"&gt;French Institute of Aeronautics and Space&lt;/a&gt;. As an open source developer, he worked on a variety of projects, notably &lt;a href="https://demo.logilab.fr/SciviJS/"&gt;SciviJS&lt;/a&gt;, a JavaScript library for 3-D mesh visualization.&lt;/p&gt;
</content><category term="C++"/><category term="geoscience"/><category term="science"/></entry></feed>