<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Jupyter Blog - visualization</title><link href="https://jasongrout.github.io/medium-archive/pelican/" rel="alternate"/><link href="https://jasongrout.github.io/medium-archive/pelican/feeds/tag-visualization.atom.xml" rel="self"/><id>https://jasongrout.github.io/medium-archive/pelican/</id><updated>2026-02-04T14:50:00+00:00</updated><subtitle>The Project Jupyter blog: news, releases, and community stories, archived from blog.jupyter.org.</subtitle><entry><title>Instantly view Parquet files in JupyterLab with Arbalister</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2026/instantly-view-parquet-files-in-jupyterlab-with/" rel="alternate"/><published>2026-01-29T16:18:00+00:00</published><updated>2026-02-04T14:50:00+00:00</updated><author><name>Antoine Prouvost</name></author><id>tag:jasongrout.github.io,2026-01-29:/medium-archive/pelican/posts/2026/instantly-view-parquet-files-in-jupyterlab-with/</id><summary type="html">&lt;p&gt;A colleague sends you a SQLite file, a Parquet dataset, or an Avro snapshot. You need to explore the content, but you’re not sure what’s…&lt;/p&gt;
</summary><content type="html">&lt;p&gt;A colleague sends you a SQLite file, a Parquet dataset, or an Avro snapshot.&lt;br&gt;
You need to explore the content, but you’re not sure what’s inside or even how to open it. You shouldn’t have to write code, craft SQL queries, or recall the syntax for &lt;code&gt;read_parquet&lt;/code&gt;in a Python library. Instead, you should be able to click the file once and instantly see the tables and metadata.&lt;/p&gt;
&lt;p&gt;Despite being the &lt;em&gt;de-facto&lt;/em&gt; standard for data science and exploration, JupyterLab lacks this basic capability out of the box. Of course, there are extremely well designed libraries to read, process, and transform tabular data — but opening and viewing a file with a table should be simpler. A workflow with libraries like Pandas or Polars require you to install relevant packages, create a notebook, and iterate on queries to get a full picture of the data.&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;pandas&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;pd&lt;/span&gt;

&lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;display.max_rows&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;display.max_columns&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;display.width&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_parquet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;data/2025/PERFORMANCE_SNAPSHOT_2025_01_05.parquet&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Whether for a newcomer to data science, or someone that needs to investigate many different files with hard to remember schemas, this is a bit cumbersome. Comma separated value files (CSV) have better support: double click on the file to see it open (see figure below). That is a great way to understand the business logic and answer questions such as &lt;em&gt;What type of information is in this file? What do values typically look like? Does it seem to contain all the data I need? What is the difference between &lt;code&gt;customer_id&lt;/code&gt; and &lt;code&gt;user_id&lt;/code&gt;?&lt;/em&gt;&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="The built-in CSV viewer of JupterLab shows data as a table." src="https://jasongrout.github.io/medium-archive/pelican/posts/2026/instantly-view-parquet-files-in-jupyterlab-with/images/001-1_pHSj3jmo0D69yzM86_XAZg.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;The JupyterLab CSV viewer&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;Arbalister&lt;/strong&gt;, our new JupyterLab extension, changes this. With Arbalister, you can &lt;strong&gt;double-click to instantly view&lt;/strong&gt; a wide range of tabular data files: &lt;strong&gt;Parquet, CSV, Avro, ORC, SQLite,&lt;/strong&gt; and more…&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Arbalister viewer can open Parquet files and more" src="https://jasongrout.github.io/medium-archive/pelican/posts/2026/instantly-view-parquet-files-in-jupyterlab-with/images/002-1_CHOorqcOpRmlHlHFIPpF-A.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Arbalister viewer can open Parquet files and more&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The extension will load data as it is displayed, making it possible to view it almost instantaneously even if the file does not fit in memory. A toolbar lets the user select some reading options, such as the delimiter for a CSV file, or selecting the table to display in the SQLite file!&lt;/p&gt;
&lt;h2 id="arrow-over-the-wire"&gt;Arrow over the wire&lt;/h2&gt;
&lt;p&gt;Fueling it all is the &lt;a href="https://arrow.apache.org/"&gt;Apache Arrow&lt;/a&gt; ecosystem, an in-memory format for tabular data used in most data science libraries. Plenty of files types can already be read into an Arrow data structure so we exploit it heavily in Arbalister (with &lt;a href="https://datafusion.apache.org/"&gt;Apache Datafusion&lt;/a&gt; in our case).&lt;/p&gt;
&lt;p&gt;The table displayed in the user’s browser reuses JupyterLab Lumino DataGrid with a custom data model. In the latter, we divide the whole table in chunks across both the rows and columns axes (&lt;em&gt;e.g.&lt;/em&gt; 512 rows and 24 columns). When we need to display data from a chunk that is not already available, we make an HTTP request to a server-side extension that open the file, read the relevant portion into an Arrow table and return it to the client. The table is returned as Arrow IPC (Inter Process Communication, a binary format close to the original Arrow memory) in the response body. In the client, a lightweight Arrow implementation can read it back efficiently.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="A diagram show a client server-server architecture for Arbalister, with the backend responsible for reading many different file types into an Arrow IPC format, while the frontend displays it." src="https://jasongrout.github.io/medium-archive/pelican/posts/2026/instantly-view-parquet-files-in-jupyterlab-with/images/003-1_6qFKCpSW5d3GT1p6EOfekg.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Arbalister client-server architecture&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;When nothing else is happening, the implementation will also pre-fetch some of the next chunks in the background so that scrolling past a chunk boundary is imperceptible.&lt;/p&gt;
&lt;p&gt;Because it all works in Arrow, which is standard for tabular data, adding support for new types of files that can be read into the Arrow format is extremely easy. Vortex, Lance, or whichever other format becomes relevant. But that is not all…&lt;/p&gt;
&lt;p&gt;The existing SQLite support is made possible through &lt;a href="https://arrow.apache.org/adbc/"&gt;ADBC&lt;/a&gt;, an SQL connector that reads databases into Arrow format. SQLite databases fit into single files, which fit the abstraction used in Arbalister, but ADBC could also be used to add general database exploration (Postgres &lt;em&gt;etc&lt;/em&gt;.) into Arbalister. With Datafusion, we could also add visualization for data lakehouses: partitioned datasets (&lt;em&gt;e.g.&lt;/em&gt; &lt;a href="https://delta.io/"&gt;DeltaLake&lt;/a&gt; or &lt;a href="https://iceberg.apache.org/"&gt;Apache Iceberg&lt;/a&gt;) over remote object storage (S3). With Intelligent predicate and projections pushdowns, we could visualize remote tera-byte table instantly by only downloading the relevant parts.&lt;/p&gt;
&lt;h2 id="looking-further"&gt;Looking further&lt;/h2&gt;
&lt;p&gt;There are multiple things that would make great improvements to Arbalister. We have already mentioned:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Optional support for newer file types: Vortex, Lance;&lt;/li&gt;
&lt;li&gt;Object storage and data lakehouses support;&lt;/li&gt;
&lt;li&gt;SQL databases support.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Another direction is support for &lt;a href="https://jupyterlite.readthedocs.io/en/stable/"&gt;JupyterLite&lt;/a&gt;, a &lt;a href="https://webassembly.org/"&gt;WebAssembly&lt;/a&gt; distribution of JupyterLab running entirely in the browser. This setting is great for education because it does not require more than a static file server to host.&lt;br&gt;
Being able to work directly with Parquet files in the browser is great for making dashboard and interactive demonstrations. Arrow and Datafusion already have some experimental support for WebAssembly so this is not so far-fetched.&lt;/p&gt;
&lt;p&gt;Finally Arbalister could use a few features to investigate deeper questions about the data. For instance, beyond the &lt;em&gt;What does the data look like?&lt;/em&gt; question, some column filters could help answer questions &lt;em&gt;such as What does the data look like in November 2024 for John Doe?&lt;/em&gt; Perhaps even an SQL console for more advanced queries.&lt;/p&gt;
&lt;h2 id="an-extension-point"&gt;An extension point&lt;/h2&gt;
&lt;p&gt;The server extension being only a way to serve Arrow data, it can be reused by other libraries to use it in other ways. For instance, if we knew that our table contains time-series data, a second viewer could display it as a graph.&lt;br&gt;
Similarly for geospatial data.&lt;/p&gt;
&lt;p&gt;If you are interested to use or contribute to Arbalister, head to &lt;a href="https://github.com/QuantStack/Arbalister"&gt;our GitHub&lt;/a&gt;!&lt;/p&gt;
&lt;h2 id="about-the-author"&gt;About the Author&lt;/h2&gt;
&lt;p&gt;Antoine Prouvost is a senior scientific software engineer at QuantStack. His work on Arbalister was funded by Bloomberg.&lt;/p&gt;
</content><category term="JupyterLab"/><category term="visualization"/></entry><entry><title>Build your Jupyter dashboard using Solara</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2024/build-your-jupyter-dashboard-using-solara/" rel="alternate"/><published>2024-12-17T10:26:00+00:00</published><updated>2024-12-18T08:06:00+00:00</updated><author><name>Maarten Breddels</name></author><id>tag:jasongrout.github.io,2024-12-17:/medium-archive/pelican/posts/2024/build-your-jupyter-dashboard-using-solara/</id><summary type="html">&lt;p&gt;Welcome to the first part of a series of articles showing you how to create a dashboard in Jupyter and deploy it as a standalone web app…&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Welcome to the first part of a series of articles showing you how to create a dashboard in Jupyter and deploy it as a standalone web app. Importantly, you won’t need to rewrite your app in a different framework for deployment. We will use a pure Python solution with no JavaScript or CSS required.&lt;/p&gt;
&lt;p&gt;Jupyter notebooks are an incredible data analysis tool since they blend code, visualization, and narrative into a single document. However, we do not want to show the code if the insights must be presented to a non-technical audience.&lt;/p&gt;
&lt;p&gt;Built on top of ipywidgets, the Solara framework integrates into the Jupyter Notebook, Jupyter Lab, and other Jupyter environments and is Open Source. As we will see in a later article, Solara apps can also be deployed efficiently using the Solara server. This, by itself, makes Solara a perfect solution for creating dashboards or data apps.&lt;/p&gt;
&lt;p&gt;In this article, we will create a simple dashboard using Solara’s UI components in Jupyter. The final product will allow an end-user to filter, visualize, and explore a dataset on a map.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="The end result will be a modern looking deploy app" src="https://jasongrout.github.io/medium-archive/pelican/posts/2024/build-your-jupyter-dashboard-using-solara/images/001-1_84N-UBW-fy0xX1pCagIeiw.jpg" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;The end result will be a modern looking deploy app&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="pre-requisites"&gt;Pre-requisites&lt;/h2&gt;
&lt;p&gt;You need to install &lt;code&gt;pandas&lt;/code&gt;, &lt;code&gt;matplotlib&lt;/code&gt;, &lt;code&gt;folium&lt;/code&gt; and &lt;code&gt;solara&lt;/code&gt;. Assuming you are using pip, you can execute on your shell:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pip&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="n"&gt;pandas&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;matplotlib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;folium&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;solara&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Or in your notebook&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;%pip&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="n"&gt;pandas&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;matplotlib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;folium&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;solara&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="the-start"&gt;The start&lt;/h2&gt;
&lt;p&gt;We will use a subsample of the &lt;a href="https://www.kaggle.com/competitions/sf-crime/data"&gt;San Fransisco crime dataset&lt;/a&gt; which contains information on types of crimes and where they were committed.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://raw.githubusercontent.com/widgetti/solara/master/solara/website/pages/docs/content/04-tutorial/SF_crime_sample.csv.gz"&gt;Download the CSV file&lt;/a&gt; to run this locally, or let the code below sort it out.&lt;/p&gt;
&lt;p&gt;The first thing we do when we read the data is to print it out to see what the dataset contains.&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;pandas&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;pd&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;pathlib&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;Path&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;solara&lt;/span&gt;

&lt;span class="n"&gt;ROOT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;solara&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="vm"&gt;__file__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;website&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;pages&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;docs&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;content&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;04-tutorial&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ROOT&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;Path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;SF_crime_sample.csv.gz&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;https://raw.githubusercontent.com/widgetti/solara/master/solara/website/pages/docs/content/04-tutorial/SF_crime_sample.csv&amp;quot;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;df_crime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;df_crime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;df_crime&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;figure&gt;
&lt;img alt="Pandas printout of the Crime dataset Dataframe" src="https://jasongrout.github.io/medium-archive/pelican/posts/2024/build-your-jupyter-dashboard-using-solara/images/002-1_bctoyIMn6I60D6gzMq-wjQ.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Pandas printout of the Crime dataset Dataframe&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The data looks clean, but since we will work with the &lt;code&gt;Category&lt;/code&gt; and &lt;code&gt;PdDistrict&lt;/code&gt; column data, let us convert those columns to title case.&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;df_crime&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Category&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df_crime&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Category&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;df_crime&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;PdDistrict&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df_crime&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;PdDistrict&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;df_crime&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;figure&gt;
&lt;img alt="Category and PdDistrict columns nicely formatted with title casing" src="https://jasongrout.github.io/medium-archive/pelican/posts/2024/build-your-jupyter-dashboard-using-solara/images/003-1_3qlsT6qyJsLyRB9Ded461Q.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Category and PdDistrict columns nicely formatted with title casing&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Using proper software engineering practices, we write a function that filters a dataframe to contain only the rows that match our chosen districts and categories.&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;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;crime_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;district_values&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;category_values&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;df_dist&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;PdDistrict&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;district_values&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;df_category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df_dist&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df_dist&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Category&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;category_values&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;df_category&lt;/span&gt;

&lt;span class="n"&gt;dff_crime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;crime_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df_crime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Bayview&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Northern&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Vandalism&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Assault&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Robbery&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now, with our filtered dataset, we create two bar charts. We use regular Pandas and Matplotlib, but Seaborn or Plotly are also appropriate choices.&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;matplotlib.pyplot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;plt&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;crime_charts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;cat_unique&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Category&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value_counts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;cat_unique&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cat_unique&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset_index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;dist_unique&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;PdDistrict&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value_counts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;dist_unique&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dist_unique&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset_index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;fig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ax1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ax2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;subplots&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;figsize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="n"&gt;ax1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cat_unique&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Category&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;cat_unique&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;count&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;ax1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Amount of Criminal Case Based on Category&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ax2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dist_unique&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;PdDistrict&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;dist_unique&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;count&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;ax2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Amount of Criminal Case in Selected District&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fig&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;crime_charts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dff_crime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2024/build-your-jupyter-dashboard-using-solara/images/004-1_5O_dyZhxuJMZNAMt3gw6rg.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;Since we do not need bidirectional communication (e.g., we do not need to receive events or data from our map), we use Folium to display the locations of the committed crimes on a map. If we do need bidirectional communication, we can use &lt;a href="https://ipyleaflet.readthedocs.io/"&gt;ipyleaflet&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Since we cannot display all the data on the map without crashing your browser, we limit it to a maximum of 50 points.&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;folium&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;folium.plugins&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;crime_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&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;37.77&lt;/span&gt;
    &lt;span class="n"&gt;longitude&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;122.42&lt;/span&gt;

    &lt;span class="n"&gt;sanfran_map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;folium&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;zoom_start&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="n"&gt;incidents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;folium&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MarkerCluster&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sanfran_map&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# loop through the dataframe and add each data point to the mark cluster&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;lng&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Category&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;folium&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Marker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;lng&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;icon&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;popup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;incidents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# show map&lt;/span&gt;
    &lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sanfran_map&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;crime_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dff_crime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;50&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;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2024/build-your-jupyter-dashboard-using-solara/images/005-1_tTvZxrjpxsrsd7f1w55QjA.jpg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;h2 id="making-our-first-reactive-visualization"&gt;Making our first reactive visualization&lt;/h2&gt;
&lt;p&gt;The above code works nicely, but if we want to explore different types of crimes, we need to modify and run all cells that determine our output manually. Would it not be much better to have a UI with controls determining the filtering and a view displaying the filtered data interactively?&lt;/p&gt;
&lt;p&gt;Let’s start by importing the solara package and creating three reactive variables.&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;solara&lt;/span&gt;

&lt;span class="n"&gt;districts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;solara&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Bayview&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Northern&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;categories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;solara&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Vandalism&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Assault&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Robbery&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;solara&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A reactive variable is a container around a value (like an int, string, or list) that allows the UI to listen to changes automatically. Any change to &lt;code&gt;your_reactive_variable.value&lt;/code&gt; will be picked up by Solara components that use them so that they can automatically redraw or update themselves.&lt;/p&gt;
&lt;p&gt;Let us now create our first component (&lt;code&gt;View&lt;/code&gt;), which filters the data based on the reactive variables and shows the map and the charts. Solara supports the &lt;code&gt;display&lt;/code&gt; mechanism of Jupyter so that we can use our previously defined functions.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nd"&gt;@solara&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;component&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;View&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;dff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;crime_filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df_crime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;districts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;categories&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;row_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dff&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;row_count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;solara&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Only showing the first &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; of &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;row_count&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; crimes on map&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;crime_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dff&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;row_count&lt;/span&gt; &lt;span class="o"&gt;&amp;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;crime_charts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dff&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;solara&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;You filtered out all the data, no charts shown&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;View&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="Our reactive visualization auto-updates when any reactive variable changes" src="https://jasongrout.github.io/medium-archive/pelican/posts/2024/build-your-jupyter-dashboard-using-solara/images/006-1_BhAMB3EetCG4IfnyuWuY1A.jpg" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Our reactive visualization auto-updates when any reactive variable changes&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Note that some UI parts (like the warning and the charts) are conditional. Solara will automatically find out what to add, remove, or update without you having to do this manually. Solara is declarative (similar to ReactJS) but also reactive. If we change the reactive variables, Solara will see those changes and notify the component instances that use its value.&lt;/p&gt;
&lt;p&gt;If we run the next lines of code in our notebook, our &lt;code&gt;View&lt;/code&gt; will automatically update.&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;limit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;70&lt;/span&gt;
&lt;span class="n"&gt;districts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&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;Soutern&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Northern&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We can now explore our data much faster since we don’t need to re-run the cells that depend on it.&lt;/p&gt;
&lt;p&gt;Solara’s reactive and declarative nature makes it scalable to much larger applications than regular ipywidgets, where keeping the UI in sync and adding, removing, and updating widgets is a manual and bug-prone process.&lt;/p&gt;
&lt;h2 id="adding-controls"&gt;Adding controls&lt;/h2&gt;
&lt;p&gt;We created a declarative and reactive mini app in our notebook, but we still need to manually modify the values by executing a code cell in our Notebook. Now, let us create a UI to control it. All Solara input components support reactive variables. This means that controlling a reactive variable using a UI element is often a one-liner.&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;solara&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SelectMultiple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;District&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;all_values&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;df_crime&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;PdDistrict&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tolist&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;
    &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;districts&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="In one line of code we made our app filtering interactive by adding a dropdown" src="https://jasongrout.github.io/medium-archive/pelican/posts/2024/build-your-jupyter-dashboard-using-solara/images/007-1_oWB4IjwHBDQZHsf13zKG6w.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;In one line of code we made our app filtering interactive by adding a dropdown&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Whow, that was simple! We can now easily change the filter and see the results update. Lets do this for all our reactive variables, and put them into a single component.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nd"&gt;@solara&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;component&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Controls&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;solara&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SelectMultiple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;District&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;all_values&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;df_crime&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;PdDistrict&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tolist&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;districts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;solara&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SelectMultiple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Category&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;all_values&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;df_crime&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Category&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tolist&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;categories&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;solara&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Maximum number of rows to show on map&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;solara&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SliderInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;min&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="nb"&gt;max&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;Controls&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="All controls for the filtering of our dataframe and visualization" src="https://jasongrout.github.io/medium-archive/pelican/posts/2024/build-your-jupyter-dashboard-using-solara/images/008-1_MhxvqxsURNH-1X9yr2La4g.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;All controls for the filtering of our dataframe and visualization&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Note that the reactive variables are bi-directional, meaning that if you change it in the UI elements, it gets reflected on the Python code!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# Note that we can read AND write reactive variables&lt;/span&gt;
&lt;span class="n"&gt;categories&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&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="n"&gt;categories&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Warrants&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2 id="the-final-dashboard"&gt;The final dashboard&lt;/h2&gt;
&lt;p&gt;We now have two parts of our UI in separate cells. This can be an amazing experience when developing in a notebook, as it flows naturally in the data exploration process while writing your notebook.&lt;/p&gt;
&lt;p&gt;However, your end user will probably want something more coherent. The components we created are perfectly reusable, so we put them together in a single UI.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nd"&gt;@solara&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;component&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Page&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;solara&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sidebar&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;Controls&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;View&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;Page&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="Our end result" src="https://jasongrout.github.io/medium-archive/pelican/posts/2024/build-your-jupyter-dashboard-using-solara/images/009-1_5Ujq7HfB0YnX9yoAzFZmwA.jpg" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Our end result&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Finally, our dashboard is finished!&lt;/p&gt;
&lt;h2 id="conclusions"&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;Using Solara, you created an interactive dashboard within a Jupyter Notebook. Your Solara components are declarative, and when using reactive variables, they are also reactive. Whether you change reactive variables via code or the UI elements, your visualizations and maps update automatically.&lt;/p&gt;
&lt;p&gt;Your dashboard prototype now runs in your Jupyter Notebook environment, but we can only deploy it as an app. In our next article, we will focus on deploying our notebook without making any code changes. In our third tutorial, we will expand our dashboard with a few more components and create a more advanced layout.&lt;/p&gt;
&lt;p&gt;All documentation for Solara can be found at &lt;a href="https://solara.dev"&gt;https://solara.dev&lt;/a&gt;, the GitHub repo can be found at &lt;a href="https://github.com/widgetti/solara/"&gt;https://github.com/widgetti/solara/&lt;/a&gt; and feel free to join our &lt;a href="https://discord.solara.dev/"&gt;Discord&lt;/a&gt; for a chat.&lt;/p&gt;
</content><category term="dashboards"/><category term="visualization"/></entry><entry><title>Interactive Mapping with ipyopenlayers</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2024/interactive-mapping-with-ipyopenlayers/" rel="alternate"/><published>2024-09-05T15:30:00+00:00</published><updated>2024-09-05T15:30:00+00:00</updated><author><name>Cheour Nour</name></author><id>tag:jasongrout.github.io,2024-09-05:/medium-archive/pelican/posts/2024/interactive-mapping-with-ipyopenlayers/</id><summary type="html">&lt;p&gt;Bringing the Power of OpenLayers to Jupyter.&lt;/p&gt;
</summary><content type="html">&lt;blockquote&gt;
&lt;p&gt;Bringing the Power of OpenLayers to Jupyter.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Interactive maps play a crucial role in presenting complex geospatial information in a clear and engaging manner. While the Python ecosystem already offers an impressive range of libraries for visualization, ipyopenlayers stands out as a powerful new tool that allows for the seamless integration of the advanced features of the OpenLayers JavaScript library into Jupyter. In this article, we will present the main features of ipyopenlayers and demonstrate how this library can transform your geospatial data into dynamic, interactive visualizations.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="1-what-is-ipyopenlayers"&gt;1. What is ipyopenlayers?&lt;/h2&gt;
&lt;p&gt;ipyopenlayers is an open-source Python library that integrates OpenLayers, a popular JavaScript library for creating interactive maps, directly into Jupyter Notebooks. By combining the strengths of Jupyter and OpenLayers, ipyopenlayers allows users to create interactive maps with ease. Its versatility and simplicity make it an ideal choice for a wide range of applications, from data exploration to presenting geospatial analysis.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="2-getting-started-with-ipyopenlayers"&gt;2. Getting Started with ipyopenlayers&lt;/h2&gt;
&lt;p&gt;To start using ipyopenlayers, you only need to install the library via pip:&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;ipyopenlayers
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Once installed, you’re ready to embark on your interactive map-making adventure!&lt;/p&gt;
&lt;h3 id="a-creating-your-first-map"&gt;a) Creating Your First Map&lt;/h3&gt;
&lt;p&gt;ipyopenlayers has a user-friendly interface that makes creating maps simple and quick. Here’s how to generate a basic map with just a few lines of code:&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;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;ipyopenlayers&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;Map&lt;/span&gt;

&lt;span class="c1"&gt;# Create a map centered on a specific location&lt;/span&gt;
&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;center&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&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;zoom&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Display the map&lt;/span&gt;
&lt;span class="n"&gt;m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;figure&gt;
&lt;img alt="Screenshot of a simple ipyopenlayers map displayed inline in the Jupyter notebook" src="https://jasongrout.github.io/medium-archive/pelican/posts/2024/interactive-mapping-with-ipyopenlayers/images/001-1_B-klBKQToGuUZtwb3xOKCQ.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Screenshot of a simple ipyopenlayers map displayed inline in the Jupyter notebook&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="b-adding-layers-and-controls"&gt;b) Adding Layers and Controls&lt;/h3&gt;
&lt;p&gt;Maps are more than just images; they allow you to mark specific locations and overlay various data. ipyopenlayers makes it easy to add layers and controls to your maps. For example, here’s how to add a raster tile layer from OpenStreetMap and a zoom slider control:&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;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;ipyopenlayers&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;RasterTileLayer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ZoomSlider&lt;/span&gt;
&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# Add a raster tile layer&lt;/span&gt;
&lt;span class="n"&gt;raster_layer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RasterTileLayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;https://{a-c}.basemaps.cartocdn.com/dark_all/&lt;/span&gt;&lt;span class="si"&gt;{z}&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{x}&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{y}&lt;/span&gt;&lt;span class="s1"&gt;.png&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_layer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raster_layer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Add a zoom slider control&lt;/span&gt;
&lt;span class="n"&gt;zoom_slider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ZoomSlider&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_control&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zoom_slider&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;figure&gt;
&lt;img alt="Screenshot of a simple ipyopenlayers map displayed inline in the Jupyter notebook showcasing the basic controls" src="https://jasongrout.github.io/medium-archive/pelican/posts/2024/interactive-mapping-with-ipyopenlayers/images/002-0_lsbq37wgQCiEuXyc.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Screenshot of a simple ipyopenlayers map displayed inline in the Jupyter notebook showcasing the basic controls&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="3-main-features-of-ipyopenlayers"&gt;3. Main Features of ipyopenlayers&lt;/h2&gt;
&lt;p&gt;ipyopenlayers is packed with a wide array of functionalities that make it ideal for creating advanced interactive maps in Jupyter Notebooks. From adding custom controls to enabling dynamic layer and overlays, this library offers you tools for enhancing your geospatial visualizations. Here’s a sneak peek at some of its key features.&lt;/p&gt;
&lt;h3 id="a-vector-tile-layer-support"&gt;a) Vector Tile Layer Support&lt;/h3&gt;
&lt;p&gt;Vector Tile Layers enable efficient, high-quality rendering of geospatial data, allowing for smooth zooming and dynamic styling of map features. They offer flexibility and customization for detailed interactive maps in Jupyter Notebooks.&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;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;ipyopenlayers&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;Map&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;VectorTileLayer&lt;/span&gt;

&lt;span class="c1"&gt;# Create a map centered at coordinates [0, 0] with zoom level 0&lt;/span&gt;
&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;center&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&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;zoom&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="c1"&gt;# Add a VectorTileLayer to the map&lt;/span&gt;
&lt;span class="n"&gt;vector_layer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="n"&gt;VectorTileLayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;https://basemaps.arcgis.com/arcgis/rest/services/World_Basemap_v2/VectorTileServer/tile/&lt;/span&gt;&lt;span class="si"&gt;{z}&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{y}&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="si"&gt;{x}&lt;/span&gt;&lt;span class="s1"&gt;.pbf&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;source_format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;&amp;#39;type&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;MVT&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_layer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vector_layer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Display the map&lt;/span&gt;
&lt;span class="n"&gt;m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;figure&gt;
&lt;img alt="Screenshot of an ipyopenlayers map displaying a vector layout in the Jupyter notebook" src="https://jasongrout.github.io/medium-archive/pelican/posts/2024/interactive-mapping-with-ipyopenlayers/images/003-0_BsaDtYKDTbciUFgt.jpg" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Screenshot of an ipyopenlayers map displaying a vector layout in the Jupyter notebook&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="b-geojson-support"&gt;b) GeoJSON Support&lt;/h3&gt;
&lt;p&gt;GeoJSON is a popular format for encoding geographic data structures. Here’s how to display GeoJSON data on your map:&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;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;json&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;ipyopenlayers&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;Map&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GeoJSON&lt;/span&gt;

&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;center&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="mf"&gt;77.15641232105159&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;34.561348453091625&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="mf"&gt;9.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Note the coordinate order: [latitude, longitude]&lt;/span&gt;

&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;demo.json&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Add the GeoJSON layer&lt;/span&gt;
&lt;span class="n"&gt;geo_json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GeoJSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Add the GeoJSON layer to the map&lt;/span&gt;
&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_layer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;geo_json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;figure&gt;
&lt;img alt="Screenshot of an ipyopenlayers map displaying a GeoJSON dataset as a layer on a map" src="https://jasongrout.github.io/medium-archive/pelican/posts/2024/interactive-mapping-with-ipyopenlayers/images/004-0_KCYQDm_sq-YRTzhb.jpg" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Screenshot of an ipyopenlayers map displaying a GeoJSON dataset as a layer on a map&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="c-geotiff-support"&gt;c) GeoTIFF Support&lt;/h3&gt;
&lt;p&gt;ipyopenlayers also enables the visualization of GeoTIFF files, which are essential for displaying raster data with geographic context:&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;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;ipyopenlayers&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;GeoTIFFTileLayer&lt;/span&gt;

&lt;span class="c1"&gt;# Create a GeoTIFF layer&lt;/span&gt;
&lt;span class="n"&gt;geo_tiff_layer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GeoTIFFTileLayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/36/Q/WD/2020/7/S2A_36QWD_20200701_0_L2A/TCI.tif&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_layer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;geo_tiff_layer&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="Screenshot of an ipyopenlayers map displaying a GeoTIFF dataset as a layer on a map" src="https://jasongrout.github.io/medium-archive/pelican/posts/2024/interactive-mapping-with-ipyopenlayers/images/005-0_4q0M7_QjVtXcrItA.jpg" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Screenshot of an ipyopenlayers map displaying a GeoTIFF dataset as a layer on a map&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="4-advanced-use-cases-building-an-electricity-map-dashboard"&gt;4. Advanced Use Cases: Building an Electricity Map Dashboard&lt;/h2&gt;
&lt;p&gt;The potential of ipyopenlayers extends far beyond basic mapping. One innovative application is its use in creating dynamic and interactive dashboards that integrate with other powerful Python tools.&lt;/p&gt;
&lt;p&gt;A notable example is the &lt;a href="https://github.com/Nour-Cheour10/electricitymap_dashboard"&gt;&lt;strong&gt;Electricity Map Dashboard&lt;/strong&gt;&lt;/a&gt;, a project designed to visualize and analyze electricity data from around the world using ipyopenlayers in conjunction with libraries such as &lt;em&gt;electricityMap&lt;/em&gt;, &lt;em&gt;ipywidgets, voila&lt;/em&gt;, and &lt;em&gt;bqplot&lt;/em&gt;.&lt;/p&gt;
&lt;h3 id="key-features"&gt;Key Features:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Real-time Visualization&lt;/strong&gt;: Using electricityMap, the dashboard overlays real-time electricity consumption and carbon intensity data onto a global map with ipyopenlayers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Interactive Controls&lt;/strong&gt;: ipywidgets enables users to filter data by region, select specific time periods, and toggle between different map layers, making the data exploration highly interactive.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dynamic Plotting&lt;/strong&gt;: bqplot allows users to generate customizable plots synchronized with the map, offering deeper insights into electricity trends and carbon emissions.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
&lt;img alt="Screenshot of the Electricity Map dashboard built with bqplot and ipyopenlayers" src="https://jasongrout.github.io/medium-archive/pelican/posts/2024/interactive-mapping-with-ipyopenlayers/images/006-1_KVMcn3qI6S79S9N8nKIy1Q.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Screenshot of the Electricity Map dashboard built with bqplot and ipyopenlayers&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;This project showcases the powerful integration of ipyopenlayers with other Python tools to create a dynamic, user-friendly dashboard for analyzing global electricity trends.&lt;/p&gt;
&lt;h2 id="5-developments"&gt;5. Developments&lt;/h2&gt;
&lt;p&gt;The future of ipyopenlayers is promising, with upcoming features like improved integration with other Python libraries, advanced customization tools, and expanded support for geospatial data formats. We invite the open-source community to contribute to this project, whether through suggestions, bug reports, or code contributions.&lt;/p&gt;
&lt;h2 id="6-conclusion"&gt;6. Conclusion&lt;/h2&gt;
&lt;p&gt;With ipyopenlayers, the power of interactive maps is at your fingertips within your Jupyter Notebooks. This Python library allows you to present your geospatial data in an engaging and insightful way, making your analyses more dynamic and accessible. Whether you’re a data analyst, researcher, or simply a mapping enthusiast, ipyopenlayers provides the tools you need to turn your data into compelling visualizations.&lt;/p&gt;
&lt;p&gt;So, what are you waiting for? Install ipyopenlayers and start creating interactive maps that bring your data to life!&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="7-acknowledgments"&gt;7. Acknowledgments&lt;/h2&gt;
&lt;p&gt;This project was made possible through the collaboration and support of several individuals. Special thanks to &lt;strong&gt;Martin Renou , Technical Director at QuantStack,&lt;/strong&gt; whose guidance and expertise were instrumental throughout this project. His mentorship greatly contributed to the success of this ipyopenlayers.&lt;/p&gt;
&lt;h2 id="8-about-the-author"&gt;8. About the Author&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.linkedin.com/in/nour-cheour-606143206/"&gt;&lt;em&gt;Nour Cheour&lt;/em&gt;&lt;/a&gt; &lt;em&gt;has just completed her Engineering degree at INSAT and her six-month internship as an open-source scientific software engineer at QuantStack.&lt;/em&gt;&lt;/p&gt;
</content><category term="geoscience"/><category term="science"/><category term="visualization"/></entry><entry><title>ipydatagrid is now part of Project Jupyter</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2024/ipydatagrid-is-now-part-of-project-jupyter/" rel="alternate"/><published>2024-08-22T15:01:00+00:00</published><updated>2024-08-22T15:01:00+00:00</updated><author><name>Sylvain Corlay</name></author><id>tag:jasongrout.github.io,2024-08-22:/medium-archive/pelican/posts/2024/ipydatagrid-is-now-part-of-project-jupyter/</id><summary type="html">&lt;p&gt;Today, we are proud to announce that the ipydatagrid open source project has been incorporated into Project Jupyter as part of the Jupyter…&lt;/p&gt;
</summary><content type="html">&lt;p&gt;Today, we are proud to announce that the &lt;a href="https://github.com/jupyter-widgets/ipydatagrid"&gt;ipydatagrid&lt;/a&gt; open source project has been incorporated into Project Jupyter as part of the Jupyter Widgets subproject.&lt;/p&gt;
&lt;h2 id="what-is-ipydatagrid"&gt;What is ipydatagrid?&lt;/h2&gt;
&lt;p&gt;ipydatagrid is a fast data grid widget for Jupyter Notebooks and JupyterLab. Since its inception in 2019, it has been developed as an open source project in Bloomberg’s GitHub organization.&lt;/p&gt;
&lt;p&gt;It offers a high-performance fully-featured DataGrid interface, fully integrated with ipywidgets. Built upon the Lumino datagrid, which also powers the JupyterLab CSV viewer, ipydatagrid provides users with a robust and versatile tool for data visualization and manipulation.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2024/ipydatagrid-is-now-part-of-project-jupyter/images/001-0_9xQd6YxFsBDFPyxw.mp4" alt="Screencast of ipydatagrid in action, showcasing multiple cell renderers with conditional rendering, and filtering of data." loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;h2 id="key-features"&gt;Key Features&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Users can customize the way data is represented in their grid using a variety of renderers.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2024/ipydatagrid-is-now-part-of-project-jupyter/images/002-0_bNrtqVrcwR1dpX9O.mp4" alt="Screencast of ipydatagrid showcasing advanced rendering capabilities." loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ipydatagrid includes a sophisticated selection model with two-way data binding.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2024/ipydatagrid-is-now-part-of-project-jupyter/images/003-0_wKlCImr0LtGDpeDz.mp4" alt="Screencast of ipydatagrid showcasing the advanced selection model with bi-directional bindings." loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It enables conditional formatting powered by&lt;/strong&gt; &lt;a href="https://vega.github.io/vega/docs/expressions/"&gt;&lt;strong&gt;Vega Expressions&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2024/ipydatagrid-is-now-part-of-project-jupyter/images/004-0_U5H7uyoSLf0pZm6q.gif" alt="Screenshot of ipydatagrid showcasing the use of Vega expression for conditional formatting." loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;h2 id="the-transfer-to-project-jupyter"&gt;The transfer to Project Jupyter&lt;/h2&gt;
&lt;p&gt;We would like to extend our gratitude to the developers and contributors who have significantly improved the ipydatagrid project over the years: Itay Dafna, Martin Renou, Mehmet Bektas, Kaia Young, Bernát Gábor, Vasilis Themelis, Supriya K., Greg Mooney, Ian Thomas, Olly Hensby, and John Gunstone. Special thanks to Chris Colbert, the creator of the Lumino Datagrid, which forms the foundation of ipydatagrid’s front-end.&lt;/p&gt;
&lt;h2 id="bloombergs-contribution-to-project-jupyter"&gt;Bloomberg’s contribution to Project Jupyter&lt;/h2&gt;
&lt;p&gt;The transfer of ipydatagrid to Project Jupyter is just one of many contributions that Bloomberg has made to Project Jupyter. As a long-standing sponsor, Bloomberg has been instrumental in the development and success of Jupyter. Home to core maintainers and a major funder of JupyterLab since its inception, Bloomberg has also sponsored all editions of JupyterCon. The sustained support by Bloomberg has been crucial to Jupyter’s growth and impact.&lt;/p&gt;
&lt;p&gt;We are excited about the future of ipydatagrid within Project Jupyter, and look forward to continued innovation and collaboration within the broader community.&lt;/p&gt;
&lt;p&gt;— on behalf of the Jupyter Widgets Council, Sylvain Corlay&lt;/p&gt;
</content><category term="visualization"/><category term="widgets"/></entry><entry><title>Embed interactive itkwidgets 3D renderings into JupyterLite deployments</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2023/embed-interactive-itkwidgets-3d-renderings-into/" rel="alternate"/><published>2023-03-10T14:04:00+00:00</published><updated>2023-03-15T10:27:00+00:00</updated><author><name>Matt McCormick @thewtex@fosstodon.org</name></author><id>tag:jasongrout.github.io,2023-03-10:/medium-archive/pelican/posts/2023/embed-interactive-itkwidgets-3d-renderings-into/</id><summary type="html">&lt;p&gt;A tutorial that demonstrates a zero-server, interactive 3D rendering notebook and walks through the quick and easy …&lt;/p&gt;
</summary><content type="html">&lt;p&gt;A tutorial that demonstrates a zero-server, interactive 3D rendering notebook and walks through the quick and easy configuration that can be customized to your needs.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;By: Matt McCormick, Brianna Major, Jeremy Tuloup, Wei Ouyang, Stephen Aylward&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Zero-install&lt;/strong&gt; web applications have transformed the way we consume and deliver software. Browser-based interfaces facilitate rapid discovery, exploration, and universal access.&lt;/p&gt;
&lt;p&gt;However, for research software engineers (RSEs), developing traditional software stacks for web applications is not only onerous, but those stacks may limit essential future scalability and may be even more onerous to sustain. A RSE must face difficult questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Who is going to pay to keep the servers online?&lt;/li&gt;
&lt;li&gt;Who is going to pay to scale the servers for many user or datasets?&lt;/li&gt;
&lt;li&gt;When are you going to find the time to learn and keep up-to-date with all the devops knowledge and skills required?&lt;/li&gt;
&lt;li&gt;Who is going to maintain the system and address security vulnerabilities as they arise?&lt;/li&gt;
&lt;li&gt;How is private data on the server managed and kept secure?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As one of my favorite professors used to say, in cases like this we can look to the advice offered by a wise doctor:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Patient: Oh, Doctor, it hurts badly when I move my knee like this.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Doctor: Stop moving your knee like that!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In some cases, components of the traditional web application software stack are necessary, and some of those components are easier, more scalable, and more sustainable than others. However, for many RSE use cases, we now can create useful web applications while avoiding traditional server-related hardships altogether.&lt;/p&gt;
&lt;p&gt;In this tutorial, we will demonstrate how to create a &lt;strong&gt;zero-server&lt;/strong&gt; JupyterLite deployment that embeds interactive 3D renderings into advanced scientific applications, such as for deep learning medical image analysis applications using &lt;a href="https://monai.io"&gt;MONAI&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://jupyterlite.readthedocs.io/en/latest/"&gt;JupyterLite&lt;/a&gt; is a &lt;a href="https://jupyter.org"&gt;JupyterLab&lt;/a&gt; distribution that runs entirely in the browser built from the ground-up using JupyterLab components and extensions. JupyterLite uses a &lt;a href="https://blog.jupyter.org/webassembly.org"&gt;WebAssembly&lt;/a&gt;-based distribution of scientific Python called &lt;a href="https://pyodide.org/en/stable/"&gt;Pyodide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://itkwidgets.readthedocs.io/"&gt;ITKWidgets&lt;/a&gt; provides interactive widgets to visualize images, point sets, and 3D geometry on the web. ITKWidgets is powered by the same WebAssembly technology. It is built on &lt;a href="https://wasm.itk.org"&gt;ITK-Wasm&lt;/a&gt; and &lt;a href="https://imjoy.io/"&gt;ImJoy&lt;/a&gt;, a hybrid computing platform that communicates via symmetrical transparent remote procedure calls. ImJoy and ITKWidgets support browser-based Pyodide communication along with a number of additional server-client communication transport mechanisms.&lt;/p&gt;
&lt;p&gt;In this tutorial, we will first demonstrate a zero-server, interactive 3D rendering notebook. Then, we walk through the quick and easy configuration that can be customized to your needs. Let’s get started! 🚀&lt;/p&gt;
&lt;h3 id="0-preliminaries"&gt;0. Preliminaries&lt;/h3&gt;
&lt;p&gt;Reproduce the figure below, a rendering of medical imaging volume of an abdominal aortic stent, by &lt;a href="https://jupyterlite-itkwidgets-config-post.netlify.app/lab/index.html?path=Hello3DWorld.ipynb"&gt;running the notebook in your web browser&lt;/a&gt;! After the page has loaded, use the standard &lt;code&gt;Shift+Enter&lt;/code&gt; keys to execute the Jupyter notebook cells.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="a medical imaging volume of an abdominal aortic stent rendered in JupyterLite" src="https://jasongrout.github.io/medium-archive/pelican/posts/2023/embed-interactive-itkwidgets-3d-renderings-into/images/001-0__zowwA1kefuHdpEX.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;a medical imaging volume of an abdominal aortic stent rendered in JupyterLite&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Note that unlike other Jupyter deployments, the python code runs on your system instead of a server.&lt;/p&gt;
&lt;h3 id="1-create-the-jupyterlite-environment"&gt;1. Create the JupyterLite environment&lt;/h3&gt;
&lt;p&gt;To build our sustainable JupyterLite deployment, we will use &lt;a href="https://github.com/conda-forge/miniforge"&gt;a Python environment&lt;/a&gt; that contains Python packages for:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;jupyterlite&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;imjoy_jupyterlab_extension&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Any other JupyterLab federated extensions (JupyterLab 3 extensions) that you want in your JupyterLab deployment.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Create a &lt;em&gt;requirements.txt&lt;/em&gt; file with:&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;jupyterlite&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="o"&gt;]==&lt;/span&gt;&lt;span class="mf"&gt;0.1.0&lt;/span&gt;&lt;span class="n"&gt;b17&lt;/span&gt;
&lt;span class="n"&gt;imjoy_jupyterlab_extension&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And install the packages:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;python -m pip install -r ./requirements.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;See also the related &lt;a href="https://jupyterlite.readthedocs.io/en/latest/howto/configure/simple_extensions.html"&gt;JupyterLite extension addition documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="2-add-itkwidgets-and-other-python-packages"&gt;2. Add itkwidgets and other Python packages&lt;/h3&gt;
&lt;p&gt;Next, we will add &lt;em&gt;itkwidgets&lt;/em&gt;, its dependencies, and other Python packages and their dependencies, that we wish to include into the JupyterLite configuration for deployment. These packages, along with &lt;a href="https://github.com/pyodide/pyodide/tree/main/packages"&gt;the packages available in the Pyodide distribution&lt;/a&gt;, will be available in the deployed site.&lt;/p&gt;
&lt;p&gt;Create a &lt;em&gt;jupyterlite_config.json&lt;/em&gt; file, which specifies the locations of the itkwidgets wheel Python packages. Add other desired packages and their dependencies as follows.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;PipliteAddon&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;piplite_urls&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;https://files.pythonhosted.org/packages/4c/ee/56f970ca26375176d3e4885f58471a12d5a6794bcefe8ad0ccb8d7158ca3/itkwasm-1.0b82-py3-none-any.whl&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;https://files.pythonhosted.org/packages/6c/55/c3fc7e2b9671d15f0c0becdcb9fad6c330172988744ad6eaa17b71bace88/imjoy_rpc-0.5.16-py3-none-any.whl&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;https://files.pythonhosted.org/packages/69/d9/5a6c8af2f4b4f49a809ae316ae4c12937d7dfda4e5b2f9e4167df5f15c0e/imjoy_utils-0.1.2-py3-none-any.whl&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;https://files.pythonhosted.org/packages/c9/dc/3504845528418aff0b71f4b622bb0e8e12adec2d8f2c1ba21d695b9ac6e6/itkwidgets-1.0a24-py3-none-any.whl&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;https://files.pythonhosted.org/packages/bb/3e/3667ac685ae83887b874896bcb55584797ba6b52a292df3e4b37736a9610/ngff_zarr-0.1.6-py3-none-any.whl&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="w"&gt;    &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;p&gt;You can find links to these URLs by browsing the package on &lt;a href="https://pypi.org"&gt;PyPI&lt;/a&gt; and copying the link from the &lt;em&gt;Download files&lt;/em&gt; page for a package.&lt;/p&gt;
&lt;p&gt;For packages that do not have a wheel on PyPI, you can provide one locally by placing them in the &lt;em&gt;pypi/&lt;/em&gt; directory of your JupyterLite configuration. For example, if you want to use a local version of itkwidgets instead of the version on PyPi, you could directly add &lt;a href="https://github.com/InsightSoftwareConsortium/itkwidgets/raw/2baa8ec865d4c08a4749cc468579742448e524c7/docs/jupyterlite/pypi/dask_image-2022.9.0-py2.py3-none-any.whl"&gt;this &lt;code&gt;dask-image&lt;/code&gt; wheel&lt;/a&gt; to your &lt;em&gt;pypi/&lt;/em&gt; directory.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;pypi/
pypi/dask_image-2022.9.0-py2.py3-none-any.whl
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="3-add-notebooks-and-data"&gt;3. Add notebooks and data&lt;/h3&gt;
&lt;p&gt;Add notebooks and data you would like available in the deployment in the &lt;em&gt;files/&lt;/em&gt; directory. In this tutorial, we will add a &lt;a href="https://github.com/InsightSoftwareConsortium/itkwidgets/raw/2baa8ec865d4c08a4749cc468579742448e524c7/docs/jupyterlite/files/Hello3DWorld.ipynb"&gt;&lt;em&gt;Hello3DWorld.ipynb&lt;/em&gt; notebook&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="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;files/
files/Hello3DWorld.ipynb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In your notebook, install additional packages in the first cell with &lt;code&gt;piplite&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;piplite&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;piplite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;itkwidgets==1.0a24&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="4-build-and-deploy"&gt;4. Build and deploy&lt;/h3&gt;
&lt;p&gt;Build your site with the command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;jupyter lite build
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Serve the site locally with &lt;code&gt;python -m http.server --directory ./_output&lt;/code&gt; or:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;jupyter lite serve
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The site can be deployed and shared with free static file hosting services such as &lt;a href="https://jupyterlite.readthedocs.io/en/latest/quickstart/deploy.html"&gt;GitHub Pages&lt;/a&gt;, &lt;a href="https://jupyterlite.readthedocs.io/en/latest/howto/deployment/vercel-netlify.html"&gt;Netlify&lt;/a&gt;, or &lt;a href="https://fleek.co/"&gt;Fleek&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="whats-next"&gt;What’s Next&lt;/h3&gt;
&lt;p&gt;In this post, we learned how to create a scalable, sustainable, zero-server Jupyter deployment that uses ITKWidgets for 3D rendering. In subsequent posts, we will discuss how to create simple, zero-server, custom web applications written in Python with &lt;a href="https://pyscript.net/"&gt;PyScript&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Enjoy ITK!&lt;/strong&gt;&lt;/p&gt;
</content><category term="JupyterLite"/><category term="visualization"/></entry><entry><title>Looking at notebooks from a new perspective</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2021/looking-at-notebooks-from-a-new-perspective/" rel="alternate"/><published>2021-10-05T08:33:00+00:00</published><updated>2021-10-05T09:48:00+00:00</updated><author><name>Mariana Meireles</name></author><id>tag:jasongrout.github.io,2021-10-05:/medium-archive/pelican/posts/2021/looking-at-notebooks-from-a-new-perspective/</id><summary type="html">&lt;p&gt;How to better communicate with Jupyter notebooks&lt;/p&gt;
</summary><content type="html">&lt;figure&gt;
&lt;img alt="Illustration by Juliette Taka" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/looking-at-notebooks-from-a-new-perspective/images/001-1_g3OWLubcUFgVIGBfPYztJQ.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Illustration by &lt;a href="http://juliettetaka.com"&gt;Juliette Taka&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Jupyter notebooks are a great tool for practitioners of scientific computing from the research phase of their work to the communication of their results. The interleaving of code and rich text makes notebooks an ideal tool to communicate the complex ideas underlying computational concepts. However, depending on the context, we might want to look at the same source material (the notebook document) with different glasses, to present the content as a slideshow, or to audiences who are not comfortable with code.&lt;/p&gt;
&lt;p&gt;One may also want to provide statically-rendered content rather than a fully-fledged executable notebook for security reasons. For each context, we should be able to adapt the notebook’s aesthetics and behavior to our needs.&lt;/p&gt;
&lt;p&gt;Fortunately, the Jupyter ecosystem offers a broad range of tools to give a new face to notebooks and adjust them to one’s needs.&lt;/p&gt;
&lt;h2 id="panoramic-view-of-visualization-tools-on-the-jupyter-ecosystem"&gt;Panoramic view of visualization tools on the Jupyter ecosystem&lt;/h2&gt;
&lt;p&gt;The two main tools in the Jupyter ecosystem for rendering notebooks in a customized fashion are &lt;strong&gt;nbconvert&lt;/strong&gt; and &lt;strong&gt;Voilà&lt;/strong&gt;. In this post, we go over the differences and similarities between these two tools.&lt;/p&gt;
&lt;p&gt;nbconvert and Voilà have the same conversion process, the main difference lies in the outcome generated by each tool. While nbconvert outputs static, non-interactive documents, Voilà converts your notebook to a fully interactive application and the way it achieves that is by keeping a Jupyter kernel active at all times.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Simplified scheme of nbconvert and Voilà’s internals" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/looking-at-notebooks-from-a-new-perspective/images/002-1_zvARwLB6MAyyb4Q_K4Gx3w.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Simplified scheme of nbconvert and Voilà’s internals&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Whichever is the format you chose to generate your notebook, end-users won’t be able to execute arbitrary code, providing a secure way of sharing your results with others.&lt;/p&gt;
&lt;h3 id="nbconvert"&gt;&lt;strong&gt;nbconvert&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/jupyter/nbconvert"&gt;Nbconvert&lt;/a&gt; converts notebooks to various other formats via &lt;a href="http://jinja.pocoo.org/"&gt;Jinja&lt;/a&gt; templates. It allows you to convert a &lt;code&gt;.ipynb&lt;/code&gt; notebook file into various static formats:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HTML&lt;/li&gt;
&lt;li&gt;LaTeX&lt;/li&gt;
&lt;li&gt;PDF&lt;/li&gt;
&lt;li&gt;Markdown document&lt;/li&gt;
&lt;li&gt;ReStructured Text&lt;/li&gt;
&lt;li&gt;Executable Script&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;nbconvert is a very versatile tool and can be used not only with the purpose of sharing your code and/or results with peers but also to create tests instances for your Jupyter notebooks and even generate blog posts. You can find more information about its possibilities in the &lt;a href="https://nbconvert.readthedocs.io"&gt;docs&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="voila"&gt;&lt;strong&gt;Voilà&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/voila-dashboards/voila"&gt;Voilà&lt;/a&gt; brings the versatility of nbconvert while allowing you to interact with your code outputs safely both in the Notebook and Lab interface.&lt;/p&gt;
&lt;p&gt;As pointed out before, Voilà keeps a Jupyter kernel instance running at all times. It is language-agnostic and it will run any language supported by Jupyter. Furthermore, as it encapsulates nbconvert, Voilà is capable of converting the notebook to any of its output formats as well as make use of all of the templates that come with nbconvert.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Rendering interactive Matplotlib figures in a web application with Voilà. Source." src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/looking-at-notebooks-from-a-new-perspective/images/003-0_OtsvahHJvfEvcziO.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Rendering interactive Matplotlib figures in a web application with Voilà. &lt;a href="/posts/2019/and-voila/"&gt;Source&lt;/a&gt;.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;You will notice that Voilà expands on the default templates: from simple one-page documents to complex grid-based dashboards and slideshows.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Grid template generated by Voilà" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/looking-at-notebooks-from-a-new-perspective/images/004-1_Fh9khuZcEG98Fz1F-AZ83A.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Grid template generated by Voilà&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="slideshows-with-jupyter"&gt;Slideshows with Jupyter&lt;/h2&gt;
&lt;p&gt;A common use case is to share the results as a slideshow. Let’s look at the different ways to do so.&lt;/p&gt;
&lt;p&gt;The first step to set up your slideshow is to define the mapping between cells and slides. This mapping is saved in the cell metadata of the notebook, and JupyterLab has the appropriate built-in tool to edit this information.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Different kinds of metadata that can be added to a cell on JupyterLab" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/looking-at-notebooks-from-a-new-perspective/images/005-1_7psFVJ14ekqdgi7n3ZwS-Q.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Different kinds of metadata that can be added to a cell on JupyterLab&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The classic notebook offers a similar interface to edit the notebook metadata. Then, to visualize the resulting slideshow, several tools are available:&lt;/p&gt;
&lt;h3 id="rise"&gt;RISE&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://github.com/damianavila/RISE"&gt;RISE&lt;/a&gt; is a classic notebook extension that provides a toolbar button to turn the notebook into a slideshow in the main notebook UI.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="RISE from the notebook to slides. Source." src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/looking-at-notebooks-from-a-new-perspective/images/006-0_eDvRenHayEmKFjfN.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;RISE from the notebook to slides. &lt;a href="https://github.com/damianavila/RISE"&gt;Source&lt;/a&gt;.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Unlike the other solutions presented here, RISE slideshows are still executable in the same way as the notebook, which can be a great feature when teaching a class. However, RISE may not be an appropriate tool to share such a slideshow online because it requires giving access to a notebook server.&lt;/p&gt;
&lt;p&gt;Unfortunately, despite the &lt;a href="https://github.com/damianavila/RISE/pull/381"&gt;effort&lt;/a&gt; of the community RISE still doesn’t offer support for JupyterLab.&lt;/p&gt;
&lt;h3 id="nbconvert-1"&gt;&lt;strong&gt;nbconvert&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;Another solution is to use the &lt;strong&gt;Reveal&lt;/strong&gt; template of nbconvert, which will use the same cell metadata as RISE to produce a static slideshow.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;nbconvert presentation.ipynb --to html --template reveal
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Unlike with RISE, for which cells remain executable, the outcome of nbconvert is a static HTML file, and only the already-computed outputs will be displayed.&lt;/p&gt;
&lt;h3 id="voila-1"&gt;Voilà&lt;/h3&gt;
&lt;p&gt;Just like with nbconvert, the Reveal template can be used with Voilà with the &lt;strong&gt;&lt;code&gt;--template reveal&lt;/code&gt;&lt;/strong&gt; command-line argument.&lt;/p&gt;
&lt;p&gt;Using Voilà instead of nbconvert will spawn a kernel for each connected user, enabling the use of interactive widgets in the resulting slideshow to interact with the backend.&lt;/p&gt;
&lt;p&gt;Besides, the default behavior of Voilà is to hide input cells and only display markdown cells and output.&lt;/p&gt;
&lt;h3 id="whats-new-dejavu"&gt;What’s new: Déjàvu!&lt;/h3&gt;
&lt;p&gt;Déjàvu is a new utility included in nbconvert 6.2, which simply specifies new default values for several options so as to mimick Voilà’s behavior with respect to hiding input cells and prompt numbers. However, these defaults can still be overwritten by the end-user. You can do it just like you would if you were using nbconvert.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;jupyter dejavu notebook.ipynb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;figure&gt;
&lt;img alt="Déjàvu output (on the left) and Voilà output (on the right)" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/looking-at-notebooks-from-a-new-perspective/images/007-1_DqBf2bE3M7ynUy-Kv0qIbA.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Déjàvu output (on the left) and Voilà output (on the right)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Voilà and Déjàvu’s outputs are identical, although, in the case of Déjàvu, interactions with widgets that require a roundtrip to the kernel will not work. In contrast, we can see the result of the calculation on the Voilà side.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;To summarize and wrap up:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Déjàvu supports all of the templates available in Voilà, and even though users don’t have access to interactivity they can still benefit from widgets outputs since they’ll be generated and included on the final file;&lt;/li&gt;
&lt;li&gt;When building a slideshow you can use JupyterLab’s interface to define specific metadata to your cells;&lt;/li&gt;
&lt;li&gt;You can also see your code in Déjàvu’s outputs. Just pass the &lt;code&gt;--show-input&lt;/code&gt; option to the command line.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="acknowledgments"&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;Thanks to &lt;a href="http://juliettetaka.com"&gt;Juliette Taka&lt;/a&gt; for creating the illustrations for this blog post.&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/looking-at-notebooks-from-a-new-perspective/images/008-1_xbhgaimjN9YclTKtIQojGQ.jpg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;My name is &lt;a href="https://twitter.com/mari_meir"&gt;Mariana Meireles&lt;/a&gt;, I’m a software engineer working for &lt;a href="http://quantstack.net/"&gt;QuantStack&lt;/a&gt;. I care deeply about the impacts that technology has in the world and try my best to be the change I want to see by contributing to open source projects that stand upon libre and diverse standards.&lt;br&gt;
I’m currently focusing on the Jupyter ecosystem and advocating for open science and open knowledge whenever I can.&lt;/p&gt;
</content><category term="visualization"/><category term="Voilà"/></entry><entry><title>Genomic data visualization in Jupyter</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2021/genomic-data-representation-in-jupyter/" rel="alternate"/><published>2021-02-08T13:29:00+00:00</published><updated>2021-02-11T11:36:00+00:00</updated><author><name>Jean-David Harrouet</name></author><id>tag:jasongrout.github.io,2021-02-08:/medium-archive/pelican/posts/2021/genomic-data-representation-in-jupyter/</id><summary type="html">&lt;p&gt;If there is one thing that recent events tell us, it is that genomic is a large source of data, and that its manipulation and…&lt;/p&gt;
</summary><content type="html">&lt;p&gt;If there is one thing that recent events tell us, it is that genomics is a large source of data, and that its manipulation and understanding allow for the quick development of new drugs and… vaccines.&lt;/p&gt;
&lt;p&gt;We decided to build upon the Jupyter ecosystem and enrich its capabilities in this space, with a genomics data visualization widget.&lt;/p&gt;
&lt;p&gt;In doing so, we chose to leverage the &lt;a href="https://github.com/igvteam/igv.js/"&gt;&lt;code&gt;igv.js&lt;/code&gt;&lt;/a&gt; JavaScript library, developped by the &lt;a href="https://igv.org/"&gt;Integrative Genomics Viewer (IGV)&lt;/a&gt; team, and used by &lt;a href="https://igv.org/app/"&gt;the web app of the same name&lt;/a&gt;. This is all done thanks for the power of &lt;code&gt;ipywidgets&lt;/code&gt; , which helps linking the JS genomic representation object to our Jupyter notebook.&lt;/p&gt;
&lt;p&gt;Hence, we are proud to announce the release of &lt;a href="https://github.com/QuantStack/ipyigv"&gt;&lt;code&gt;ipyigv&lt;/code&gt;&lt;/a&gt;, a Jupyter widget to render genomics data, based on &lt;code&gt;igv.js&lt;/code&gt;!&lt;/p&gt;
&lt;h2 id="installing-ipyigv"&gt;Installing ipyigv&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;ipyigv&lt;/code&gt; is available on PyPI and conda-forge. It can be installed with both pip and &lt;a href="https://github.com/mamba-org/mamba"&gt;mamba&lt;/a&gt; / &lt;a href="https://github.com/conda/conda"&gt;conda&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 ipyigv
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can find additional installation instruction on the &lt;a href="https://github.com/QuantStack/ipyigv"&gt;project’s page on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="rendering-genomic-data"&gt;Rendering genomic data&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;igv.js&lt;/code&gt; consumes genomic data in two chunks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the genome itself as documented &lt;a href="https://github.com/igvteam/igv.js/wiki/Reference-Genome"&gt;here&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;specificities of the genome underlined as &lt;code&gt;Tracks&lt;/code&gt;, which are displayed alongside or on top of the genome&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;ipyigv&lt;/code&gt; uses the same logic, with a helper function to use the public genomes available. Data is then displayed in an &lt;code&gt;IgvBrowser&lt;/code&gt; widget, a wrapper for the &lt;code&gt;igv.js&lt;/code&gt; browser.&lt;/p&gt;
&lt;p&gt;To make things easier, there are a few public genomes made directly available via a helper &lt;code&gt;Bunch&lt;/code&gt; , &lt;code&gt;PUBLIC_GENOMES&lt;/code&gt; .&lt;/p&gt;
&lt;p&gt;Here is what it looks like:&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Creating a genome browser with data from a public genome" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/genomic-data-representation-in-jupyter/images/001-1_fxJcZt6CBqZodRKm-k9vBA.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Creating a genome browser with data from a public genome&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Now that we have created a genome browser, we may add tracks to it. Tracks may be of different sorts, about ten according to &lt;a href="https://github.com/igvteam/igv.js/wiki/Tracks-2.0"&gt;the &lt;code&gt;igv.js&lt;/code&gt; documentation&lt;/a&gt;. Describing all the kinds of tracks is out of the scope of this article, but it should be noted that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a common &lt;code&gt;Track&lt;/code&gt; class is defined with all the common properties. Each track type corresponds to a subclass inheriting &lt;code&gt;Track&lt;/code&gt; .&lt;/li&gt;
&lt;li&gt;in order to ease things out, some class introspection was introduced in order to identify the type of &lt;code&gt;Track&lt;/code&gt; based on the extension of the containing file. As shown below, this allows for instantiating a track by just using the &lt;code&gt;Track&lt;/code&gt; constructor, without knowing the name of the actual subclass being instantiated (e.g. &lt;code&gt;AnnotationTrack&lt;/code&gt; in the example below). Type inference is made through the type of file, or by specifying a &lt;code&gt;type&lt;/code&gt; property.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, let’s add a &lt;code&gt;Track&lt;/code&gt; to our browser, then remove it:&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Adding and removing a track to/from our browser" src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/genomic-data-representation-in-jupyter/images/002-1_681fIddZAaQc8w72MmmIiw.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Adding and removing a track to/from our browser&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;In this first version, two other functions come in as handy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;browser.search('chr3:1-190,100,300')&lt;/code&gt; would position the browser at the requested position in the genome;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;browser.dump_json()&lt;/code&gt; prepares a JSON representing the configuration of the browser. Handy if you would like to reinstantiate another browser with the same configuration without redoing it manually. Use &lt;code&gt;browser.out&lt;/code&gt; to output the JSON content.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We hope you’ll have fun manipulating genome data in Jupyter, and sharing visual knowledge thanks to &lt;code&gt;ipyigv&lt;/code&gt;!&lt;/p&gt;
&lt;h2 id="acknowledgments"&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;The development of ipyigv by &lt;a href="https://twitter.com/Harr0uet"&gt;Jean-David Harrouet&lt;/a&gt; at &lt;a href="https://twitter.com/QuantStack"&gt;QuantStack&lt;/a&gt; was funded as part of the &lt;a href="https://twitter.com/PlasmaBio"&gt;PLASMA&lt;/a&gt; project, led by &lt;a href="https://twitter.com/CVandiedonck"&gt;Claire Vandiedonck&lt;/a&gt;, &lt;a href="https://twitter.com/pierrepo"&gt;Pierre Poulain&lt;/a&gt;, and &lt;a href="https://twitter.com/SCaburet"&gt;Sandrine Caburet&lt;/a&gt;, associate professors at Université de Paris.&lt;/p&gt;
&lt;p&gt;Sponsors to the PLASMA initiative include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://twitter.com/iledefrance"&gt;Région Île-de-France&lt;/a&gt;, via the “Trophées franciliens de l’innovation numérique dans le supérieur” (&lt;a href="https://www.iledefrance.fr/trophees-franciliens-de-linnovation-numerique-dans-le-superieur-les-laureats-2018"&gt;EdTech 2018&lt;/a&gt;) grant program,&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/Univ_Paris"&gt;Université de Paris&lt;/a&gt;, via the &lt;a href="https://u-paris.fr/en/the-initiative-of-excellence-idex-label/"&gt;Initiative of Excellence (IdEx) Label&lt;/a&gt; and its “inovating teaching” grant program,&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/EURGENEPARIS"&gt;EUR G.E.N.E.&lt;/a&gt;, the graduate school on Genetics and Epigenetics,&lt;/li&gt;
&lt;li&gt;the university training “Création, analyse et valorisation de données biologiques omiques” (&lt;a href="https://omics-school.net/"&gt;DU Omiques&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="about-the-author"&gt;About the author&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.linkedin.com/in/harrouet/"&gt;Jean-David Harrouet&lt;/a&gt; is an innovator helping companies with their digital transformation.&lt;/p&gt;
&lt;p&gt;He believes that the right mix of coding and business acumen is a way to make life better for many people.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2021/genomic-data-representation-in-jupyter/images/003-1_wACAwVx0PZAsEH8myXyUqg.jpeg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
</content><category term="science"/><category term="visualization"/></entry><entry><title>A C++ API for Vega-Lite</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2020/a-c-backend-for-vega-lite/" rel="alternate"/><published>2020-12-02T15:27:00+00:00</published><updated>2020-12-03T14:23:00+00:00</updated><author><name>Madhur Tandon</name></author><id>tag:jasongrout.github.io,2020-12-02:/medium-archive/pelican/posts/2020/a-c-backend-for-vega-lite/</id><summary type="html">&lt;p&gt;In this post, we present the first public release of XVega, a C++ library for producing vega-lite charts.&lt;/p&gt;
</summary><content type="html">&lt;p&gt;&lt;em&gt;In this post, we present the first public release of XVega, a C++ library for producing Vega-Lite charts.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Data science workflows differ from traditional software development in that engineers make use of available tools to &lt;em&gt;explore&lt;/em&gt; and &lt;em&gt;reason&lt;/em&gt; about a problem. In such exploratory work, engineers load data, crunch numbers, produce simple visualizations and &lt;em&gt;iterate…&lt;/em&gt; Progress happens in quick incremental iterations, which is possible when tooling does not get in the way.&lt;/p&gt;
&lt;p&gt;This kind of interactive computing is generally associated with the Python or R programming languages. However, with the advent of the &lt;a href="https://github.com/root-project/cling/"&gt;&lt;strong&gt;Cling&lt;/strong&gt;&lt;/a&gt; C++ interpreter from &lt;a href="https://home.cern/"&gt;CERN&lt;/a&gt;, and the subsequent development of the &lt;a href="https://github.com/jupyter-xeus/xeus-cling"&gt;&lt;strong&gt;xeus-cling&lt;/strong&gt;&lt;/a&gt; Jupyter kernel, new possibilities have opened up in this space.&lt;/p&gt;
&lt;p&gt;The Jupyter stack — that started in the scientific Python community has evolved into a language-agnostic framework that can now be leveraged by C++ developers. It bridges the gap between the countless scientific computing libraries and tools available in C++ and the Jupyter ecosystem.&lt;/p&gt;
&lt;p&gt;The scientific C++ stack now has numerous projects under its belt — such as &lt;a href="https://github.com/xtensor-stack/xtensor"&gt;xtensor&lt;/a&gt;, &lt;a href="https://github.com/xtensor-stack/xframe"&gt;xframe&lt;/a&gt;, etc. However, there is little support for visualization — especially for interactive plots. While there exist &lt;a href="https://github.com/lava/matplotlib-cpp"&gt;matplotlib-cpp&lt;/a&gt; and &lt;a href="https://github.com/alandefreitas/matplotplusplus"&gt;matplotplusplus&lt;/a&gt; (with their plotting API resembling the original &lt;a href="https://github.com/matplotlib/matplotlib"&gt;matplotlib&lt;/a&gt; library) — they suffer from the same cons as the original library does (such as the imperative API and the confusion between dual object-oriented and state-based interface).&lt;/p&gt;
&lt;p&gt;Owing to all these shortcomings, along with the observation that JupyterLab comes with existing support for Vega and Vega-Lite Charts (through the &lt;a href="https://jupyterlab.readthedocs.io/en/stable/user/file_formats.html#vega-vega-lite"&gt;&lt;code&gt;application/vnd.vegalite.v3+json&lt;/code&gt;&lt;/a&gt; MIME type), one can leverage this support to bridge the gap rather than reinvent the wheel. Apart from standalone use — one could also integrate such a system into other projects such as &lt;a href="https://github.com/jupyter-xeus/xeus-sqlite"&gt;xeus-SQLite&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The main idea is to programmatically fill in a JSON that conforms to the Vega-Lite specification and respects the notion of grammar of graphics. It is analogous to what &lt;a href="https://github.com/altair-viz/altair"&gt;Altair&lt;/a&gt; did for Python. We will expose different APIs responsible for filling in certain parts of the JSON.&lt;/p&gt;
&lt;p&gt;The fundamentals with XVega are still the same, i.e. the three essential elements of a &lt;em&gt;Chart&lt;/em&gt; are &lt;em&gt;Data, Marks and Encodings&lt;/em&gt; as usual and importing the library is as simple as writing two statements:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;quot;xvega/xvega.hpp&amp;quot;&lt;/span&gt;
&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;&lt;span class="n"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;xv&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The experience is similar to what Altair offers and, hence, the central piece to the library is the &lt;em&gt;&lt;strong&gt;Chart()&lt;/strong&gt;&lt;/em&gt; object — which knows how to emit the JSON dictionary representing the data and visualization encodings.&lt;/p&gt;
&lt;p&gt;For those unfamiliar with the Vega ecosystem, a quick recap for the above terms is given below:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;Marks&lt;/strong&gt;&lt;/em&gt; — What graphic should represent the data?&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;Encodings&lt;/strong&gt;&lt;/em&gt; — Mapping between Data and Visual Elements of the Chart (such as x-axis, etc.).&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;Encoding Types&lt;/strong&gt;&lt;/em&gt;: &lt;em&gt;&lt;strong&gt;Quantitative&lt;/strong&gt;&lt;/em&gt; (real-valued), &lt;em&gt;&lt;strong&gt;Nominal&lt;/strong&gt;&lt;/em&gt; (unordered categorical), &lt;em&gt;&lt;strong&gt;Ordinal&lt;/strong&gt;&lt;/em&gt; (ordered categorical), &lt;em&gt;&lt;strong&gt;Temporal&lt;/strong&gt;&lt;/em&gt; (time-series).&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
&lt;img alt="Basic usage of XVega showcasing the essential elements — Data, Marks and Encodings." src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/a-c-backend-for-vega-lite/images/001-1_GCkpVPeF-s7-64hNzyOcjg.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Basic usage of XVega showcasing the essential elements — Data, Marks and Encodings.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The core strength of using such a system is the separation of specification and execution. The declarative API makes it easy to specify “&lt;em&gt;&lt;strong&gt;what&lt;/strong&gt;&lt;/em&gt;” should be done rather than focus on incidental details of the “&lt;em&gt;&lt;strong&gt;how&lt;/strong&gt;&lt;/em&gt;”. It means that rather than having a special “&lt;em&gt;&lt;strong&gt;hist()&lt;/strong&gt;&lt;/em&gt;” function for plotting a histogram, passing “&lt;em&gt;&lt;strong&gt;bin=True&lt;/strong&gt;&lt;/em&gt;” does the job.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Simply stating bin=True bins the x-axis giving us the Histogram directly — without using a dedicated function." src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/a-c-backend-for-vega-lite/images/002-1_t3w0G2XCiNBw3VajHbGiCw.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Simply stating &lt;strong&gt;bin=True&lt;/strong&gt; bins the x-axis giving us the Histogram directly — without using a dedicated function.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;We can of-course customize the binning parameters with a “&lt;em&gt;&lt;strong&gt;Bin()&lt;/strong&gt;&lt;/em&gt;” object instead. And while we are doing that, let’s add a colour encoding as well to get a sense of the 3rd dimension.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="More control can be achieved using a custom Bin() object — used to set the binning parameters." src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/a-c-backend-for-vega-lite/images/003-1_UkIPGquufhYT7-S62MTECg.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;More control can be achieved using a custom &lt;strong&gt;Bin()&lt;/strong&gt; object — used to set the binning parameters.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Another plus of using Vega-Lite is the possibility of using transformations within the specification rather than doing it before.&lt;br&gt;
(E.g., one can do linear regression as a part of this declarative API).&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Usage of layering and transformations in XVega." src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/a-c-backend-for-vega-lite/images/004-1_2jpd8rcTdgnLq8fBwL0XXA.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Usage of layering and transformations in XVega.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Lastly, support for &lt;em&gt;&lt;strong&gt;Interactions&lt;/strong&gt;&lt;/em&gt; and &lt;em&gt;&lt;strong&gt;Selections&lt;/strong&gt;&lt;/em&gt; is a no-brainer. It’s as simple as defining what to use and adding it to the &lt;em&gt;&lt;strong&gt;Chart()&lt;/strong&gt;&lt;/em&gt; object.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Zooming and Panning along with Tooltips using Interval Selection in XVega" src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/a-c-backend-for-vega-lite/images/005-1_AQTFHOwHXS3uJUC6WKR6WA.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Zooming and Panning along with Tooltips using Interval Selection in XVega&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;hr&gt;
&lt;p&gt;Developing such a system for C++ comes with its own challenges and to provide a seamless experience like &lt;em&gt;Altair&lt;/em&gt;, several things are needed to be taken care of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Multiple types for a single entity:&lt;/strong&gt; the Vega-Lite specification allows variables of different kinds (such as a boolean type and an integer type may be equally valid for a particular property). &lt;em&gt;&lt;strong&gt;Variants&lt;/strong&gt;&lt;/em&gt; and &lt;em&gt;&lt;strong&gt;Visitors&lt;/strong&gt;&lt;/em&gt; in C++ allow us to achieve this.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Out of order keyword arguments:&lt;/strong&gt; Method chaining is the classical approach to tackle out-of-order keyword arguments in C++ and is what is used in &lt;em&gt;&lt;strong&gt;XVega&lt;/strong&gt;&lt;/em&gt; indeed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optional fields:&lt;/strong&gt; A lot of values in the Vega-Lite specification are optional, and this is made possible by the optionally contained values in C++ (i.e. using &lt;em&gt;std::optional&lt;/em&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id="installation"&gt;&lt;strong&gt;Installation&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;You can install XVega 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 xvega
&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 xvega
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;hr&gt;
&lt;h3 id="what-is-coming"&gt;What is coming?&lt;/h3&gt;
&lt;p&gt;XVega is still at an early stage and under active development. We are currently working on integrating it with the &lt;a href="https://github.com/jupyter-xeus/xeus-sqlite"&gt;xeus-sqlite&lt;/a&gt; and other SQL Jupyter kernels to enable the visualization from SQL queries. We are also working on improving the compilation time of XVega with Cling.&lt;/p&gt;
&lt;h3 id="acknowledgements"&gt;Acknowledgements&lt;/h3&gt;
&lt;p&gt;This work on XVega was funded by &lt;a href="https://twitter.com/QuantStack"&gt;QuantStack&lt;/a&gt;. Thanks to &lt;a href="https://twitter.com/SylvainCorlay"&gt;Sylvain Corlay&lt;/a&gt; and &lt;a href="https://twitter.com/JohanMabille"&gt;Johan Mabille&lt;/a&gt; for their continuous support.&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;It is an exciting time for the interactive C++ ecosystem, as so much innovation is happening in the Cling and Jupyter projects. There is a lot more to come for sure. If you are interested in helping us build that future, come talk to us at &lt;a href="https://gitter.im/QuantStack/Lobby"&gt;Gitter&lt;/a&gt; and &lt;a href="https://github.com/QuantStack/"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&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/a-c-backend-for-vega-lite/images/006-1_smY4K4tEKudPztWWxpBNvw.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;My name is &lt;a href="https://twitter.com/mad_tandon"&gt;Madhur Tandon&lt;/a&gt;, and I currently work with &lt;a href="https://quantstack.net/"&gt;QuantStack&lt;/a&gt; as a Scientific Software Engineer. Before joining QuantStack, I have worked with &lt;a href="https://github.com/iodide-project/pyodide"&gt;Mozilla&lt;/a&gt;, &lt;a href="https://www.deepnote.com/"&gt;Deepnote&lt;/a&gt;, &lt;a href="https://github.com/BIDS-Apps/rsHRF"&gt;INCF&lt;/a&gt; (International Neuroinformatics Coordinating Facility), &lt;a href="https://www.tcs.com/tcs-research"&gt;TCS Research&lt;/a&gt; and &lt;a href="https://elucidata.io/"&gt;Elucidata&lt;/a&gt;. I have also been a speaker at JupyterCon 2020 and PyData Delhi 2017 and 2018. I graduated from &lt;a href="https://iiitd.ac.in/"&gt;IIIT-Delhi&lt;/a&gt; this year with a Bachelor’s degree in Computer Science with Honors. Besides core Data Science and Machine Learning, I am interested in tools that enable and enhance data scientists’ workflow and experience.&lt;/p&gt;
</content><category term="C++"/><category term="visualization"/></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>SlicerJupyter: a 3D Slicer kernel for interactive publications</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2020/slicerjupyter-a-3d-slicer-kernel-for-interactive/" rel="alternate"/><published>2020-07-08T16:29:00+00:00</published><updated>2020-07-08T16:58:00+00:00</updated><author><name>Jean-Christophe Fillion-Robin</name></author><id>tag:jasongrout.github.io,2020-07-08:/medium-archive/pelican/posts/2020/slicerjupyter-a-3d-slicer-kernel-for-interactive/</id><summary type="html">&lt;p&gt;Use Jupyter and 3D Slicer kernel to implement biomedical data processing workflows in a notebook&lt;/p&gt;
</summary><content type="html">&lt;p&gt;The Jupyter ecosystem is a powerful platform for exploratory computational science, and now it can connect with some of the deep and rich domain-specific desktop applications that have decades of feature development already invested in them. With the integration of &lt;a href="https://www.slicer.org/"&gt;3D Slicer&lt;/a&gt; with Jupyter through the &lt;a href="https://github.com/jupyter-xeus/xeus-python"&gt;xeus-python&lt;/a&gt;’s interpreter, we demonstrate how a &lt;a href="https://www.qt.io/"&gt;Qt-based&lt;/a&gt; graphical desktop application with 3D visualization provided by &lt;a href="https://vtk.org/"&gt;Visualization Toolkit (VTK)&lt;/a&gt;, image processing provided by the &lt;a href="https://itk.org/"&gt;Insight Toolkit (ITK)&lt;/a&gt;, can be used through a Jupyter notebook. This approach is available on the &lt;a href="https://github.com/Slicer/SlicerJupyter"&gt;SlicerJupyter&lt;/a&gt; GitHub repository and could be extended to other applications that embed Python, such as Blender, FreeCAD, or ParaView.&lt;/p&gt;
&lt;p&gt;This xeus-python integration is beneficial both for the Jupyter ecosystem and desktop applications. Features that have been developed for decades for desktop applications become readily available for Jupyter users without learning a new working environment or redeveloping features. For a desktop application, the Jupyter notebook can serve as a way to create reproducible data processing workflows, scientific publications, and maintainable tutorials without requiring local software installation. From Jupyter, you can now quickly create simple medical imaging applications with extremely rich interactivity from 3D Slicer. Read below for a discussion of the features available and the history of the project.&lt;/p&gt;
&lt;h2 id="powerful-medical-imaging-capabilities-available-through-jupyter"&gt;Powerful Medical Imaging Capabilities Available Through Jupyter&lt;/h2&gt;
&lt;p&gt;3D Slicer (or Slicer for short) is a C++ desktop application that uses Qt, ITK, and VTK libraries for visualization and medical image analysis. Slicer’s embedded Python interpreter makes all its features accessible with the Python programming language. Slicer has a simple built-in console to run Python commands interactively and can run Python scripts from files, but these are not as convenient as cell-base interactive notebooks, which have become popular among data scientists and researchers in recent years.&lt;/p&gt;
&lt;p&gt;By integrating the xeus-python kernel, we can use a Slicer process as a Jupyter kernel. xeus-python leverages the &lt;a href="https://github.com/jupyter-xeus/xeus"&gt;xeus&lt;/a&gt; C++ implementation of the Jupyter kernel protocol. xeus-python is &lt;a href="/posts/2019/a-new-python-kernel-for-jupyter/"&gt;an alternative to ipykernel&lt;/a&gt;, which can be used with a vanilla CPython interpreter, interfacing to standard CPython Jupyter widgets like &lt;a href="https://github.com/InsightSoftwareConsortium/itkwidgets"&gt;itkwidgets&lt;/a&gt;, but it can also be coupled with custom interpreters and GUI event loops, like the Slicer interpreter and its Qt event loop. This allows you to represent a complete scene in Medical Reality Markup Language, MRML, Slicer’s internal data structure. The kernel exposes the full medical imaging API and representation of your data in a meaningful way for Python developers, allowing access through standard Python ecosystem formats such as pandas dataframes and NumPy arrays in the Notebook.&lt;/p&gt;
&lt;h3 id="interactivity-levels"&gt;Interactivity Levels&lt;/h3&gt;
&lt;p&gt;You can also use Jupyter interactive widgets (sliders, buttons, etc.) to control Slicer, modify data, or adjust processing and visualization parameters. Interactivity can be implemented at different levels.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Level 1&lt;/strong&gt;: Standard Jupyter widgets display application specific objects by automatic conversion of application-specific data objects to standard Python objects. For example, Slicer markup fiducial lists are displayed as a nicely formatted table and model nodes are rendered as 3D objects.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Level 2&lt;/strong&gt;: Static image widgets display content that the desktop application renders. These widgets can be made interactive by modifying data and rendering parameters using additional standard widgets. This makes rich visualization capabilities — sophisticated rendering various data types, rendering of very large data sets, etc. directly available in Jupyter.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Level 3&lt;/strong&gt;: Dynamic viewer widgets display 2D and 3D views rendered by the desktop application. Mouse and keyboard events are forwarded to the desktop application that allows zooming/rotating views, and to utilize all 3D interactions implemented in the desktop such as placing annotations, making measurements, or segmenting images the same way as if it was done on the desktop appication’s screen. This is implemented in the Slicer Jupyter kernel using &lt;a href="https://ipycanvas.readthedocs.io/en/latest/"&gt;ipycanvas&lt;/a&gt; and &lt;a href="https://github.com/mwcraig/ipyevents"&gt;ipyevents&lt;/a&gt; packages.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Level 4&lt;/strong&gt;: Full desktop graphical user interface integration. Users can see parts of the application window rendered in notebook cells, including standard desktop widgets (sliders, menus, etc.). It is implemented using noVNC and TigerVNC in Slicer Jupyter. This is particularly useful when the application runs on a remote server.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/oZ3_cRXX2QM" title="Medical image processing in your web browser using Jupyter notebooks and 3D Slicer" 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;Video demonstrating how to run 3D Slicer using Binder&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;These interactive tools allow developers to implement complete data processing workflows in a notebook, even if certain steps require manual user inputs such as segmenting 3D regions or setting seed points.&lt;/p&gt;
&lt;h3 id="try-it-online"&gt;Try it online!&lt;/h3&gt;
&lt;p&gt;Since Jupyter notebooks can be used from any web browser, it can essentially turn any desktop application to a web application. By setting up a remote Jupyter server, users do not have to install anything on their computers. We have set up a demonstration of this using Binder (&lt;a href="http://www.mybinder.org"&gt;www.mybinder.org&lt;/a&gt;) that anybody can try at &lt;a href="https://mybinder.org/v2/gh/Slicer/SlicerNotebooks/master"&gt;https://mybinder.org/v2/gh/Slicer/SlicerNotebooks/master&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;a href="https://mybinder.org/v2/gh/Slicer/SlicerNotebooks/master"&gt;&lt;img alt="Click on the binder image to launch the demo" src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/slicerjupyter-a-3d-slicer-kernel-for-interactive/images/001-0_powLrWNrbtb0dRWs.webp" loading="lazy" data-body-image=""&gt;&lt;/a&gt;
&lt;figcaption&gt;Click on the binder image to launch the demo&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The docker image that installs and configures Slicer and all dependencies (ipycanvas, ipyevents, VNC, etc.) is available at &lt;a href="https://github.com/Slicer/SlicerDocker/tree/master/slicer-notebook"&gt;https://github.com/Slicer/SlicerDocker/tree/master/slicer-notebook&lt;/a&gt;. For deployment to non-technical users, applications can be deployed using Voilà (&lt;a href="https://voila.readthedocs.io/"&gt;https://voila.readthedocs.io/&lt;/a&gt;), which only shows relevant content and interactive widgets, so the notebook looks like a simple dynamic web page.&lt;/p&gt;
&lt;p&gt;The current implementation is already stable and offers a wide range of features, but there is still room for design and performance improvements. For example, we could not implement fully automatic conversion of application-specific data objects to displayable Python objects (due to complex implementation of display hooks); xeus-python debugger’s threading model needs to be improved to allow using it without locking the application’s main thread; and dynamic viewer widget’s performance (level 3 interaction) could be optimized to achieve higher refresh rates.&lt;/p&gt;
&lt;h2 id="history-of-slicer-and-this-integration"&gt;History of Slicer and this integration&lt;/h2&gt;
&lt;p&gt;Built over two decades with support from the NIH and a worldwide open source developer community, 3D Slicer is a unique, multi-platform desktop application for analysis, integration, and visualization of medical images that is heavily used by researchers globally for basic and applied research in a wide range of topics. The 3D Slicer Community includes physician-scientists with disease-specific knowledge of clinical challenges, computer scientists and physicists who develop novel algorithms, imaging informatics researchers, software engineers with the ability to understand clinical problems and create reliable tools, and application engineers with the multidisciplinary skills to deploy these tools in a range of cancer research settings. Slicer is maintained by Kitware, Inc., and the NAMIC consortium, and has an active open source software community. Slicer is used in hospitals and by researchers, with more than 10k academic citations and more than 150k downloads in the last year alone.&lt;/p&gt;
&lt;figure&gt;
&lt;a href="https://download.slicer.org"&gt;&lt;img alt="Click on the image to download 3D Slicer" src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/slicerjupyter-a-3d-slicer-kernel-for-interactive/images/002-1_ePhHKkjqV-AW0mvDkaeurw.webp" loading="lazy" data-body-image=""&gt;&lt;/a&gt;
&lt;figcaption&gt;Click on the image to download 3D Slicer&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;It can be used for image processing workflows on 2D, 3D, and 4D images. What makes Slicer so useful is its huge set of community contributed modules that extend its functionality, as well as its ability to read DICOM and a wide array of exotic file formats.&lt;/p&gt;
&lt;p&gt;Slicer has been scriptable in Python for well over a decade, but a robust &lt;a href="https://github.com/Slicer/SlicerJupyter"&gt;SlicerJupyter&lt;/a&gt; extension is born from significant development effort by the community. The idea for this integration dates back to SciPy in 2014, when Jean-Christophe Fillion-Robin of Kitware organized a sprint intended to integrate Slicer and an IPython notebook, motivated by the dream of creating interactive and fun tutorials for Slicer. Mike Sarahan and Jean-Christophe created this proof of concept &lt;a href="https://github.com/commontk/QEmbedIPython#qt-embed-ipython"&gt;https://github.com/commontk/QEmbedIPython#qt-embed-ipython&lt;/a&gt;, but it was far from usable. In 2015 Matt McCormick of Kitware, created the &lt;a href="https://github.com/Slicer/SlicerDocker"&gt;SlicerDocker&lt;/a&gt; repository to support headless builds and rendering in a Docker image. Then in June 2018, while attending the Slicer Project Week, Andras Lasso (Queen’s University) and Jean-Christophe learned about Xeus, a C++ implementation of the Jupyter kernel protocol developed by QuantStack that would help streamline the integration of Slicer with Jupyter. To support this effort, Andras and Jean-Christophe created the &lt;a href="https://github.com/Slicer/SlicerJupyter"&gt;Slicer/SlicerJupyter&lt;/a&gt; GitHub repository. They also contributed changes to Xeus to support this new integration paradigm where the event loop of the kernel is driven by a Qt-based Desktop application (see &lt;a href="https://github.com/jupyter-xeus/xeus/pull/63"&gt;here&lt;/a&gt;). Building on this foundation, Isaiah Norton, then working at Brigham and Women’s Hospital, contributed additional improvements like a better auto-completion using jedi (see &lt;a href="https://github.com/Slicer/SlicerJupyter/pull/12"&gt;https://github.com/Slicer/SlicerJupyter/pull/12&lt;/a&gt;) as well as integration with Binder. More recently, Jean-Christophe and Sylvain Corlay (QuantStack) met after the Slicer project week while attending SciPy in Austin. Following the creation of a new project called xeus-python (started by Martin Renou at QuantStack), we took the integration of Jupyter and Slicer to the next level by adding support for improved interactive use and MRML data node visualization directly in the notebook.&lt;/p&gt;
&lt;h2 id="about-the-authors"&gt;About the authors&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Alphabetically ordered&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sylvain Corlay&lt;/strong&gt; is the founder and CEO of QuantStack, and a core Jupyter developer. He co-authored xeus and xeus-python.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Sylvain Corlay" src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/slicerjupyter-a-3d-slicer-kernel-for-interactive/images/003-1_DKAhOe_Y4JdGYkgi9jHBSQ.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Sylvain Corlay&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;Jean-Christophe Fillion-Robin&lt;/strong&gt; is an open-source enthusiast, original author of the SlicerJupyter extension and a principal engineer at Kitware Inc where he leads the development of “3D Slicer” based commercial applications. J-Christophe also maintains &lt;a href="https://scikit-build.org"&gt;scikit-build&lt;/a&gt;, an improved build system generator for CPython C/C++/Fortran/Cython extensions.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Jean-Christophe Fillion-Robin" src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/slicerjupyter-a-3d-slicer-kernel-for-interactive/images/004-1_slg9clPxU3DhL4W2pE2kCA.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Jean-Christophe Fillion-Robin&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;Mike Grauer&lt;/strong&gt; is a Technical Leader on the data and analytics team at Kitware. He is specialized in building scalable server-side processing frameworks that enable scientific workflows over web platforms.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Mike Grauer" src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/slicerjupyter-a-3d-slicer-kernel-for-interactive/images/005-1_SuBw-BD8efPla8tfd98RUg.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Mike Grauer&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;Andras Lasso&lt;/strong&gt; is an original author of the SlicerJupyter extension, Senior Research Engineer and Associate Director of the Laboratory for Percutaneous Surgery at Queen’s University.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Andras Lasso" src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/slicerjupyter-a-3d-slicer-kernel-for-interactive/images/006-1_kINpFRIt94iHaxTA90zncQ.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Andras Lasso&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;Matt McCormick&lt;/strong&gt; is an open source, medical imaging researcher working at Kitware Inc. Matt is an active, contributing member of scientific open source software efforts such as the Insight Toolkit (ITK) and scientific Python (SciPy) communities, and maintains the Jupyter 3D widget, &lt;a href="https://github.com/InsightSoftwareConsortium/itkwidgets"&gt;itkwidgets&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Matt McCormick" src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/slicerjupyter-a-3d-slicer-kernel-for-interactive/images/007-1_Pm17Os2v8Kf_GiZQw1G_ZQ.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Matt McCormick&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;Isaiah Norton&lt;/strong&gt; is a Senior Software Developer at TileDB, Inc. with experience in digital pathology and image-guided surgical navigation.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Isaiah Norton" src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/slicerjupyter-a-3d-slicer-kernel-for-interactive/images/008-1_eR4Y9MX-2lcRsXEKodCJrQ.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Isaiah Norton&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;Steve Pieper&lt;/strong&gt; is a Chief Architect and active developer of the 3D Slicer application for well over a decade. He is CEO of Isomics, Inc, where he uses a range of software technologies to perform medical imaging research with leading universities and companies.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Steve Pieper" src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/slicerjupyter-a-3d-slicer-kernel-for-interactive/images/009-1_aNwZz5TLENXuS2WQRb_N9w.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Steve Pieper&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;Martin Renou&lt;/strong&gt; is a scientific software developer at QuantStack. He is the original author of xeus-python, the xeus-based Python kernel, and contributed to the new concurrency model used for the debugger.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Martin Renou" src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/slicerjupyter-a-3d-slicer-kernel-for-interactive/images/010-1_Cy9QfZytimqXQut2-bdcIA.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Martin Renou&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;Mike Sarahan&lt;/strong&gt; is a software engineer at RStudio, PBC working on bringing language ecosystems together. He is passionate about making software work for data scientists in ways that are easy to maintain and improve.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Mike Sarahan" src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/slicerjupyter-a-3d-slicer-kernel-for-interactive/images/011-1_YKNdPIBH39iFBIL9nD_kfg.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Mike Sarahan&lt;/figcaption&gt;
&lt;/figure&gt;
</content><category term="kernels"/><category term="science"/><category term="visualization"/></entry><entry><title>Interactive Graph Visualization in Jupyter with ipycytoscape</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2020/interactive-graph-visualization-in-jupyter-with/" rel="alternate"/><published>2020-04-30T16:16:00+00:00</published><updated>2020-07-28T08:34:00+00:00</updated><author><name>Mariana Meireles</name></author><id>tag:jasongrout.github.io,2020-04-30:/medium-archive/pelican/posts/2020/interactive-graph-visualization-in-jupyter-with/</id><summary type="html">&lt;p&gt;The Jupyter widgets ecosystem offers a broad variety of data visualization tools for exploratory analysis in the notebook. However, we…&lt;/p&gt;
</summary><content type="html">&lt;p&gt;The Jupyter widgets ecosystem offers a broad variety of data visualization tools for exploratory analysis in the notebook. However, we lack a good story for exploratory graph visualization.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://cytoscape.org/"&gt;Cytoscape&lt;/a&gt; is an open-source software platform for visualizing complex networks and integrating these with any type of attribute data. While it comes from the computational biology community, cytoscape is fully-fledged general-purpose tool for graph visualization and analytics. It now includes a modern web front-end (&lt;a href="https://js.cytoscape.org/"&gt;Cytoscape.JS&lt;/a&gt;) which is a great candidate for integration with Project Jupyter. This is the &lt;em&gt;raison d’être&lt;/em&gt; of &lt;strong&gt;ipycytoscape&lt;/strong&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Gene visualization in ipycytoscape" src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/interactive-graph-visualization-in-jupyter-with/images/001-1_d9UZBB4OB3LXVm7fTHBHaw.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Gene visualization in ipycytoscape&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The goal of ipycytoscape is to enable users of well-established libraries of the Python ecosystem like Pandas, NetworkX, and NumPy, to visualize their graph data in the Jupyter notebook, and enable them modify the visual outcome programmatically or graphically with a simple API and user interface.&lt;/p&gt;
&lt;p&gt;Fortunately, Cytoscape offers a broad enough API that allows ipycytoscape to be a tool that can, in fact, be used to solve any type of problem modeled as a graph. Some examples consist in the development of new chemicals to analyze interactions between substances in the pharmaceutic industry, in security systems to create attack graphs that can be useful to show possible vulnerabilities in systems, modeling human behavior to understand people’s interaction with business or even to understand complex phenomena like the current crisis. Currently, there is an effort to make ipycytoscape an accessible tool for researchers that are trying to find ways to mitigate and understand it, there is more information about this initiative on the COVID OSS Help &lt;a href="https://covid-oss-help.org/"&gt;website&lt;/a&gt; and the discussion is happening in this &lt;a href="https://github.com/covid-19-net/covid-19-community/"&gt;repository&lt;/a&gt; if you’re interested in joining it.&lt;/p&gt;
&lt;h2 id="current-state"&gt;Current state&lt;/h2&gt;
&lt;p&gt;IPycytoscape is part of the PLASMA project (aka in French, Plateforme d’eLearning pour l’Analyse de données Scientifiques MAssives). This project aims at creating an interactive tool to teach computational analysis of massive scientific data. Its first instance, PlasmaBio, is designed for the needs of teachers and students of the &lt;a href="http://www.magisteregenet.univ-paris-diderot.fr/"&gt;European Master of Genetics&lt;/a&gt; at &lt;a href="https://u-paris.fr/"&gt;Université de Paris&lt;/a&gt;. PlasmaBio provides an authentic experience of the actual genomic and bioinformatic analyses performed in research labs. For that purpose, a custom &lt;a href="https://github.com/plasmabio/plasmabio"&gt;JupyterHub-based system&lt;/a&gt; to control many different Jupyter instances is being specially developed by &lt;a href="http://twitter.com/jtpio"&gt;Jeremy Tuloup&lt;/a&gt; at &lt;a href="https://twitter.com/QuantStack"&gt;QuantStack&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In this first version of ipycytoscape, there are still some limitations to what you may be able to do, but there are also some extents from the Python world that will just work out of the box for you. ipycytoscape offers integration between Pandas DataFrames and NetworkX, meaning that you can have a graph visualization of the data you already have with minimal or none adjustments and just a few lines of code.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Usage with NetworkX and DataFrame" src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/interactive-graph-visualization-in-jupyter-with/images/002-1_yRpK3giBa1BLxxnepSE-kg.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Usage with NetworkX and DataFrame&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;ipycytoscape supports all of the built-in CytoscapeJS layouts. This includes the &lt;code&gt;cola&lt;/code&gt;, &lt;code&gt;grid&lt;/code&gt;, &lt;code&gt;breadthfirst&lt;/code&gt;, &lt;code&gt;circular&lt;/code&gt;, &lt;code&gt;concentric&lt;/code&gt; and &lt;a href="https://github.com/dagrejs/dagre"&gt;Dagre&lt;/a&gt; layout as well as the &lt;code&gt;random&lt;/code&gt;, &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;preset&lt;/code&gt; options to build a graph visualization that fits better to your data .Additionally, ipycytoscape also supports the &lt;a href="https://popper.js.org/docs/v2/"&gt;PopperJS&lt;/a&gt; and &lt;a href="https://atomiks.github.io/tippyjs/"&gt;TippyJS&lt;/a&gt; extensions, that allows you to create customizable tips for your nodes and edges .&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="cola, concentric, dagre and grid layouts" src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/interactive-graph-visualization-in-jupyter-with/images/003-1__7mOQADG9USBa0AY-RZaBw.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;cola, concentric, dagre and grid layouts&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;You can also use a variety of labels for a quick visualization of your nodes’ and edges’ contents.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Labels on nodes" src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/interactive-graph-visualization-in-jupyter-with/images/004-1_Tx54Yjz5EbF3kUC-u82XaQ.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Labels on nodes&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Like most Jupyter interactive widgets, ipycytoscape relies on the traitlets library to synchronize data between the back-end and the front-end model.&lt;/p&gt;
&lt;p&gt;Unfortunately, traitlets have a limitation when it comes to container objects and other mutable structures, because synchronization is only triggered upon assignment of the container and not when modifying individual elements.&lt;/p&gt;
&lt;p&gt;To work around this limitation, we make use of the excellent &lt;a href="https://github.com/rmorshea/spectate"&gt;Spectate&lt;/a&gt; library by &lt;a href="https://twitter.com/rmorshea"&gt;Ryan Morshead&lt;/a&gt;, which triggers observers upon individual element changes in containers.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Interaction between ipywidgets and ipycytoscape" src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/interactive-graph-visualization-in-jupyter-with/images/005-1_0l66uLHE51IpGlDLsOf2kw.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Interaction between ipywidgets and ipycytoscape&lt;/figcaption&gt;
&lt;/figure&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/QuantStack/ipycytoscape/stable?filepath=examples"&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/interactive-graph-visualization-in-jupyter-with/images/006-0_-Lcpj92fbL3Zr7N3.webp" alt="https://mybinder.org/v2/gh/QuantStack/ipycytoscape/stable?filepath=examples" 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 &lt;code&gt;ipycytoscape&lt;/code&gt; using pip:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pip install ipycytoscape
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Or using conda:&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 ipycytoscape
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;If you use JupyterLab, you would need to install the JupyterLab extension for ipycanvas (this requires nodejs to be installed):&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;jupyter&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cytoscape&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&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/2020/interactive-graph-visualization-in-jupyter-with/images/007-1_S-w69baox7Q1D997a5yKNw.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;My name is &lt;a href="https://twitter.com/mari_meir"&gt;Mariana Meireles&lt;/a&gt; and I’m a software developer working for &lt;a href="http://quantstack.net/"&gt;QuantStack&lt;/a&gt;. I care deeply about the impacts that technology has in the world and try my best to be the change I want to see by contributing to open source projects that stand upon libre and diverse standards.&lt;/p&gt;
&lt;p&gt;Prior to QuantStack I worked as a developer on the PySide team at the Qt Company and as a web performance developer at Mozilla.&lt;/p&gt;
&lt;p&gt;Currently I’m working on expanding the Jupyter ecosystem with new libraries and functionalities, like an experimental &lt;a href="https://github.com/jupyter-xeus/xeus-sqlite"&gt;SQLite kernel&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="acknowledgements"&gt;&lt;strong&gt;Acknowledgements&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;The development of ipycytoscape at &lt;a href="https://quantstack.net/"&gt;QuantStack&lt;/a&gt; was funded as part of the &lt;a href="https://twitter.com/PlasmaBio"&gt;PLASMA&lt;/a&gt; project, led by &lt;a href="https://twitter.com/CVandiedonck"&gt;Claire Vandiedonck&lt;/a&gt;, &lt;a href="https://twitter.com/pierrepo"&gt;Pierre Poulain&lt;/a&gt;, and &lt;a href="https://twitter.com/SCaburet"&gt;Sandrine Caburet&lt;/a&gt;, associate professors at Université de Paris.&lt;/p&gt;
&lt;p&gt;Sponsors to the PLASMA initiative include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://twitter.com/iledefrance"&gt;Région Île-de-France&lt;/a&gt;, via the “Trophées franciliens de l’innovation numérique dans le supérieur” (&lt;a href="https://www.iledefrance.fr/trophees-franciliens-de-linnovation-numerique-dans-le-superieur-les-laureats-2018"&gt;EdTech 2018&lt;/a&gt;) grant program,&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/Univ_Paris"&gt;Université de Paris&lt;/a&gt;, via the &lt;a href="https://u-paris.fr/en/the-initiative-of-excellence-idex-label/"&gt;Initiative of Excellence (IdEx) Label&lt;/a&gt; and its “inovating teaching” grant program,&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/EURGENEPARIS"&gt;EUR G.E.N.E.&lt;/a&gt;, the graduate school on Genetics and Epigenetics,&lt;/li&gt;
&lt;li&gt;the university training “Création, analyse et valorisation de données biologiques omiques” (&lt;a href="https://omics-school.net/"&gt;DU Omiques&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
</content><category term="visualization"/><category term="widgets"/></entry><entry><title>Report on the Jupyter Community Workshop on Dashboarding</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2020/report-on-the-jupyter-community-workshop-on/" rel="alternate"/><published>2020-02-14T21:06:00+00:00</published><updated>2020-02-14T21:06:00+00:00</updated><author><name>Sylvain Corlay</name></author><id>tag:jasongrout.github.io,2020-02-14:/medium-archive/pelican/posts/2020/report-on-the-jupyter-community-workshop-on/</id><summary type="html">&lt;p&gt;This report is long overdue! From June 3rd to June 6th 2019, thirty-five developers from the Jupyter community met in Paris for a…&lt;/p&gt;
</summary><content type="html">&lt;p&gt;From June 3rd to June 6th 2019, thirty-five developers from the Jupyter community met in Paris for a four-day workshop on dashboarding with Project Jupyter.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Attendees to the Jupyter Community Workshop on Kernels (Photo credit to Lindsey Heagy)" src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/report-on-the-jupyter-community-workshop-on/images/001-1_e8gJ4j2hCn4XMPagp6etOA.jpeg" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Attendees to the Jupyter Community Workshop on Kernels (Photo credit to Lindsey Heagy)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;For four days, attendees worked full time on the Jupyter project, including hacking sessions and discussions on improvements to Jupyter components and new development. We were lucky to count a large number of core developers to the project in the group.&lt;/p&gt;
&lt;p&gt;Beyond the hacking sessions, each day was concluded with a series of presentations and demos of the progress made during the workshop. In partnership with the &lt;a href="https://twitter.com/pydataparis"&gt;PyData Paris&lt;/a&gt; team, we had a special installment of the PyData Paris Meetup with&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;an invited presentation by &lt;a href="https://twitter.com/egouillart"&gt;Emmanuelle Gouillart&lt;/a&gt; on &lt;a href="https://plot.ly/dash/"&gt;Plotly Dash&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;a series of lightning talks by attendees of the workshop on their achievements, including a talk by &lt;a href="https://github.com/philippjfr"&gt;Philip Rudiger&lt;/a&gt; on the first release of &lt;a href="https://github.com/holoviz/panel"&gt;Panel&lt;/a&gt;, and an announcement of the first releases of &lt;a href="https://github.com/voila-dashboards/voila"&gt;Voilà&lt;/a&gt; and the Voilà Gallery.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We ended the week with a social evening at the &lt;a href="https://twitter.com/QuantStack"&gt;QuantStack&lt;/a&gt; offices in Paris.&lt;/p&gt;
&lt;h2 id="why-a-workshop-on-jupyter-dashboarding-with-jupyter"&gt;Why a workshop on Jupyter Dashboarding with Jupyter?&lt;/h2&gt;
&lt;p&gt;The Jupyter ecosystem is used extensively in scientific computing both in academia and industry, and a rich ecosystem of data visualization tools has been developed around the Jupyter widgets frameworks, from geographical data visualization to protein folding simulation.&lt;/p&gt;
&lt;p&gt;However, the Jupyter ecosystem still did not provide a means for developers to transition from notebooks to stand-alone web applications that can be accessed by multiple users.&lt;/p&gt;
&lt;p&gt;This has been a longstanding request from the community: provide better tools built upon the Jupyter stack to share results with students, peers, or the general public.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;These are the challenges that we decided to tackle during that week. The workshop was attended by many Jupyter core developers.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="highlights-of-the-week"&gt;Highlights of the week&lt;/h2&gt;
&lt;p&gt;Many of the developers spent the week working on the Voilà and Panel projects. Both projects had their first public releases during that week (see the first public announcement of &lt;a href="https://medium.com/@philipp.jfr/panel-announcement-2107c2b15f52"&gt;Panel&lt;/a&gt; and &lt;a href="/posts/2019/and-voila/"&gt;Voilà&lt;/a&gt;).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;During this week, a team of participants including Yuvi Panda, Pascal Bugnion, and Jeremy Tuloup iterated on the first version of the Voilà gallery. Several first-time contributors to the widget framework authored example dashboards for the gallery, showcasing their existing work. Yuvi also produced the first deployment scenarii for Voilà on Heruku.&lt;/li&gt;
&lt;li&gt;Cheryl Quah, from Bloomberg MC-ed a panel on dashboarding in the Jupyter ecosystem, including lots of questions and comparisons with Dash.&lt;/li&gt;
&lt;li&gt;Philip Rudigger started working on a Bokeh/ipywidgets integration for better interoperability between the two frameworks.&lt;/li&gt;
&lt;li&gt;Other contributors iterated on creating new Voilà templates, such as voila-vuetify, adding the ability to position Jupyter widgets and outputs in arbitrary location in the dashboard template. Grant Nestor created visual mockups for a UI for creating dashboard layouts in JupyterLab. Grant also helped iterating on logos for the project, and gave a presentation on dynamically loading JavaScript modules in the browser.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="acknowledgments"&gt;Acknowledgments&lt;/h2&gt;
&lt;p&gt;This event would not have been possible without the generous support provided by &lt;a href="https://www.techatbloomberg.com/"&gt;&lt;strong&gt;Bloomberg&lt;/strong&gt;&lt;/a&gt;, who made this workshop series possible&lt;/p&gt;
&lt;p&gt;We are grateful to &lt;a href="https://twitter.com/SG_CIB"&gt;&lt;strong&gt;Société Générale&lt;/strong&gt;&lt;/a&gt; for funding the catering for the workshop.&lt;/p&gt;
&lt;p&gt;The hosting of the workshop at &lt;a href="https://cri-paris.org/"&gt;CRI&lt;/a&gt; was paid for by &lt;a href="https://twitter.com/QuantStack"&gt;&lt;strong&gt;QuantStack&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The public meetup was organized in partnership with the &lt;a href="https://twitter.com/pydataparis"&gt;&lt;strong&gt;PyData Paris&lt;/strong&gt;&lt;/a&gt; team.&lt;/p&gt;
&lt;p&gt;Finally, we especially thank &lt;a href="https://twitter.com/ruv7?lang=en"&gt;&lt;strong&gt;Ana Ruvalcaba&lt;/strong&gt;&lt;/a&gt; from Project Jupyter for her incredible work on the logistics and finances of the Jupyter Community Workshop series.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2020/report-on-the-jupyter-community-workshop-on/images/002-1_FMKOoximrvz6sASKu19C-g.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
</content><category term="dashboards"/><category term="events"/><category term="visualization"/><category term="workshops"/></entry><entry><title>Voilà is now a Jupyter subproject</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2019/voila-is-now-an-official-jupyter-subproject/" rel="alternate"/><published>2019-12-29T12:11:00+00:00</published><updated>2019-12-29T12:15:00+00:00</updated><author><name>Sylvain Corlay</name></author><id>tag:jasongrout.github.io,2019-12-29:/medium-archive/pelican/posts/2019/voila-is-now-an-official-jupyter-subproject/</id><summary type="html">&lt;p&gt;It is a great pleasure to announce that the Voilà project has been incorporated as a Jupyter subproject. Voilà will now be subject to the…&lt;/p&gt;
</summary><content type="html">&lt;blockquote&gt;
&lt;p&gt;It is a great pleasure to announce that the Voilà project has been incorporated as a Jupyter subproject. Voilà will now be subject to the &lt;a href="https://github.com/jupyter/governance/blob/master/governance.md"&gt;Jupyter governance&lt;/a&gt; and &lt;a href="https://github.com/jupyter/governance/blob/master/conduct/code_of_conduct.md"&gt;code of conduct&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For reference, the Jupyter Enhancement Proposal (JEP) for the Voilà incorporation is available &lt;a href="https://github.com/jupyter/enhancement-proposals/pull/42"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="what-is-voila"&gt;What is Voilà?&lt;/h3&gt;
&lt;p&gt;Voilà helps you communicate insights, by transforming a Jupyter Notebook into a stand-alone web application you can share. It gives you control over what your readers experience in a secure and customizable interactive dashboard.&lt;/p&gt;
&lt;p&gt;The easiest way to get started with Voilà is to install it via &lt;code&gt;pip&lt;/code&gt; or &lt;code&gt;conda&lt;/code&gt; and type &lt;code&gt;voila some_notebook.ipynb&lt;/code&gt; to turn the said notebook into a dashboard.&lt;/p&gt;
&lt;p&gt;Besides, Voilà includes a templating system that allows to overload the behavior of the front-end. Using this templating system, Voilà can be used to create&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;slideshows (with voila-reveal)&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
&lt;img alt="A Voilà slideshow created with the voila-reveal template." src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/voila-is-now-an-official-jupyter-subproject/images/001-1_mp59BtUkz046smQek2-BFA.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;A Voilà slideshow created with the voila-reveal template.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;dashboards (with voila-gridstack)&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
&lt;img alt="A Voilà Dashboard based on the voila-gridstack template." src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/voila-is-now-an-official-jupyter-subproject/images/002-1_P447LmtfAnhIcCol6q6FBw.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;A Voilà Dashboard based on the voila-gridstack template.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="why-moving-voila-under-the-jupyter-governance"&gt;Why moving Voilà under the Jupyter governance?&lt;/h3&gt;
&lt;p&gt;While the project was initially started by QuantStack, the team now comprises developers from Bloomberg, UC Berkeley, JP Morgan, and Cal Poly San Luis Obispo. OVH has been supportive of the project by kindly providing the free hosting of the gallery on their infrastructure.&lt;/p&gt;
&lt;p&gt;We believe that the &lt;em&gt;&lt;strong&gt;multi-stakeholder&lt;/strong&gt;&lt;/em&gt; nature of the Voilà project is well-suited for the Jupyter organization.&lt;/p&gt;
&lt;p&gt;The Voilà project is largely built upon Jupyter subprojects and standards.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The standard &lt;strong&gt;notebook file format&lt;/strong&gt; is the main entry point to Voilà.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;nbconvert&lt;/strong&gt; is used for the conversion to progressively-rendered HTML.&lt;/li&gt;
&lt;li&gt;naturally, we use &lt;strong&gt;jupyter_client&lt;/strong&gt; for handling the execution of notebook cells&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;jupyter_server&lt;/strong&gt; is the default back-end.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JupyterHub&lt;/strong&gt; is at the foundation of the voila-gallery project.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JupyterLab&lt;/strong&gt; components (mime renderers, input and output areas) are used in the front-end implementation. Voilà also includes a preview JupyterLab extension.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ipywidgets&lt;/strong&gt; and custom jupyter widget libraries such as bqplot, ipyvolume, ipyleaflets provide the bulk of the interactivity of Voilà applications.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Voilà is more a &lt;em&gt;remix&lt;/em&gt; of existing Jupyter components (with changes to enable that use case) than a completely new application.&lt;/p&gt;
&lt;h3 id="resources"&gt;Resources&lt;/h3&gt;
&lt;p&gt;Should you be interested in Voilà, feel free to try it on Binder or locally! You can also engage with the developer community during our public team meetings and the various GitHub repositories of the project:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the Voilà &lt;strong&gt;GitHub repository&lt;/strong&gt; is available here: &lt;a href="https://github.com/voila-dashboards/voila"&gt;https://github.com/voila-dashboards/voila&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;the &lt;strong&gt;Documentation&lt;/strong&gt; is hosted on &lt;em&gt;Read the Docs&lt;/em&gt;: &lt;a href="https://voila.readthedocs.io"&gt;https://voila.readthedocs.io&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;the &lt;strong&gt;Team Compass&lt;/strong&gt; holds the calendar for the public developer meetings, as well as the meeting minutes: &lt;a href="https://voila-dashboards.github.io"&gt;https://voila-dashboards.github.io&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;the &lt;strong&gt;Announcement&lt;/strong&gt; of the first Voilà release was published on this blog: &lt;a href="/posts/2019/and-voila/"&gt;https://blog.jupyter.org/and-voilà-f6a2c08a4a93&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="acknowledgements"&gt;&lt;strong&gt;Acknowledgements&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Voilà was started by the team of open-source developers at &lt;a href="https://twitter.com/QuantStack"&gt;QuantStack&lt;/a&gt; as a separate project, but with the full intent to incorporate it into Jupyter. The initial project development at QuantStack was funded by &lt;a href="https://twitter.com/techatbloomberg"&gt;Bloomberg&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Now, Voilà contributors work in many institutions, including UC Berkeley, Cal Poly San Luis Obispo, JP Morgan, and Faculty (formerly ASI Data Science).&lt;/li&gt;
&lt;li&gt;The Voilà Gallery is kindly hosted by &lt;a href="https://www.ovh.com/"&gt;OVH&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/voila-is-now-an-official-jupyter-subproject/images/003-1_ZrMs1GjNdEYhsbqese6xVA.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
</content><category term="dashboards"/><category term="visualization"/><category term="Voilà"/></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>Interactive GIS in Jupyter with ipyleaflet</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2019/interactive-gis-in-jupyter-with-ipyleaflet/" rel="alternate"/><published>2019-09-24T22:54:00+00:00</published><updated>2019-09-25T15:19:00+00:00</updated><author><name>QuantStack</name></author><id>tag:jasongrout.github.io,2019-09-24:/medium-archive/pelican/posts/2019/interactive-gis-in-jupyter-with-ipyleaflet/</id><summary type="html">&lt;p&gt;As Jupyter grew in popularity, a broad ecosystem of data visualization packages based on Jupyter widgets has arisen, bringing even more…&lt;/p&gt;
</summary><content type="html">&lt;p&gt;As Jupyter grew in popularity, a broad ecosystem of visualization packages based on Jupyter widgets has been developed, bringing even more interactivity to the Jupyter world.&lt;/p&gt;
&lt;p&gt;In this article, we dive into Jupyter Interactive Widgets and the &lt;a href="https://github.com/jupyter-widgets/ipyleaflet"&gt;ipyleaflet&lt;/a&gt; package, an interactive maps visualization system for Jupyter.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="A non-interactive map." src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/interactive-gis-in-jupyter-with-ipyleaflet/images/001-1_YA26aVkLDM1KXjNtGu5-Hw.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;A non-interactive map.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="jupyter-widgets"&gt;Jupyter Widgets&lt;/h2&gt;
&lt;p&gt;Jupyter Interactive Widgets are “special objects” that can be instantiated by the user in their code and result in a counterpart component being created in the front-end.&lt;/p&gt;
&lt;p&gt;The core &lt;code&gt;ipywidgets&lt;/code&gt; package provides a collection of controls that Jupyter users can use to build simple UIs as part of their notebooks (sliders, buttons, dropdowns, layout components).&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Basic ipywidgets controls." src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/interactive-gis-in-jupyter-with-ipyleaflet/images/002-1_a8s90I7Kj3DyBjmh_LjAaw.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Basic ipywidgets &lt;strong&gt;controls&lt;/strong&gt;.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;More than a collection of controls, it provides a framework upon which a large ecosystem of components has been built, allowing notebook authors to capture user inputs in very diverse ways.&lt;/p&gt;
&lt;p&gt;Popular libraries built upon interactive widgets include&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/bloomberg/bqplot"&gt;&lt;strong&gt;bqplot&lt;/strong&gt;&lt;/a&gt;, a 2-D plotting system for Jupyter,&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/maartenbreddels/ipyvolume/"&gt;&lt;strong&gt;ipyvolume&lt;/strong&gt;&lt;/a&gt;, a 3-D plotting package based on WebGL and ThreeJS,&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/jupyter-widgets/pythreejs"&gt;&lt;strong&gt;PythreeJS&lt;/strong&gt;&lt;/a&gt;, a 3-D scene description package exposing a large part of the ThreeJS API to Jupyter,&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mariobuikhuizen/ipyvuetify"&gt;&lt;strong&gt;ipyvuetify&lt;/strong&gt;&lt;/a&gt;, a large collection of VuetifyJS components exposed to Jupyter,&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/maartenbreddels/ipywebrtc"&gt;&lt;strong&gt;ipywebrtc&lt;/strong&gt;&lt;/a&gt;, a library exposing the features of the WebRTC protocol to Jupyter kernels,&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/twosigma/beakerx"&gt;&lt;strong&gt;beakerx&lt;/strong&gt;&lt;/a&gt;, a collection of widgets, extensions, and kernels for Jupyter,&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;and many more… This list is not comprehensive and dozens of other widget packages have been developed.&lt;/p&gt;
&lt;h3 id="key-aspects-of-jupyter-widgets-include"&gt;Key aspects of Jupyter widgets include:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Bidirectionality&lt;/strong&gt;Widgets are not just meant for display but can also be used to capture user inputs, which can then trigger new computation. Notebook authors can compose sophisticated applications including a variety of components from different packages.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Language Agnosticism&lt;/strong&gt;Built upon the Jupyter ecosystem, the interactive widget protocol used for the synchronization between the kernel and the front-end is well-specified and can be implemented for any kernel.&lt;br&gt;
Back-ends for other languages than Python already exist, such as for C++ (with the &lt;a href="https://github.com/QuantStack/xeus-cling"&gt;xeus-cling&lt;/a&gt; Jupyter kernel), and languages of the JVM such as Clojure or Groovy (with the &lt;a href="http://beakerx.com/"&gt;beakerx&lt;/a&gt; kernels).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extensibility&lt;/strong&gt;Jupyter widgets are not meant as a monolithic system with one and only one way to achieve a specific task. We strive to provide a foundational layer allowing third-party widget authors to be as inventive as possible.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;A common pattern for Jupyter widget packages has been to bring the capabilities of popular JavaScript visualization frameworks to Jupyter with a bridge based on ipywidgets. This is the case for the ipyleaflet package, as well as pythreejs and ipyvuetify.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Another use case is the development of &lt;em&gt;ad hoc&lt;/em&gt; controls that are not necessarily relevant for a mainstream visualization package, but may be specific to a scientific field. An example is the &lt;a href="https://github.com/erdc/ipymesh"&gt;ipymesh&lt;/a&gt; project by Chris Kees which can be used to draw PSLG (planar straight-line graphs) in the Jupyter notebook.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="ipyleaflet"&gt;ipyleaflet&lt;/h2&gt;
&lt;p&gt;ipyleaflet is a Jupyter - LeafletJS bridge, bringing mapping capabilities to the notebook and JupyterLab.&lt;/p&gt;
&lt;p&gt;Built as a bridge between the LeafletJS package and Jupyter, the ipyleaflet API maps to that of LeafletJS, bringing most of the core features of the package to Jupyter, and enabling a few popular LeafletJS extensions. A small difference is that following the Python coding style, ipyleaflet makes use of &lt;em&gt;snake_case&lt;/em&gt; instead of &lt;em&gt;CamelCase&lt;/em&gt; for attribute names.&lt;/p&gt;
&lt;h3 id="ipyleaflet-features"&gt;ipyleaflet features&lt;/h3&gt;
&lt;p&gt;The main components to the library are layers and controls, respectively items to be displayed on the map, and interactive widgets overlayed on the map area for greater interactivity.&lt;/p&gt;
&lt;p&gt;The first thing for which you may want to change the default value are the zoom level, the position, or the base layer for the map.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Changing the basemap layer in an ipyleaflet map." src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/interactive-gis-in-jupyter-with-ipyleaflet/images/003-1_02DmPnByfXtPkeYnytNvfA.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Changing the basemap layer in an ipyleaflet map.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Maps can be interactively edited in the Jupyter notebook, by dynamically changing or adding layers. In this screenshot, we add a custom layer including a GeoJSON dataset.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: An alternative layer to GeoJSON is GeoData, which lets the user load the data in the form of a GeoPandas dataframe instead of raw GeoJSON.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure&gt;
&lt;img alt="Adding a GeoJSON dataset to an interactive map." src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/interactive-gis-in-jupyter-with-ipyleaflet/images/004-1_3t7T3EGIeA10R0XrrM9ZVw.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Adding a GeoJSON dataset to an interactive map.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;A number of simple primitives are available such as markers and heatmaps. In the following screencast, we show how primitive properties can be linked with other widgets, and used as means to take user input on a map:&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Linking properties of ipyleaflet primitives to other Jupyter widgets." src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/interactive-gis-in-jupyter-with-ipyleaflet/images/005-1_31XAuFgaeln-mrjxxRzdxA.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Linking properties of ipyleaflet primitives to other Jupyter widgets.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;The &lt;em&gt;splitmap&lt;/em&gt; control can be used to compare to different set of ipyleaflet layers at the same location.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="The splitmap control." src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/interactive-gis-in-jupyter-with-ipyleaflet/images/006-1_lZT_nX-jH3jcMLFdhTUxXw.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;The &lt;strong&gt;splitmap&lt;/strong&gt; control.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Another interesting layer is the &lt;em&gt;velocity&lt;/em&gt; layer which can be used to display wind velocity data. This control can take data in the form of an &lt;a href="https://github.com/pydata/xarray"&gt;xarray&lt;/a&gt; dataset.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="The velocity layer." src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/interactive-gis-in-jupyter-with-ipyleaflet/images/007-1_u2J2aJy6FfBaFytG0ppruw.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;The &lt;strong&gt;velocity&lt;/strong&gt; layer.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;More classical visualization tools are also available, such as &lt;em&gt;choropleths&lt;/em&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="A choropleth layer." src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/interactive-gis-in-jupyter-with-ipyleaflet/images/008-1_MbLnLa_LsugvYdBNjGhhQQ.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;A &lt;strong&gt;choropleth&lt;/strong&gt; layer.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="jupyterlab-integration-with-the-sidecar-and-theming-support"&gt;JupyterLab Integration with the Sidecar and Theming Support&lt;/h3&gt;
&lt;p&gt;ipyleaflet is well integrated with JupyterLab&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ipyleaflet controls make use of the &lt;strong&gt;JupyterLab themes&lt;/strong&gt; for coloring so that they don’t stand out when using e.g. a dark theme.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
&lt;img alt="The support for JupyterLab themes in ipyleaflet." src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/interactive-gis-in-jupyter-with-ipyleaflet/images/009-1_6tCnE8oedSXuEtiGKA1fAA.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;The support for JupyterLab &lt;strong&gt;themes&lt;/strong&gt; in ipyleaflet.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;ipyleaflet can be used in combination with the &lt;a href="https://github.com/jupyter-widgets/jupyterlab-sidecar/"&gt;&lt;strong&gt;JupyterLab sidecar&lt;/strong&gt;&lt;/a&gt; widget.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;
&lt;img alt="Using the sidecar widget in JupyterLab to display a map aside of the notebook." src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/interactive-gis-in-jupyter-with-ipyleaflet/images/010-1_eUr0hcPcBInlp125yA7sHg.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Using the &lt;strong&gt;sidecar&lt;/strong&gt; widget in JupyterLab to display a map aside of the notebook.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Together with the sidecar, a map can be programmatically added to the right-side toolbar of the JupyterLab application, and interactively edited in the notebook. This prevents the back-and-forth scrolling often required to see how changes are reflected visually.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The workflow enabled by ipyleaflet in combination with the sidecar is similar to that of the &lt;a href="https://github.com/OpenGeoscience/geonotebook"&gt;geonotebook&lt;/a&gt; project by Christopher Kotfila, Jonathan Beezley, and Dan LaManna from &lt;a href="https://www.kitware.com/"&gt;Kitware&lt;/a&gt;).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure&gt;
&lt;img alt="The geonotebook (which was based on the classic notebook) provided a similar workflow to the lab sidecar." src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/interactive-gis-in-jupyter-with-ipyleaflet/images/011-1_u2dMqR9n5Vwl1ELtpTbVCg.jpg" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;The &lt;strong&gt;geonotebook&lt;/strong&gt; (which was based on the classic notebook) provided a similar workflow to the lab sidecar.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="a-more-advanced-example"&gt;A more advanced example&lt;/h3&gt;
&lt;p&gt;Combined with other widget libraries such as bqplot or the core ipywidget package, ipyleaflet users can easily compose more complex applications and dashboards. In the following screencast, we explore the wealth-of-nations dataset with a leafletmap, a bqplot line chart and a dropdown widget:&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Exploring the wealth-of-nations dataset with ipyleaflet, bqplot and core ipywidgets." src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/interactive-gis-in-jupyter-with-ipyleaflet/images/012-1_0SvmdK7ykkDXZ4oU-x6QzA.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Exploring the wealth-of-nations dataset with ipyleaflet, bqplot and core ipywidgets.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="trying-ipyleaflet-online-with-mybinder"&gt;Trying ipyleaflet online with mybinder&lt;/h3&gt;
&lt;p&gt;If you would like to try out ipyleaflet &lt;em&gt;now&lt;/em&gt;, it is possible thanks to the binder project. Just click on the image below!&lt;/p&gt;
&lt;p&gt;&lt;a href="https://mybinder.org/v2/gh/jupyter-widgets/ipyleaflet/stable?filepath=examples"&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/interactive-gis-in-jupyter-with-ipyleaflet/images/013-1_AsxYLD3dKd9Vej3SII_eLg.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="interactive-gis-in-c-xleaflet"&gt;Interactive GIS in C++: xleaflet&lt;/h3&gt;
&lt;p&gt;As mentioned earlier, interactive widgets back-ends for other programming languages have be implemented. There is a C++ back-end for ipywidgets: &lt;a href="https://github.com/QuantStack/xwidgets"&gt;xwidgets&lt;/a&gt; which is the building block for creating other C++ widgets back-ends.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/interactive-gis-in-jupyter-with-ipyleaflet/images/014-0_aPvM-7TR9IbP_NXO.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/QuantStack/xleaflet"&gt;xleaflet&lt;/a&gt; is the C++ - LeafletJS bridge that exposes almost the same API as ipyleaflet, only that you use it from a C++ interpreter! It is based upon xwidgets which brings the bidirectional communication with the front-end.&lt;/p&gt;
&lt;p&gt;You can learn more about the &lt;a href="https://github.com/QuantStack/xeus-cling"&gt;xeus-cling&lt;/a&gt; Jupyter kernel, xwidgets and xleaflet by reading the following &lt;a href="/posts/2018/interpreted-c-for-gis-with-jupyter/"&gt;blogpost&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="xleaflet is the C++ backend to the jupyter-leaflet integration." src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/interactive-gis-in-jupyter-with-ipyleaflet/images/015-1_m2ElLEj6r-6uDqXmA0tqRw.mp4" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;&lt;strong&gt;xleaflet&lt;/strong&gt; is the C++ backend to the jupyter-leaflet integration.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="deploying-ipyleaflet-based-dashboards-with-voila"&gt;Deploying ipyleaflet-based dashboards with Voilà&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/interactive-gis-in-jupyter-with-ipyleaflet/images/016-1_36JTV2RMHwg0DEW6V00d2A.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/QuantStack/voila"&gt;Voilà&lt;/a&gt; is a tool that turns Jupyter notebooks into standalone dashboards. Built upon the Jupyter stack, it inherits the language agnosticism of the ecosystem, and can be used to produce standalone applications based on ipyleaflet.&lt;/p&gt;
&lt;p&gt;A companion project to Voilà is the Voilà gallery project, a public facing set up of JupyterHub serving Voilà dashboard. It is kindly hosted by &lt;a href="https://www.ovh.com/fr/"&gt;OVH&lt;/a&gt;. You can check out the Voilà gallery at URL &lt;a href="https://voila-gallery.org/services/gallery/"&gt;https://voila-gallery.org&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For more resources about &lt;em&gt;voilà&lt;/em&gt;, check out&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the original announcement of the project: &lt;a href="https://blog.jupyter.org/and-voil%C3%A0-f6a2c08a4a93,"&gt;&lt;em&gt;And Voilà!&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;and for the gallery: &lt;a href="/posts/2019/a-gallery-of-voila-examples/"&gt;&lt;em&gt;A Gallery of Voilà Examples&lt;/em&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you check out the Voilà gallery, don’t miss Jeremy Tuloup’s GPX loader demo!&lt;/p&gt;
&lt;h2 id="jupyter-for-geo-sciences"&gt;Jupyter for Geo Sciences&lt;/h2&gt;
&lt;p&gt;Jupyter’s adoption is exploding in the GeoScience space. Notable projects building upon Jupyter include&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://jeodpp.jrc.ec.europa.eu/home/"&gt;&lt;em&gt;&lt;strong&gt;JEODPP&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt; (JRC Earth Observation Data and Processing Platform) is a EU project providing petabyte scale storage and high-throughput computing capacities to facilitate large scale analysis of Earth Observation data. The main front-end to the platform is base on Jupyter. The mapping capability is based on &lt;strong&gt;ipyleaflet&lt;/strong&gt;. End users can request custom visualization that are returned to them in the form of lazily computed tile layers.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pangeo.io"&gt;&lt;em&gt;&lt;strong&gt;Pangeo&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt; is a community platform providing open, reproducible, and scalable sciences. The Pangeo software ecosystem involves open source tools such as xarray, Iris, Dask, Jupyter, and many other packages.&lt;/li&gt;
&lt;li&gt;It was &lt;a href="/posts/2019/jupyter-meets-the-earth/"&gt;recently announced&lt;/a&gt; that the NSF would be funding the UC Berkeley + NCAR “&lt;em&gt;&lt;strong&gt;EarthCube&lt;/strong&gt;&lt;/em&gt;” proposal “Jupyter meets the Earth: Enabling discovery in geoscience through interactive computing at scale”. The plan involves the development of interactive dashboards with &lt;strong&gt;Voilà&lt;/strong&gt; and contributions to the Voilà codebase.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="related-projects"&gt;Related Projects&lt;/h2&gt;
&lt;h3 id="jupyter-gmaps"&gt;Jupyter-gmaps&lt;/h3&gt;
&lt;p&gt;We should mention the &lt;a href="https://github.com/pbugnion/gmaps"&gt;jupyter-gmaps&lt;/a&gt; project by Pascal Bugnion. Jupyter-gmaps is a bridge between Google maps and Jupyter. Just like ipyleaflet, jupyter-gmaps is built upon the jupyter interactive widgets framework but relies on Google maps for the display instead of LeafletJS library.&lt;/p&gt;
&lt;p&gt;This is a high-quality widget by another core developer of ipywidgets. Pascal is also one of the people behind Voilà and the Voilà gallery.&lt;/p&gt;
&lt;h3 id="folium"&gt;Folium&lt;/h3&gt;
&lt;p&gt;The &lt;a href="https://github.com/python-visualization/folium"&gt;Folium&lt;/a&gt; project enables maps visualization in the Jupyter notebook. Just like ipyleaflet, it is based on LeafletJS. Folium was created by Rob Story and is now maintained by Frank Conengmo and Filipe Fernandes.&lt;/p&gt;
&lt;p&gt;A key difference between Folium and ipyleaflet is that ipyleaflet is built upon ipywidgets and allows bidirectional communication between the front-end and the backend enabling the use of the map to capture user input, while Folium is meant for displaying static data only. Folium enables many LeafletJS extensions, some of which may not be available in ipyleaflet at the moment.&lt;/p&gt;
&lt;h2 id="acknowledgements"&gt;Acknowledgements&lt;/h2&gt;
&lt;p&gt;The ipyleaflet project was started in 2015 by &lt;a href="https://twitter.com/ellisonbg?lang=en"&gt;Brian Granger&lt;/a&gt;, and funded by the &lt;a href="https://www.erdc.usace.army.mil/"&gt;ERDC&lt;/a&gt;. The further development by Sylvain Corlay and Martin Renou was supported by &lt;a href="https://quantstack.net/"&gt;QuantStack&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We are grateful to &lt;a href="https://www.ovh.com"&gt;OVH&lt;/a&gt; for kindly hosting the &lt;a href="http://voila-gallery.org"&gt;Voilà gallery&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Other key contributors to Voilà and ipyleaflet that should be thanked here are Maarten Breddels, Pascal Bugnion, and Yuvi Panda. We should also mention the recent contributions by &lt;a href="https://twitter.com/VasavanT"&gt;Vasavan Thirusittampalam&lt;/a&gt; who worked on the full-screen control and better interoperability with geopandas.&lt;/p&gt;
&lt;h2 id="about-the-authors"&gt;About the Authors&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://twitter.com/SylvainCorlay"&gt;Sylvain Corlay&lt;/a&gt;, and &lt;a href="https://twitter.com/martinRenou"&gt;Martin Renou&lt;/a&gt; are Scientific Software Developers at &lt;a href="https://github.com/QuantStack/"&gt;QuantStack&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="sylvain-corlay"&gt;Sylvain Corlay&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/interactive-gis-in-jupyter-with-ipyleaflet/images/017-1_6-g_O5JJQn4uSoAreSq9Pw_2x.jpeg" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sylvain Corlay&lt;/strong&gt; is the founder and CEO of QuantStack.&lt;/p&gt;
&lt;p&gt;As an Open Source Developer, Sylvain contributes to Project Jupyter in the areas of interactive widgets and language kernels and is a steering committee member of the Project. Beyond QuantStack, Sylvain serves as a member of the board of directors of the NumFOCUS foundation. He also co-organizes the PyData Paris Meetup.&lt;/p&gt;
&lt;h3 id="martin-renou"&gt;Martin Renou&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/interactive-gis-in-jupyter-with-ipyleaflet/images/018-1_eZ36LOdroOy_-KBEN8TLlg_2x.jpeg" alt="" 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. Prior to joining QuantStack, Martin also worked as a Software developer at Enthought. He studied at the French Aerospace Engineering School ISAE-Supaero, with major in autonomous systems and programming.&lt;/p&gt;
&lt;p&gt;As an open source developer, Martin has worked on a variety of projects, such as SciviJS (a JavaScript 3-D mesh visualization library), Xtensor, and Xeus.&lt;/p&gt;
</content><category term="geoscience"/><category term="science"/><category term="visualization"/></entry><entry><title>ROS @ Jupyter</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2019/ros-jupyter/" rel="alternate"/><published>2019-04-07T21:15:00+00:00</published><updated>2019-04-07T21:15:00+00:00</updated><author><name>Wolf Vollprecht</name></author><id>tag:jasongrout.github.io,2019-04-07:/medium-archive/pelican/posts/2019/ros-jupyter/</id><summary type="html">&lt;p&gt;Project Jupyter is a huge hit in data science, but it has not yet found widespread adoption in robotics. Today, we are releasing the first version of jupyter-ros, a collection of Jupyter interactive widgets inspired by Qt and RViz, to bring their features to the Jupyter ecosystem. This may be the right time for Jupyter-based developer tools, as cloud robotics is taking off.&lt;/p&gt;
</summary><content type="html">&lt;figure&gt;
&lt;p&gt;&lt;video src="images/005-Ri327iDKuC4pnExM4L-giphy.mp4" preload="metadata" loop muted playsinline controls&gt;&lt;/video&gt;&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;This may be the right time for Jupyter-based developer tools, as cloud robotics is taking off. A PR2 robot in the browser, and making him dance through the traditional Qt interface&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Historically, the &lt;a href="http://www.ros.org/"&gt;ROS (Robot Operating System)&lt;/a&gt; community has relied on Qt for building complex user interfaces. Nowadays, the Jupyter notebook and the ipywidgets framework offer a compelling alternative for several reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Code and interface are &lt;em&gt;not separated&lt;/em&gt; — both are in the same notebook.&lt;/li&gt;
&lt;li&gt;Complex widgets using browser technology are possible: from &lt;a href="https://github.com/jupyter-widgets/ipywidgets"&gt;JavaScript sliders&lt;/a&gt; to 3D with &lt;a href="https://github.com/maartenbreddels/ipyvolume"&gt;WebGL&lt;/a&gt;, &lt;a href="https://github.com/maartenbreddels/ipywebrtc"&gt;real time video streaming with WebRTC&lt;/a&gt;…&lt;/li&gt;
&lt;li&gt;Works with any web browser — not bound to Linux, and no Qt applications need to be compiled.&lt;/li&gt;
&lt;li&gt;Doesn’t need to run locally! Applications can run on a server far away, without any manual setup or installation procedure.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However, ROS does not play nicely with Jupyter. For example, rospy is inherently multi-threaded (every new ROS topic subscriber spawns a new thread). Debug printouts in callbacks result in Jupyter printing that content into the output area of the active notebook cell, quickly flooding the user interface — and there is no easy way to stop logging threads once started.&lt;/p&gt;
&lt;h3 id="ipywidgets-to-the-rescue-jupyter-ros"&gt;ipywidgets to the rescue: jupyter-ros&lt;/h3&gt;
&lt;p&gt;That is why &lt;a href="https://github.com/RoboStack/jupyter-ros"&gt;jupyter-ros&lt;/a&gt; was created. It is a suite of plugins to the Jupyter ecosystem to make working with ROS inside Jupyter a breeze.&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="Subscribing with jupyter-ros produces an interactive widget" src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/ros-jupyter/images/001-1_35w3erSL2xz0mp9le6YNyg.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;Subscribing with jupyter-ros produces an interactive widget&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;First, when you subscribe using jupyter-ros, the function returns an ipywidget with a start/stop button and a dedicated output area for debug prints. Internally this re-routes all print outs from your subscriber thread to this Jupyter cell, and gives full control over the thread (by being able to stop and restart it at any time).&lt;/p&gt;
&lt;figure&gt;
&lt;img alt="The jupyros publishing sugar" src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/ros-jupyter/images/002-1_yBgrLtyCGlaZcUQnFV9Jpg.webp" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;The jupyros publishing sugar&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;If you call the publish function in jupyter-ros, a widget is automatically generated from the message specification. For example, a ROS message String field automatically becomes a text input widget, a Float32 becomes a FloatSlider…&lt;/p&gt;
&lt;figure&gt;
&lt;p&gt;&lt;video src="images/006-fSqNQ06Ujnuu8juH2t-giphy.mp4" preload="metadata" loop muted playsinline controls&gt;&lt;/video&gt;&lt;/p&gt;
&lt;figcaption&gt;
&lt;p&gt;Live plotting IMU data from a BBC micro:bit&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Another interesting functionality is the live plotting, similar to rqt_plot. For this we use &lt;a href="https://github.com/bloomberg/bqplot"&gt;bqplot&lt;/a&gt;, a “jupyter-native” solution to plotting. With jupyter-ros, you can select a couple of fields from your message, and they will be automatically plotted to a bqplot.&lt;/p&gt;
&lt;h3 id="going-3-d"&gt;Going 3-D&lt;/h3&gt;
&lt;p&gt;Most robots are three dimensional, and so should be the visualizations! The go-to tool in the ROS ecosystem at the moment is RViz, a very powerful 3-D visualization tool.&lt;/p&gt;
&lt;p&gt;Some of RViz’s functionality has already been ported over to the web browser as part of the &lt;a href="http://robotwebtools.org/"&gt;RobotWebTools&lt;/a&gt; effort. We’ve been able to piggy-back on their impressive work, and we’re releasing the first iteration of ROS3D Jupyter widgets. Currently, they allow you to programatically plug together RViz like visualizations for different data types, such as laser scans, robot trajectories, and 3D (URDF) models of the robot!&lt;/p&gt;
&lt;p&gt;Thanks to the ipywidgetification, you can now bring complex visualizations to the web, without writing any JavaScript, and arrange those visualizations freely in JupyterLab.&lt;/p&gt;
&lt;figure&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/mPvYZango2E" title="ROS widgets in JupyterLab" 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;Interactive widgets showing ROS data inside JupyterLab&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="jupyter-widgets-and-cloud-robotics"&gt;Jupyter, Widgets, and Cloud Robotics&lt;/h3&gt;
&lt;p&gt;We hope that Jupyter, and the jupyter-ros widgets will play a big role in cloud robotics. In cloud robotics, some of the software powering one or multiple robots runs on powerful computers in data centers. For monitoring purposes, or development, Jupyter and JupyterLab are perfect candidates. Robot customers will be able to login to a single user-friendly interface, without having to install any custom software on their machine, or run a specialized operating system (ROS usually runs on Ubuntu). Exciting possibilities arise: it is already possible to run a Docker container running JupyterLab and jupyter-ros on the leading cloud robotics platforms, &lt;a href="https://rapyuta-robotics.com"&gt;Rapyuta Robotics&lt;/a&gt; and their freshly launched platform &lt;a href="http://rapyuta.io"&gt;rapyuta.io&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="installation-source"&gt;Installation &amp;amp; source&lt;/h3&gt;
&lt;p&gt;The jupyter-ros widgets can be installed from PyPI using&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;pip&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;jupyros
$&lt;span class="w"&gt; &lt;/span&gt;jupyter&lt;span class="w"&gt; &lt;/span&gt;nbextension&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--py&lt;span class="w"&gt; &lt;/span&gt;--sys-prefix&lt;span class="w"&gt; &lt;/span&gt;jupyros
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The examples and the source code can be found on github: &lt;a href="https://github.com/robostack/jupyter-ros"&gt;https://github.com/robostack/jupyter-ros&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This work is still early stages and you might find some rough edges. We look forward to collaborating with the community to polish these widgets to the highest standards!&lt;/p&gt;
&lt;h3 id="about-quantstack"&gt;About QuantStack&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://twitter.com/QuantStack"&gt;QuantStack&lt;/a&gt; is located in the center of Europe (Paris). We are core Jupyter developers, and love ROS, and the cloud. If you are interested in working with us on professional user interfaces for developers or clients in the cloud, do not hesitate to send us an email: &lt;a href="mailto:wolf.vollprecht@quantstack.net"&gt;wolf.vollprecht@quantstack.net&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/ros-jupyter/images/003-1_puvws-ulE4ShvCd9inzo0g.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;br&gt;
&lt;img src="https://jasongrout.github.io/medium-archive/pelican/posts/2019/ros-jupyter/images/004-1_WqG2vz1hl2X0-Z2TZFFSAQ.webp" alt="" loading="lazy" data-body-image=""&gt;&lt;/p&gt;
</content><category term="robotics"/><category term="visualization"/></entry><entry><title>A Diagram Editor for JupyterLab</title><link href="https://jasongrout.github.io/medium-archive/pelican/posts/2018/a-diagram-editor-for-jupyterlab/" rel="alternate"/><published>2018-02-26T11:33:00+00:00</published><updated>2018-02-26T11:51:00+00:00</updated><author><name>Wolf Vollprecht</name></author><id>tag:jasongrout.github.io,2018-02-26:/medium-archive/pelican/posts/2018/a-diagram-editor-for-jupyterlab/</id><summary type="html">&lt;p&gt;With the success of the notebook file format as a medium for communicating scientific results, more than an interactive development environment, Jupyter is turning into an interactive scientific authoring environment.&lt;/p&gt;
</summary><content type="html">&lt;figure&gt;
&lt;img alt="JupyterLab viewing LaTeX source code and a PDF document" src="https://jasongrout.github.io/medium-archive/pelican/posts/2018/a-diagram-editor-for-jupyterlab/images/001-0_SQhbgeWA5hO5_nt7.jpg" loading="lazy" data-body-image=""&gt;
&lt;figcaption&gt;JupyterLab viewing LaTeX source code and a PDF document&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;a href="/posts/2018/jupyterlab-is-ready-for-users/"&gt;The new JupyterLab interface&lt;/a&gt; is much more than a replacement for the classic notebook. It aims to bring together all the pieces required for a complete scientific workflow. The extension-based architecture of JupyterLab comes with a number of components already enabled:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a Jupyter notebook,&lt;/li&gt;
&lt;li&gt;a text editor,&lt;/li&gt;
&lt;li&gt;a file browser in the sidebar,&lt;/li&gt;
&lt;li&gt;a number of editors and viewers for &lt;a href="http://jupyterlab.readthedocs.io/en/stable/user/file_formats.html"&gt;various file formats&lt;/a&gt;,&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;and much more. However, some pieces are still missing to complete the picture for a scientific authoring environment. One would be a featureful LaTeX editor. The &lt;a href="https://github.com/jupyterlab/jupyterlab-latex"&gt;first LaTeX editor for JupyterLab&lt;/a&gt; is a step in the right direction and offers an easy way to live-compile &lt;code&gt;tex&lt;/code&gt; documents. Another piece is — of course — a means to produce diagrams, flow charts and draw figures!&lt;/p&gt;
&lt;h3 id="drawing-charts-and-diagrams"&gt;Drawing charts and diagrams&lt;/h3&gt;
&lt;p&gt;On the occasion of the Paris Jupyter Widgets workshop, I started working on a feature to fill that gap and built a JupyterLab extension for the &lt;a href="http://draw.io"&gt;Draw.io&lt;/a&gt; diagram editor.&lt;/p&gt;
&lt;p&gt;Draw.io is a diagram editor that runs in the web browser and is Apache 2.0 licensed. It’s got a really mature code base, which has been around for many years. However, unlike the other components used by JupyterLab, Draw.io has not yet embraced the new JavaScript packaging tooling such as NPM, which complicated the integration with JupyterLab a little bit, but it all paid off eventually!&lt;/p&gt;
&lt;p&gt;Now, I am really pleased to announce the first release of the draw.io extension, a fully fledged integration for JupyterLab of the fully-fledged diagram editor!&lt;/p&gt;
&lt;iframe src="https://www.youtube-nocookie.com/embed/CJH34I01cKA" title="Screencast: JupyterLab with Drawio Plugin" 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;p&gt;The Draw.io JupyterLab extension takes advantages of the JupyterLab architecture: i.e. registering a new mime type (.dio) with the file explorer to open files, and adding a launcher button and menu items. Besides that, multiple synchronized views of the same diagrams can be displayed at the same time, allowing a user to visualize the same content with different zoom levels, or with a bare text editor.&lt;/p&gt;
&lt;h3 id="installation"&gt;Installation&lt;/h3&gt;
&lt;p&gt;You can install the jupyterlab-drawio extension with the following command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;jupyter labextension install jupyterlab-drawio
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This should set up the extension inside your JupyterLab environment. I hope this will be a useful extension for the larger community. All the code is available on GitHub: &lt;a href="https://github.com/QuantStack/jupyterlab-drawio"&gt;https://github.com/QuantStack/jupyterlab-drawio&lt;/a&gt;. Don’t hesitate to open issues and come contribute to jupyterlab-drawio.&lt;/p&gt;
&lt;h3 id="the-future"&gt;The future&lt;/h3&gt;
&lt;p&gt;There are other projects just waiting to be packaged for use inside of JupyterLab: one great &lt;em&gt;webapp&lt;/em&gt; for JupyterLab would probably be the &lt;a href="https://github.com/sharelatex/sharelatex"&gt;ShareLaTeX&lt;/a&gt; application, which is Open Source as well and provides a very nicely integrated editing experience for LaTeX documents, with autocomplete of LaTeX commands and reference search. Eventually, we might be able to integrate with the official ShareLaTeX server for a collaborative, hosted, editing experience for LaTeX documents from inside JupyterLab.&lt;/p&gt;
&lt;p&gt;Maybe we as a community can come together and start building integrations for these amazing free tools into JupyterLab!&lt;/p&gt;
&lt;p&gt;To conclude, thanks to all who’ve organized and participated in the workshop (especially &lt;a href="https://twitter.com/SylvainCorlay"&gt;Sylvain&lt;/a&gt; for the organization). I’ve used the opportunity to chat with the core developers and get their helpful input: &lt;a href="https://twitter.com/steve_silvester"&gt;Steven&lt;/a&gt;, &lt;a href="http://micronova"&gt;Afshin&lt;/a&gt;, and &lt;a href="https://twitter.com/jason_grout"&gt;Jason&lt;/a&gt;, thanks for helping me out in getting this off the ground and making JupyterLab! And honestly, the biggest shoutout has to go to the people who’ve worked on improving draw.io and thankfully open sourced this &lt;a href="https://github.com/jgraph/mxgraph"&gt;amazing code base&lt;/a&gt;: the entire draw.io team.&lt;/p&gt;
&lt;h3 id="about-the-author"&gt;About the Author&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://twitter.com/wuoulf"&gt;Wolf Vollprecht&lt;/a&gt; is a scientific software developer at &lt;a href="https://twitter.com/QuantStack"&gt;QuantStack&lt;/a&gt;, passionate about High-Performance Computing and Robotics. He is one of the core developers of &lt;a href="https://github.com/QuantStack/xtensor/"&gt;xtensor&lt;/a&gt;.&lt;/p&gt;
</content><category term="JupyterLab"/><category term="visualization"/></entry></feed>